查看种子详细信息用户端和管理员端界面

Change-Id: I29e761d67a1eab741a91feb3f4c686055bb1b382
diff --git a/src/App.css b/src/App.css
new file mode 100644
index 0000000..1766c19
--- /dev/null
+++ b/src/App.css
@@ -0,0 +1,2891 @@
+#root {
+  max-width: 100%;
+  margin: 0;
+  padding: 0;
+}
+
+/* 覆盖默认样式,适配Mantine组件 */
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+.mantine-Image-root {
+  border-radius: 8px;
+}
+
+.logo {
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
+}
+.logo:hover {
+  filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+  filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+  from {
+    transform: rotate(0deg);
+  }
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+  a:nth-of-type(2) .logo {
+    animation: logo-spin infinite 20s linear;
+  }
+}
+
+.card {
+  padding: 2em;
+}
+
+.read-the-docs {
+  color: #888;
+}
+
+.mantine-Card-root {
+  margin-bottom: 1rem;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
diff --git a/src/App.jsx b/src/App.jsx
new file mode 100644
index 0000000..b04728a
--- /dev/null
+++ b/src/App.jsx
@@ -0,0 +1,58 @@
+import React from 'react';
+import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
+import Home from './pages/Home';
+import AdminPage from './pages/AdminPage';
+import TorrentDetail from './components/torrentdetail';
+import TorrentDetailhelp from './components/torrentdetailhelp';
+import TorrentDetailcomplain from './components/torrentdetailcomplain';
+import TorrentList from './components/torrentlist';
+import UploadTorrent from './components/upload';
+import Navbar from './components/Navbar';
+import TorrentDetailmanage from './pages/managetorrentdetail';
+import RecommendAll from './components/RecommendAll';
+import UserAuth from './pages/UserAuth';
+import 'antd/dist/reset.css'; // Ant Design 默认样式
+import './App.css';
+import MainPage from './pages/MainPage';
+import Friend from './pages/Friend';
+import Community from './pages/Community';
+import UserCenter from './pages/UserCenter111';
+import UploadTorrentFull from './components/upload-full';
+import ShopPage from './pages/ShopPage';
+
+// 定义橙色主题(使用 Ant Design 的 orange-6 色值)
+const orangeTheme = {
+  token: {
+    colorPrimary: '#fa8c16', // orange-6
+    borderRadius: 4,         // 可选:圆角大小
+  },
+};
+
+function App() {
+  return (
+    <div className="App">
+      {/* <div className="container mx-auto p-4"> */}
+        <Routes>
+          {/* <Route path="/" element={<Home />} /> */}
+          <Route path="/home" element={<MainPage />} />
+          <Route path="/admin" element={<AdminPage />} />
+          <Route path="/admin/:id" element={<TorrentDetailmanage />} />
+          <Route path="/process/:id" element={<TorrentDetailhelp />} />
+          <Route path="/complain-process/:id" element={<TorrentDetailcomplain />} />
+          <Route path="/torrents" element={<TorrentList />} />
+          <Route path="/upload" element={<UploadTorrent />} />
+          <Route path="/torrent/:id" element={<TorrentDetail />} />
+          <Route path="/recommend" element={<RecommendAll />} />
+          <Route path="/" element={<UserAuth />} />
+          <Route path="/Community" element={<Community />} />
+          <Route path="/friend" element={<Friend />} />
+          <Route path="/usercenter" element={<UserCenter />} />
+          <Route path="/uploadfull/:requestid" element={<UploadTorrentFull/>}/>
+          <Route path="/shop" element={<ShopPage />} />
+        </Routes>
+      {/* </div> */}
+    </div>
+  );
+}
+
+export default App;
\ No newline at end of file
diff --git a/src/Modal.css b/src/Modal.css
new file mode 100644
index 0000000..c37a106
--- /dev/null
+++ b/src/Modal.css
@@ -0,0 +1,118 @@
+/* 模态框遮罩层 */
+.modal-overlay {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background-color: rgba(0, 0, 0, 0.5); /* 半透明黑色背景 */
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  z-index: 1000; /* 确保在最上层 */
+}
+
+/* 模态框内容 */
+.modal-content {
+  background-color: white;
+  border-radius: 12px;
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
+  width: 90%;
+  max-width: 500px; /* 最大宽度 */
+  overflow: hidden;
+  animation: fadeInUp 0.3s ease-out; /* 淡入动画 */
+}
+
+/* 模态框头部 */
+.modal-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 16px 20px;
+  background-color: #e6f0ff; /* 浅蓝色背景 */
+  border-bottom: 1px solid #d0e3ff;
+}
+
+.modal-header h3 {
+  margin: 0;
+  font-size: 18px;
+  font-weight: 600;
+  color: #0066cc; /* 蓝色标题 */
+}
+
+.close-btn {
+  background: none;
+  border: none;
+  font-size: 24px;
+  cursor: pointer;
+  color: #666;
+}
+
+.close-btn:hover {
+  color: #000;
+}
+
+/* 模态框主体 */
+.modal-body {
+  padding: 20px;
+}
+
+.modal-body p {
+  margin: 0;
+  font-size: 16px;
+  color: #333;
+}
+
+.highlight {
+  font-weight: 600;
+  color: #0066cc; /* 蓝色高亮 */
+}
+
+/* 模态框底部 */
+.modal-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 10px;
+  padding: 16px 20px;
+  background-color: #f5f5f5;
+}
+
+/* 按钮样式 */
+.btn-cancel {
+  padding: 8px 16px;
+  border: 1px solid #ccc;
+  background: white;
+  border-radius: 6px;
+  cursor: pointer;
+  transition: all 0.2s;
+}
+
+.btn-cancel:hover {
+  background: #f0f0f0;
+}
+
+.btn-confirm {
+  padding: 8px 16px;
+  background-color: #0066cc; /* 蓝色按钮 */
+  color: white;
+  border: none;
+  border-radius: 6px;
+  cursor: pointer;
+  transition: all 0.2s;
+}
+
+.btn-confirm:hover {
+  background-color: #0052a3; /* 深蓝色 */
+}
+
+/* 动画 */
+@keyframes fadeInUp {
+  from {
+    opacity: 0;
+    transform: translateY(10px);
+  }
+  to {
+    opacity: 1;
+    transform: translateY(0);
+  }
+}
\ No newline at end of file
diff --git a/src/TorrentDetail.css b/src/TorrentDetail.css
new file mode 100644
index 0000000..d854a7c
--- /dev/null
+++ b/src/TorrentDetail.css
@@ -0,0 +1,48 @@
+.page-wrapper {
+  padding: 0px 24px 24px 24px;
+  background-color: #ffffff;
+  min-height: 100vh;
+}
+
+.custom-card {
+  background-color: #fafae7;
+  border: 1px solid #ffd591 !important;
+  border-radius: 12px !important;
+  box-shadow: 0 4px 12px rgba(255, 153, 0, 0.1);
+}
+
+.custom-table .ant-table-thead > tr > th {
+  background-color: #fff1b8 !important;
+  color: #a15c00;
+  font-weight: bold;
+}
+
+.info-card {
+  background-color: #fffefc;
+  border: 1px solid #ffe58f;
+  border-radius: 16px !important;
+  box-shadow: 0 6px 16px rgba(255, 140, 0, 0.15);
+  padding: 24px;
+  transition: box-shadow 0.3s ease;
+}
+
+.info-card:hover {
+  box-shadow: 0 10px 24px rgba(255, 140, 0, 0.25);
+}
+
+.info-title {
+  color: #d46b08;
+  font-weight: 700;
+  margin-bottom: 24px;
+}
+
+.custom-descriptions .ant-descriptions-item-label {
+  background-color: #fff7e6 !important;
+  color: #a15c00 !important;
+  font-size: 16px;
+}
+
+.custom-descriptions .ant-descriptions-item-content {
+  font-size: 15px;
+  color: #595959;
+}
diff --git a/src/__mocks__/axios.js b/src/__mocks__/axios.js
new file mode 100644
index 0000000..1e2caac
--- /dev/null
+++ b/src/__mocks__/axios.js
@@ -0,0 +1,4 @@
+// __mocks__/axios.js
+const axios = jest.createMockFromModule('axios');
+
+export default axios;
\ No newline at end of file
diff --git a/src/components/Torrentdetail.jsx b/src/components/Torrentdetail.jsx
new file mode 100644
index 0000000..a955b7b
--- /dev/null
+++ b/src/components/Torrentdetail.jsx
@@ -0,0 +1,206 @@
+import React, { useEffect, useState } from 'react';
+import { useParams, useNavigate } from 'react-router-dom'; // 添加 useNavigate
+import axios from 'axios';
+import {
+  Row,
+  Col,
+  Card,
+  Descriptions,
+  Table,
+  Typography,
+  Spin,
+  Tag,
+  Button, // 添加 Button 组件
+} from 'antd';
+import { Image as AntdImage } from 'antd';
+import '../TorrentDetail.css'; // 引入样式
+
+const { Title, Text } = Typography;
+
+const TorrentDetail = () => {
+  const { id } = useParams();
+  const navigate = useNavigate(); // 获取导航函数
+  const [torrent, setTorrent] = useState(null);
+  const [seeders, setSeeders] = useState([]);
+  const [loading, setLoading] = useState(true);
+  const [torrentLoading, setTorrentLoading] = useState(true);
+  const [seedersLoading, setSeedersLoading] = useState(false);
+
+  useEffect(() => {
+    const fetchTorrentDetails = async () => {
+      try {
+        setTorrentLoading(true);
+        const torrentRes = await axios.get(`http://localhost:8080/torrent/${id}`);
+        setTorrent(torrentRes.data);
+
+        setSeedersLoading(true);
+        const seedersRes = await axios.get(`http://localhost:8080/torrent/${torrentRes.data.infoHash}/seeders`);
+        setSeeders(seedersRes.data);
+      } catch (err) {
+        console.error('获取数据失败', err);
+      } finally {
+        setTorrentLoading(false);
+        setSeedersLoading(false);
+        setLoading(false);
+      }
+    };
+
+    fetchTorrentDetails();
+  }, [id]);
+
+  const formatSize = (bytes) => {
+    if (bytes === 0) return '0 B';
+    const k = 1024;
+    const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
+    const i = Math.floor(Math.log(bytes) / Math.log(k));
+    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
+  };
+
+  const formatSpeed = (bytesPerSec) => {
+    if (bytesPerSec < 1024) return bytesPerSec.toFixed(2) + ' B/s';
+    if (bytesPerSec < 1024 * 1024) return (bytesPerSec / 1024).toFixed(2) + ' KB/s';
+    return (bytesPerSec / (1024 * 1024)).toFixed(2) + ' MB/s';
+  };
+
+  const columns = [
+    {
+      title: '用户名',
+      dataIndex: 'username',
+      key: 'username',
+      align: 'center',
+      render: (text) => <Tag color="orange">{text}</Tag>,
+    },
+    {
+      title: '已上传',
+      dataIndex: 'uploaded',
+      key: 'uploaded',
+      align: 'center',
+      render: (text) => <Text>{formatSize(text)}</Text>,
+    },
+    {
+      title: '上传速度',
+      dataIndex: 'uploadSpeed',
+      key: 'uploadSpeed',
+      align: 'center',
+      render: (text) => <Text>{formatSpeed(text)}</Text>,
+    },
+    {
+      title: '已下载',
+      dataIndex: 'downloaded',
+      key: 'downloaded',
+      align: 'center',
+      render: (text) => <Text>{formatSize(text)}</Text>,
+    },
+    {
+      title: '下载速度',
+      dataIndex: 'downloadSpeed',
+      key: 'downloadSpeed',
+      align: 'center',
+      render: (text) => text > 0 ? <Text>{formatSpeed(text)}</Text> : <Text>-</Text>,
+    },
+    {
+      title: '客户端',
+      dataIndex: 'client',
+      key: 'client',
+      align: 'center',
+    },
+    {
+      title: '最后活动',
+      dataIndex: 'lastEvent',
+      key: 'lastEvent',
+      align: 'center',
+    },
+  ];
+
+  if (loading) return <div className="page-wrapper"><Spin size="large" /></div>;
+
+  return (
+    <div className="page-wrapper">
+      {/* 添加返回按钮 */}
+      <div className="mb-4">
+        <Button 
+          type="primary" 
+          onClick={() => navigate(-1)} // 返回上一页
+          style={{ marginBottom: '16px' }}
+        >
+          返回列表
+        </Button>
+      </div>
+
+      <Row gutter={[16, 16]}>
+        <Col xs={24} md={8}>
+          <Card bordered={false} className="custom-card h-full">
+            {torrent.coverImagePath ? (
+              <AntdImage
+                src={torrent.coverImagePath}
+                alt="Torrent Cover"
+                className="w-full h-64 object-cover rounded"
+                placeholder={
+                  <div className="w-full h-64 flex items-center justify-center bg-gray-100">
+                    <Spin size="small" />
+                  </div>
+                }
+                preview={false}
+              />
+            ) : (
+              <div className="w-full h-64 flex items-center justify-center bg-gray-100 rounded">
+                <Text type="secondary">无封面图片</Text>
+              </div>
+            )}
+          </Card>
+        </Col>
+
+        <Col xs={24} md={16}>
+          <Card className="info-card">
+            <Title level={1} className="info-title">
+              {torrent?.torrentTitle || '加载中...'}
+            </Title>
+
+            <Descriptions
+              bordered
+              column={{ xs: 1, sm: 2 }}
+              size="middle"
+              className="custom-descriptions"
+              labelStyle={{ fontWeight: 'bold', color: '#a15c00', fontSize: '16px' }}
+              contentStyle={{ fontSize: '15px' }}
+            >
+              <Descriptions.Item label="简介">{torrent.description || '暂无简介'}</Descriptions.Item>
+              <Descriptions.Item label="上传人">{torrent.uploader_id || '未知用户'}</Descriptions.Item>
+              <Descriptions.Item label="上传时间">{new Date(torrent.uploadTime).toLocaleString()}</Descriptions.Item>
+              <Descriptions.Item label="文件大小"><Text>{formatSize(torrent.torrentSize)}</Text></Descriptions.Item>
+              <Descriptions.Item label="下载数"><Text>{torrent.downloadCount || 0}</Text></Descriptions.Item>
+              <Descriptions.Item label="做种数"><Text>{seeders.length}</Text></Descriptions.Item>
+              <Descriptions.Item label="文件分辨率">{torrent.dpi || '未知'}</Descriptions.Item>
+              <Descriptions.Item label="文件字幕">{torrent.caption || '无'}</Descriptions.Item>
+              <Descriptions.Item label="最后做种时间">
+                {torrent.lastseed ? new Date(torrent.lastseed).toLocaleString() : '暂无'}
+              </Descriptions.Item>
+            </Descriptions>
+          </Card>
+        </Col>
+      </Row>
+
+      <Card className="custom-card mt-4">
+        <Title level={4} style={{ color: '#d46b08' }}>当前做种用户 ({seeders.length})</Title>
+        {seedersLoading ? (
+          <div className="p-4 text-center"><Spin size="small" /></div>
+        ) : seeders.length > 0 ? (
+          <Table
+            columns={columns}
+            dataSource={seeders}
+            rowKey={(record, index) => index}
+            pagination={false}
+            size="small"
+            className="custom-table"
+          />
+        ) : (
+          <div className="p-4 text-center text-gray-500 bg-gray-50 rounded">
+            当前没有用户在做种
+          </div>
+        )}
+      </Card>
+    </div>
+  );
+};
+
+export default TorrentDetail;
\ No newline at end of file
diff --git a/src/main.jsx b/src/main.jsx
new file mode 100644
index 0000000..62c9250
--- /dev/null
+++ b/src/main.jsx
@@ -0,0 +1,11 @@
+// src/main.jsx 或 src/index.jsx
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import { BrowserRouter } from 'react-router-dom';
+import App from './App';
+
+ReactDOM.createRoot(document.getElementById('root')).render(
+  <BrowserRouter>
+    <App />
+  </BrowserRouter>
+);
diff --git a/src/pages/managetorrentdetail.jsx b/src/pages/managetorrentdetail.jsx
new file mode 100644
index 0000000..029d06d
--- /dev/null
+++ b/src/pages/managetorrentdetail.jsx
@@ -0,0 +1,287 @@
+import React, { useState, useEffect } from 'react';
+import { useParams, useNavigate } from 'react-router-dom';
+import { 
+   Descriptions,
+  Table, 
+  Button, 
+  Modal, 
+  Image, 
+  message, 
+  Spin, 
+  Input, 
+  Select,
+  Pagination,
+  Space,
+  Card
+} from 'antd';
+import { ExclamationCircleOutlined } from '@ant-design/icons';
+import axios from 'axios';
+import '../torrentdetailmanage.css'; // 引入样式
+
+const { confirm } = Modal;
+const { Option } = Select;
+
+//const { confirm } = Modal;
+
+const TorrentDetailmanage = () => {
+  const { id } = useParams(); // 从URL获取种子ID
+  const navigate = useNavigate(); // 用于返回上一页
+  const [torrent, setTorrent] = useState(null);
+  const [loading, setLoading] = useState(true);
+  const [error, setError] = useState(null);
+  const [isLoading, setIsLoading] = useState(false);
+
+  console.log('Torrent ID:', id);
+
+  const currentUserId = 1; // 示例,实际应从认证系统获取
+  
+
+  // 格式化日期
+  const formatDate = (dateString) => {
+    if (!dateString) return '未知';
+    const date = new Date(dateString);
+    return date.toLocaleString('zh-CN', {
+      year: 'numeric',
+      month: '2-digit',
+      day: '2-digit',
+      hour: '2-digit',
+      minute: '2-digit'
+    });
+  };
+
+  // 处理删除种子
+  const handleDeleteTorrent = async (torrentId) => {
+    if (!currentUserId) {
+      message.warning('请先登录');
+      return;
+    }
+
+    confirm({
+      title: '确认删除',
+      icon: <ExclamationCircleOutlined />,
+      content: '确定要删除这个种子吗?此操作不可恢复!',
+      onOk: async () => {
+        try {
+          await axios.delete(`http://localhost:8080/torrent/delete/${torrentId}`, {
+            params: { userid: currentUserId }
+          });
+          // 成功删除后,更新状态或返回上一页
+          setTorrent(null); // 清空当前种子详情
+          navigate(-1); // 返回上一页
+          message.success('种子删除成功');
+        } catch (err) {
+          console.error('删除种子失败', err);
+          if (err.response && err.response.status === 403) {
+            message.error('无权删除此种子');
+          } else {
+            message.error('删除种子失败');
+          }
+        }
+      }
+    });
+  };
+
+
+const handleDownloadTorrent = async (torrentId) => {
+  if (!currentUserId) {
+    message.warning('请先登录');
+    return;
+  }
+
+  setIsLoading(true); // 开始加载
+  try {
+    // 使用axios发送带有参数的GET请求
+    // const response = await axios.get(`http://localhost:8080/torrent/download/${torrentId}`, {
+    //   params: { userId: currentUserId },  // 正确添加请求参数
+    //   responseType: 'blob'  // 重要:指定响应类型为blob以处理文件下载
+    // });
+
+    // // 创建下载链接
+    // const url = window.URL.createObjectURL(new Blob([response.data]));
+    // const link = document.createElement('a');
+    // link.href = url;
+    // //link.setAttribute('download', 'torrent_file.torrent');  // 可以设置为动态文件名
+    // document.body.appendChild(link);
+    // link.click();
+    // document.body.removeChild(link);
+    // window.URL.revokeObjectURL(url);
+    open(`http://localhost:8080/torrent/download/${torrentId}?userId=${currentUserId}`, '_blank');
+
+    message.success('种子下载开始');
+  } catch (err) {
+    console.error('下载种子失败', err);
+    if (err.response?.status === 404) {
+      message.error('种子不存在');
+    } else {
+      message.error('下载失败: ' + (err.response?.data?.message || err.message));
+    }
+  } finally {
+    setIsLoading(false); // 结束加载
+  }
+};
+
+
+  // 格式化文件大小
+  const formatFileSize = (bytes) => {
+    if (bytes === 0) return '0 Bytes';
+    const k = 1024;
+    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
+    const i = Math.floor(Math.log(bytes) / Math.log(k));
+    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
+  };
+
+  // 在组件函数内部添加这个函数
+const getPromotionName = (promotionId) => {
+  const promotionMap = {
+    1: '上传加倍',
+    2: '下载减半',
+    3: '免费下载',
+    0: '无促销'
+  };
+  
+  return promotionMap[promotionId] || '未知促销';
+};
+
+  // 获取种子详情
+  useEffect(() => {
+    const fetchTorrentDetail = async () => {
+      try {
+        const response = await axios.get(`http://localhost:8080/torrent/${id}`);
+        if (response.status === 200) {
+          setTorrent(response.data);
+        } else {
+          setError('获取种子详情失败');
+        }
+      } catch (err) {
+        console.error('获取种子详情失败:', err);
+        if (err.response) {
+          if (err.response.status === 404) {
+            setError('种子不存在');
+          } else {
+            setError('获取种子详情失败: ' + err.response.data);
+          }
+        } else {
+          setError('网络错误,请稍后重试');
+        }
+      } finally {
+        setLoading(false);
+      }
+    };
+
+    fetchTorrentDetail();
+  }, [id]);
+
+  console.log('Torrent Detail:', torrent);
+
+  // 返回上一页
+  const handleBack = () => {
+    navigate(-1); // 返回上一页
+  };
+
+  // 如果正在加载
+  if (loading) {
+    return (
+      <div className="flex justify-center items-center h-96">
+        <Spin size="large" tip="加载中..." />
+      </div>
+    );
+  }
+
+  // 如果有错误
+  if (error) {
+    return (
+      <div className="p-6">
+        <Card>
+          <div className="text-center p-6">
+            <ExclamationCircleOutlined className="text-2xl text-red-500 mb-4" />
+            <h3 className="text-lg font-medium text-red-600 mb-2">错误</h3>
+            <p className="text-gray-600">{error}</p>
+            <Button type="primary" onClick={handleBack} className="mt-4">
+              返回
+            </Button>
+          </div>
+        </Card>
+      </div>
+    );
+  }
+
+  // 如果种子不存在
+  if (!torrent) {
+    return (
+      <div className="p-6">
+        <Card>
+          <div className="text-center p-6">
+            <ExclamationCircleOutlined className="text-2xl text-yellow-500 mb-4" />
+            <h3 className="text-lg font-medium text-yellow-600 mb-2">种子不存在</h3>
+            <p className="text-gray-600">抱歉,您查找的种子不存在或已被删除。</p>
+            <Button type="primary" onClick={handleBack} className="mt-4">
+              返回
+            </Button>
+          </div>
+        </Card>
+      </div>
+    );
+  }
+
+return (
+  <div className="torrent-detail-page">
+    <Card
+      className="torrent1-card"
+      title={<div className="torrent-title">种子详情</div>}
+      extra={
+        <Button type="primary" onClick={handleBack}>
+          返回列表
+        </Button>
+      }
+    >
+      <Descriptions bordered column={1} size="middle">
+        <Descriptions.Item label="ID">{torrent.torrentid}</Descriptions.Item>
+
+        {torrent.coverImagePath && (
+          <Descriptions.Item label="封面图片">
+            <Image
+              className="torrent-cover-image"
+              src={torrent.coverImagePath}
+              alt="种子封面"
+              width={260}
+              height={160}
+              placeholder={
+                <div className="w-60 h-40 bg-gray-200 flex items-center justify-center">
+                  加载中...
+                </div>
+              }
+            />
+          </Descriptions.Item>
+        )}
+
+        <Descriptions.Item label="文件名">{torrent.filename}</Descriptions.Item>
+        <Descriptions.Item label="大小">{formatFileSize(torrent.torrentSize)}</Descriptions.Item>
+        <Descriptions.Item label="上传者ID">{torrent.uploader_id}</Descriptions.Item>
+        <Descriptions.Item label="上传时间">{formatDate(torrent.uploadTime)}</Descriptions.Item>
+        <Descriptions.Item label="下载次数">{torrent.downloadCount}</Descriptions.Item>
+        <Descriptions.Item label="促销">{getPromotionName(torrent.promotionid)}</Descriptions.Item>
+        <Descriptions.Item label="描述">{torrent.description || '无描述'}</Descriptions.Item>
+      </Descriptions>
+
+      <div className="torrent-buttons">
+        <Button 
+          danger 
+          onClick={() => handleDeleteTorrent(torrent.torrentid)}
+          loading={isLoading}
+        >
+          删除
+        </Button>
+        <Button 
+          type="primary" 
+          onClick={() => handleDownloadTorrent(torrent.torrentid)}
+          loading={isLoading}
+        >
+          下载
+        </Button>
+      </div>
+    </Card>
+  </div>
+);
+};
+
+export default TorrentDetailmanage;
\ No newline at end of file
diff --git a/src/test/TorrentDetail.test.jsx b/src/test/TorrentDetail.test.jsx
new file mode 100644
index 0000000..a540a81
--- /dev/null
+++ b/src/test/TorrentDetail.test.jsx
@@ -0,0 +1,91 @@
+import React from 'react';
+import { render, screen, waitFor } from '@testing-library/react';
+import { MemoryRouter, Route, Routes } from 'react-router-dom';
+import axios from 'axios';
+import TorrentDetail from '../components/Torrentdetail';
+import { vi } from 'vitest';
+
+
+beforeAll(() => {
+  Object.defineProperty(window, 'matchMedia', {
+    writable: true,
+    value: vi.fn().mockImplementation((query) => ({
+      matches: false,
+      media: query,
+      onchange: null,
+      addListener: vi.fn(),
+      removeListener: vi.fn(),
+      addEventListener: vi.fn(),
+      removeEventListener: vi.fn(),
+      dispatchEvent: vi.fn(),
+    })),
+  });
+});
+
+
+// 模拟 axios
+vi.mock('axios');
+
+describe('TorrentDetail Page', () => {
+  const mockTorrent = {
+    torrentTitle: '测试种子',
+    uploader_id: 'uploader123',
+    description: '这是一个测试种子描述',
+    uploadTime: '2024-06-01T12:00:00Z',
+    torrentSize: 104857600,
+    downloadCount: 10,
+    dpi: '1080p',
+    caption: '简体中文',
+    lastseed: '2024-06-05T14:00:00Z',
+    coverImagePath: 'http://example.com/cover.jpg',
+    infoHash: 'abc123'
+  };
+
+  const mockSeeders = [
+    {
+      username: 'Seeder1',
+      uploaded: 204857600,
+      uploadSpeed: 1048576,
+      downloaded: 102400,
+      downloadSpeed: 0,
+      client: 'qBittorrent',
+      lastEvent: '2024-06-06T11:22:00Z'
+    }
+  ];
+
+  beforeEach(() => {
+    axios.get.mockImplementation((url) => {
+      if (url.includes('/torrent/abc123/seeders')) {
+        return Promise.resolve({ data: mockSeeders });
+      }
+      if (url.includes('/torrent/123')) {
+        return Promise.resolve({ data: mockTorrent });
+      }
+      return Promise.reject(new Error('not found'));
+    });
+  });
+
+  afterEach(() => {
+    vi.clearAllMocks();
+  });
+
+  test('renders torrent detail and seeders correctly', async () => {
+    render(
+      <MemoryRouter initialEntries={['/torrent/123']}>
+        <Routes>
+          <Route path="/torrent/:id" element={<TorrentDetail />} />
+        </Routes>
+      </MemoryRouter>
+    );
+
+    expect(document.querySelector('.ant-spin')).toBeInTheDocument();
+
+
+    await waitFor(() => {
+      expect(screen.getByText('测试种子')).toBeInTheDocument();
+      expect(screen.getByText('uploader123')).toBeInTheDocument();
+      expect(screen.getByText(/1080p/)).toBeInTheDocument();
+      expect(screen.getByText('Seeder1')).toBeInTheDocument();
+    });
+  });
+});
diff --git a/src/test/setup.js b/src/test/setup.js
new file mode 100644
index 0000000..43c149b
--- /dev/null
+++ b/src/test/setup.js
@@ -0,0 +1,2 @@
+// src/test/setup.js
+import '@testing-library/jest-dom';
diff --git a/src/torrentdetailmanage.css b/src/torrentdetailmanage.css
new file mode 100644
index 0000000..b38cf6d
--- /dev/null
+++ b/src/torrentdetailmanage.css
@@ -0,0 +1,53 @@
+/* TorrentDetail.css */
+
+body, html, #root {
+  margin: 0;
+  padding: 0;
+  height: 100%;
+  background-color: #f4f6f9;
+  font-family: 'Segoe UI', 'Roboto', 'Helvetica Neue', sans-serif;
+}
+
+.torrent-detail-page {
+  min-height: 100vh;
+  padding: 32px 48px;
+  background-color: #f4f6f9;
+  box-sizing: border-box;
+}
+
+.torrent1-card {
+  width: 100%;
+  max-width: 1080px;
+  min-width: 1000px; /* 确保不会太窄 */
+  margin: 0 auto;
+  border-radius: 16px;
+  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
+  border: none;
+  background: #fff;
+  padding: 32px;
+}
+
+.torrent-title {
+  font-size: 28px;
+  font-weight: 600;
+  color: #d46b08;
+  margin-bottom: 20px;
+}
+
+.torrent-cover-image {
+  border-radius: 12px;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
+  border: 1px solid #eee;
+}
+
+.torrent-buttons {
+  margin-top: 32px;
+  display: flex;
+  justify-content: flex-end;
+  gap: 20px;
+}
+
+.torrent-buttons .ant-btn {
+  font-size: 16px;
+  padding: 10px 28px;
+}
diff --git a/src/torrentlist.css b/src/torrentlist.css
new file mode 100644
index 0000000..b6fa9d1
--- /dev/null
+++ b/src/torrentlist.css
@@ -0,0 +1,168 @@
+/* 加载状态 */
+.loading-container {
+  height: 16rem; /* 64 x 4 */
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.spinner {
+  border: 4px solid #f3f3f3;
+  border-top: 4px solid #f59e0b; /* 橙黄色 */
+  border-radius: 50%;
+  width: 48px;
+  height: 48px;
+  animation: spin 1s linear infinite;
+}
+
+@keyframes spin {
+  to { transform: rotate(360deg); }
+}
+
+/* 容器和网格 */
+.torrents-container {
+  padding: 16px;
+  background-color: #f9fafb;
+  min-height: 100vh;
+}
+
+.torrents-grid {
+  display: grid;
+  /* grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));   */
+  grid-template-columns: repeat(4, 1fr); /* 固定每行4列 */
+  gap: 24px;
+}
+
+.torrents1-grid {
+  display: grid;
+  grid-template-columns: repeat(4, 1fr); /* 固定每行4列 */
+  gap: 24px;
+}
+
+
+/* 卡片样式 */
+.torrent-card {
+  background-color: white;
+  border-radius: 8px;
+  box-shadow: 0 2px 8px rgb(0 0 0 / 0.1);
+  display: flex;
+  flex-direction: column;
+  overflow: hidden;
+  transition: box-shadow 0.3s ease;
+}
+
+.torrent-card:hover {
+  box-shadow: 0 6px 16px rgb(0 0 0 / 0.15);
+}
+
+/* 封面区域 */
+.cover {
+  height: 160px;
+  overflow: hidden;
+  background-color: #e5e7eb;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.cover-image {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+}
+
+.no-cover {
+  color: #9ca3af;
+  font-size: 14px;
+}
+
+/* 信息区域 */
+.info {
+  padding: 16px;
+  flex-grow: 1;
+  display: flex;
+  flex-direction: column;
+}
+
+.title {
+  font-size: 18px;
+  font-weight: 600;
+  color: #d97706; /* 橙色 */
+  margin: 0 0 6px 0;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.description {
+  font-size: 14px;
+  color: #6b7280;
+  margin: 0 0 12px 0;
+  height: 36px; /* 限制两行高度 */
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.details {
+  font-size: 12px;
+  color: #6b7280;
+  display: flex;
+  flex-wrap: wrap;
+  gap: 8px;
+  margin-bottom: 16px;
+}
+
+.details span {
+  white-space: nowrap;
+}
+
+/* 操作按钮 */
+.actions {
+  margin-top: auto;
+  display: flex;
+  gap: 12px;
+}
+
+.btn {
+  flex: 1;
+  padding: 8px 12px;
+  border-radius: 6px;
+  font-size: 14px;
+  font-weight: 600;
+  cursor: pointer;
+  text-align: center;
+  text-decoration: none;
+  user-select: none;
+  transition: background-color 0.3s ease;
+  border: none;
+}
+
+.btn-download {
+  background-color: #f97316; /* 明亮橙色 */
+  color: white;
+}
+
+.btn-download:hover {
+  background-color: #ea580c; /* 深橙 */
+}
+
+.btn-detail {
+  background-color: #e5e7eb;
+  color: #374151;
+  display: inline-flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.btn-detail:hover {
+  background-color: #d1d5db;
+}
+
+/* 没有数据提示 */
+.no-data {
+  text-align: center;
+  color: #6b7280;
+  font-size: 18px;
+  margin-top: 80px;
+}
+
diff --git a/src/upload.css b/src/upload.css
new file mode 100644
index 0000000..3e35e89
--- /dev/null
+++ b/src/upload.css
@@ -0,0 +1,151 @@
+
+
+  /* 表单组样式 */
+  .form-group {
+    margin-bottom: 1rem;
+  }
+  
+  .form-label {
+    display: block;
+    margin-bottom: 0.5rem;
+    font-weight: 500;
+  }
+  
+  .form-control {
+    width: 100%;
+    padding: 0.5rem;
+    border: 1px solid #ddd;
+    border-radius: 4px;
+    transition: border-color 0.3s;
+  }
+  
+  .form-control:focus {
+    outline: none;
+    border-color: #ff8c00;
+    box-shadow: 0 0 0 3px rgba(255, 140, 0, 0.2);
+  }
+  
+  /* 提交按钮样式 */
+  .submit-btn {
+    background-color: #ff8c00;
+    color: white;
+    padding: 0.5rem 1rem;
+    border: none;
+    border-radius: 4px;
+    cursor: pointer;
+    font-weight: 500;
+    transition: background-color 0.3s;
+  }
+  
+  .submit-btn:hover {
+    background-color: #ff7f00;
+  }
+  
+  /* 成功消息样式 */
+  .success-message {
+    margin-top: 1rem;
+    padding: 0.75rem;
+    background-color: #fff3cd;
+    color: #856404;
+    border: 1px solid #ffeeba;
+    border-radius: 4px;
+  }
+
+  /* 表单组样式 */
+  .form-group {
+    margin-bottom: 1.5rem;
+  }
+  
+  .form-label {
+    display: block;
+    margin-bottom: 0.5rem;
+    font-weight: 500;
+  }
+  
+  .form-control {
+    width: 100%;
+    padding: 0.75rem;
+    border: 1px solid #ddd;
+    border-radius: 8px;
+    transition: border-color 0.3s;
+    font-size: 1rem;
+  }
+  
+  .form-control:focus {
+    outline: none;
+    border-color: #ff8c00;
+    box-shadow: 0 0 0 3px rgba(255, 140, 0, 0.2);
+  }
+  
+  /* 上传区域样式 */
+  .upload-area {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    transition: all 0.3s;
+  }
+  
+  .upload-area:hover {
+    background-color: rgba(255, 140, 0, 0.05);
+  }
+  
+  /* 自定义下拉框样式 */
+  .custom-select {
+    width: 100%;
+    padding: 0.75rem 2.5rem 0.75rem 1rem;
+    border: 1px solid #ddd;
+    border-radius: 8px;
+    appearance: none;
+    background-color: white;
+    font-size: 1rem;
+    cursor: pointer;
+    transition: border-color 0.3s;
+  }
+  
+  .custom-select:focus {
+    outline: none;
+    border-color: #ff8c00;
+    box-shadow: 0 0 0 3px rgba(255, 140, 0, 0.2);
+  }
+  
+  .select-arrow {
+    position: absolute;
+    right: 1rem;
+    top: 50%;
+    transform: translateY(-50%);
+    pointer-events: none;
+  }
+  
+  /* 提交按钮样式 */
+  .submit-btn {
+    background-color: #ff8c00;
+    color: white;
+    padding: 0.75rem 2rem;
+    border: none;
+    border-radius: 8px;
+    cursor: pointer;
+    font-weight: 600;
+    font-size: 1rem;
+    transition: background-color 0.3s;
+    display: inline-block;
+  }
+  
+  .submit-btn:hover {
+    background-color: #ff7f00;
+  }
+  
+  /* 成功消息样式 */
+  .success-message {
+    margin-top: 1.5rem;
+    padding: 0.75rem 1.5rem;
+    background-color: #fff3cd;
+    color: #856404;
+    border: 1px solid #ffeeba;
+    border-radius: 8px;
+  }
+  
+  /* 居中布局 */
+  .text-center {
+    text-align: center;
+  }
diff --git a/src/uploadtorrent.css b/src/uploadtorrent.css
new file mode 100644
index 0000000..213336c
--- /dev/null
+++ b/src/uploadtorrent.css
@@ -0,0 +1,95 @@
+/* UploadTorrent.css */
+.container {
+  min-height: 100vh;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding: 10px;
+}
+
+.card {
+  width: 100%;
+  max-width: 1000px;;
+  min-width: 800px;  /* 最小宽度 800px(确保不会太窄) */
+  margin: 0 auto;
+  padding: 20px;
+  background-color: #fff;
+  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+  border-radius: 8px;
+}
+
+.title {
+  text-align: center;
+  font-size: 1.5rem;
+  font-weight: bold;
+  color: #ff8c00;
+  margin-bottom: 20px;
+  padding-bottom: 10px;
+  border-bottom: 2px solid #ffe0b2;
+}
+
+.form {
+  display: flex;
+  flex-direction: column;
+  gap: 15px;
+}
+
+.uploadArea {
+  text-align: center;
+  padding: 20px;
+  border: 2px dashed #ffe0b2;
+  border-radius: 8px;
+  cursor: pointer;
+  transition: border-color 0.3s;
+}
+
+.uploadArea:hover {
+  border-color: #ff8c00;
+}
+
+.uploadIcon {
+  color: #ffe0b2;
+  font-size: 2rem;
+}
+
+.uploadText {
+  margin-top: 10px;
+  font-size: 0.8rem;
+  color: #666;
+}
+
+.hiddenInput {
+  display: none;
+}
+
+.input {
+  width: 100%;
+  text-align: center;
+}
+
+.textArea {
+  width: 100%;
+  text-align: center;
+}
+
+.select {
+  width: 100%;
+}
+
+.submitButton {
+  width: 100%;
+  background-color: #ff8c00;
+  border-color: #ff8c00;
+}
+
+.submitButton:hover {
+  background-color: #ff7f00;
+  border-color: #ff7f00;
+}
+
+.successMessage {
+  text-align: center;
+  color: green;
+  font-weight: bold;
+  margin-top: 10px;
+}