Refresh the homepage and improve export and draft guidance
This commit is contained in:
918
app/block-theme.css
Normal file
918
app/block-theme.css
Normal file
@@ -0,0 +1,918 @@
|
||||
@font-face {
|
||||
font-family: MineGeoPixel;
|
||||
src: url("/fonts/VT323-Regular.ttf") format("truetype");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
:root {
|
||||
--bg: #080c12;
|
||||
--panel: #121b26;
|
||||
--panel2: #192430;
|
||||
--line: #2c3743;
|
||||
--green: #86ce56;
|
||||
--muted: #99a5ae;
|
||||
--text: #edf1f4;
|
||||
--sand: #dcc197;
|
||||
}
|
||||
body {
|
||||
background-color: var(--bg);
|
||||
background-image: radial-gradient(
|
||||
ellipse at 75% 8%,
|
||||
#18202b66,
|
||||
transparent 52%
|
||||
);
|
||||
color: var(--text);
|
||||
}
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
.brand,
|
||||
.button,
|
||||
.header-account,
|
||||
.site-header nav,
|
||||
.world-stats strong {
|
||||
font-family: MineGeoPixel, "Courier New", monospace;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
text-shadow: 2px 2px 0 #0008;
|
||||
}
|
||||
h1 {
|
||||
font-size: 64px;
|
||||
}
|
||||
h2 {
|
||||
font-size: 40px;
|
||||
}
|
||||
h3 {
|
||||
font-size: 28px;
|
||||
}
|
||||
.button {
|
||||
border: 2px solid #4b5965;
|
||||
border-bottom: 4px solid #03070b;
|
||||
box-shadow:
|
||||
inset 2px 2px #ffffff15,
|
||||
3px 3px 0 #0008;
|
||||
background: #25313c;
|
||||
font-size: 23px;
|
||||
padding: 7px 20px;
|
||||
line-height: 1.2;
|
||||
border-radius: 0;
|
||||
}
|
||||
.button.primary {
|
||||
color: #10240b;
|
||||
background: linear-gradient(#94df61, #5da732);
|
||||
border: 2px solid #afd98b;
|
||||
border-bottom: 4px solid #294b17;
|
||||
box-shadow:
|
||||
inset 2px 2px #d7ffb066,
|
||||
0 3px 0 #050904;
|
||||
font-weight: 400;
|
||||
text-shadow: 1px 1px #d7ffa555;
|
||||
}
|
||||
.button.primary:hover {
|
||||
background: linear-gradient(#acf77a, #76bd4b);
|
||||
}
|
||||
.button:hover {
|
||||
transform: translateY(-2px);
|
||||
background-color: #334552;
|
||||
}
|
||||
.button:active {
|
||||
transform: translateY(1px);
|
||||
}
|
||||
.site-header {
|
||||
height: 68px;
|
||||
background: #090e16ed;
|
||||
border-bottom: 2px solid #222b37;
|
||||
box-shadow: 0 3px #03070b;
|
||||
}
|
||||
.header-inner,
|
||||
.section,
|
||||
.site-footer {
|
||||
max-width: 1160px;
|
||||
}
|
||||
.header-inner {
|
||||
padding: 0 28px;
|
||||
gap: 24px;
|
||||
}
|
||||
.brand {
|
||||
font-size: 34px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.brand-cube {
|
||||
transform: none;
|
||||
box-shadow: 3px 3px #000;
|
||||
border: 1px solid #748952;
|
||||
border-bottom: 11px solid #785033;
|
||||
background: repeating-linear-gradient(90deg, #6faf3f 0 7px, #81c64b 7px 14px);
|
||||
width: 27px;
|
||||
height: 29px;
|
||||
}
|
||||
.brand sup {
|
||||
font-size: 8px;
|
||||
margin-top: -10px;
|
||||
}
|
||||
.site-header nav {
|
||||
font-size: 23px;
|
||||
gap: 25px;
|
||||
}
|
||||
.header-account {
|
||||
font-size: 21px;
|
||||
padding: 5px 13px;
|
||||
border: 2px solid #9f87c3;
|
||||
border-bottom: 4px solid #45325f;
|
||||
background: linear-gradient(#8560b2, #694890);
|
||||
box-shadow: inset 2px 2px #ffffff20;
|
||||
color: #fff;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.home-page {
|
||||
position: relative;
|
||||
background-image:
|
||||
radial-gradient(#9dabb332 1px, transparent 2px),
|
||||
radial-gradient(#9dabb318 1px, transparent 2px);
|
||||
background-size:
|
||||
103px 89px,
|
||||
179px 151px;
|
||||
background-position:
|
||||
18px 8px,
|
||||
62px 40px;
|
||||
}
|
||||
.hero {
|
||||
max-width: 1160px;
|
||||
min-height: 394px;
|
||||
padding: 44px 28px 46px;
|
||||
grid-template-columns: 1.3fr 1fr;
|
||||
gap: 35px;
|
||||
overflow: visible;
|
||||
}
|
||||
.hero h1 {
|
||||
font-size: clamp(44px, 4.7vw, 66px);
|
||||
line-height: 0.97;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
.hero h1 span {
|
||||
color: #87c855;
|
||||
text-shadow: 3px 3px #23421d;
|
||||
}
|
||||
.hero p {
|
||||
font-size: 14px;
|
||||
line-height: 1.7;
|
||||
color: #a6afb8;
|
||||
margin-bottom: 19px;
|
||||
}
|
||||
.status-label {
|
||||
font-size: 10px;
|
||||
border: 1px solid #2b3541;
|
||||
background: #111822;
|
||||
display: inline-flex;
|
||||
padding: 3px 8px;
|
||||
margin-bottom: 15px;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
.hero-actions {
|
||||
margin-top: 19px;
|
||||
gap: 16px;
|
||||
}
|
||||
.hero-mode-note {
|
||||
font-size: 11px;
|
||||
color: #94a0aa;
|
||||
}
|
||||
.hero-notes {
|
||||
margin-top: 20px;
|
||||
align-items: center;
|
||||
color: #9ba6af;
|
||||
font-size: 11px;
|
||||
}
|
||||
.mode-dots {
|
||||
display: flex;
|
||||
gap: 9px !important;
|
||||
}
|
||||
.mode-dots i {
|
||||
display: block;
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
background: #6cab43;
|
||||
border: 2px solid #a1c875;
|
||||
box-shadow: 2px 2px #000;
|
||||
}
|
||||
.mode-dots i:nth-child(2) {
|
||||
background: #cca34c;
|
||||
border-color: #e7c47b;
|
||||
}
|
||||
.mode-dots i:nth-child(3) {
|
||||
background: #4786b8;
|
||||
border-color: #88b1d1;
|
||||
}
|
||||
.mode-dots i:nth-child(4) {
|
||||
background: #b64d5b;
|
||||
border-color: #df7d89;
|
||||
}
|
||||
.hero-art {
|
||||
min-height: 300px;
|
||||
margin: 0;
|
||||
}
|
||||
.map-art-frame {
|
||||
width: 277px;
|
||||
height: 277px;
|
||||
transform: rotate(-5deg);
|
||||
border: 12px solid var(--sand);
|
||||
box-shadow:
|
||||
0 0 0 4px #81684a,
|
||||
8px 8px 0 #0009;
|
||||
clip-path: polygon(
|
||||
0 3%,
|
||||
5% 3%,
|
||||
5% 0,
|
||||
22% 0,
|
||||
22% 2%,
|
||||
43% 2%,
|
||||
43% 0,
|
||||
65% 0,
|
||||
65% 2%,
|
||||
89% 2%,
|
||||
89% 0,
|
||||
97% 0,
|
||||
97% 7%,
|
||||
100% 7%,
|
||||
100% 27%,
|
||||
98% 27%,
|
||||
98% 71%,
|
||||
100% 71%,
|
||||
100% 95%,
|
||||
95% 95%,
|
||||
95% 100%,
|
||||
70% 100%,
|
||||
70% 98%,
|
||||
30% 98%,
|
||||
30% 100%,
|
||||
3% 100%,
|
||||
3% 93%,
|
||||
0 93%
|
||||
);
|
||||
}
|
||||
.square-pin {
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 3px solid #16231b;
|
||||
box-shadow: 2px 2px #0008;
|
||||
}
|
||||
.pin-green {
|
||||
top: 65%;
|
||||
left: 30%;
|
||||
background: #60c8a0;
|
||||
}
|
||||
.pin-red {
|
||||
top: 40%;
|
||||
left: 56%;
|
||||
background: #cd5367;
|
||||
}
|
||||
.pin-gold {
|
||||
top: 20%;
|
||||
left: 70%;
|
||||
background: #e4b851;
|
||||
}
|
||||
.compass-art {
|
||||
right: 12%;
|
||||
top: 0;
|
||||
transform: none;
|
||||
border: 2px solid #535e68;
|
||||
background: linear-gradient(135deg, #26313e, #080d16);
|
||||
box-shadow:
|
||||
inset 3px 3px #ffffff0c,
|
||||
4px 4px #0008;
|
||||
width: 66px;
|
||||
height: 70px;
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #d5dade;
|
||||
}
|
||||
.compass-art small {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 27px;
|
||||
font: 10px monospace;
|
||||
color: #dd6270;
|
||||
}
|
||||
.floating-tag {
|
||||
bottom: 0;
|
||||
right: auto;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
white-space: nowrap;
|
||||
padding: 6px 10px;
|
||||
background: #0d151f;
|
||||
border: 2px solid #273240;
|
||||
display: flex;
|
||||
gap: 9px;
|
||||
font: 11px monospace;
|
||||
color: #b8c1c9;
|
||||
}
|
||||
.floating-tag strong {
|
||||
color: #eff2f5;
|
||||
}
|
||||
.floating-tag svg {
|
||||
color: #ce5367;
|
||||
}
|
||||
.grass-divider {
|
||||
height: 23px;
|
||||
background: repeating-linear-gradient(
|
||||
90deg,
|
||||
#5d422c 0 8px,
|
||||
#513827 8px 16px,
|
||||
#624731 16px 24px
|
||||
);
|
||||
border-top: 5px solid #578b30;
|
||||
border-bottom: 3px solid #332419;
|
||||
box-shadow: 0 -2px #8db85a;
|
||||
}
|
||||
.grass-divider span {
|
||||
display: block;
|
||||
height: 6px;
|
||||
background: repeating-linear-gradient(
|
||||
90deg,
|
||||
#427329 0 13px,
|
||||
transparent 13px 19px,
|
||||
#355d21 19px 26px
|
||||
);
|
||||
}
|
||||
.world-stats {
|
||||
position: relative;
|
||||
max-width: 1104px;
|
||||
margin: -3px auto 0;
|
||||
background: #131d29;
|
||||
border: 2px solid #303b46;
|
||||
border-top: 0;
|
||||
box-shadow: 4px 4px #0008;
|
||||
padding: 19px 28px;
|
||||
gap: 20px;
|
||||
}
|
||||
.world-stats > div {
|
||||
gap: 13px;
|
||||
border-right: 1px solid #2e3743;
|
||||
}
|
||||
.world-stats > div:last-child {
|
||||
border: 0;
|
||||
}
|
||||
.world-stats > div > div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
}
|
||||
.world-stats strong {
|
||||
font-size: 32px;
|
||||
line-height: 0.95;
|
||||
color: #f0f2f5;
|
||||
}
|
||||
.world-stats span:not(.live-dot) {
|
||||
font-size: 8px;
|
||||
letter-spacing: 0.3px;
|
||||
max-width: none;
|
||||
color: #929eac;
|
||||
}
|
||||
.stat-cube {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
border: 2px solid #b5d99b;
|
||||
box-shadow:
|
||||
inset 3px 3px #ffffff25,
|
||||
3px 3px #000a;
|
||||
}
|
||||
.green-cube {
|
||||
background: linear-gradient(#8ccb55, #4b8f31);
|
||||
}
|
||||
.gold-cube {
|
||||
background: linear-gradient(#ebcc65, #b78a32);
|
||||
border-color: #f0d797;
|
||||
}
|
||||
.cyan-cube {
|
||||
background: linear-gradient(#73c6c3, #378f91);
|
||||
border-color: #a5dfd8;
|
||||
}
|
||||
.red-cube {
|
||||
background: linear-gradient(#d97988, #a73d52);
|
||||
border-color: #e8a5af;
|
||||
}
|
||||
.section {
|
||||
padding: 48px 28px;
|
||||
}
|
||||
.section-heading {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.section-heading h2 {
|
||||
font-size: 38px;
|
||||
}
|
||||
.eyebrow {
|
||||
font:
|
||||
11px/1.4 "Courier New",
|
||||
monospace;
|
||||
letter-spacing: 0.5px;
|
||||
margin-bottom: 5px;
|
||||
color: #9ec581;
|
||||
}
|
||||
.text-link {
|
||||
font-size: 12px;
|
||||
color: #b4c0ca;
|
||||
}
|
||||
.cards-grid {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
.map-card {
|
||||
border: 2px solid #303c49;
|
||||
background: #141e2b;
|
||||
box-shadow: 3px 3px #0008;
|
||||
}
|
||||
.map-card:hover {
|
||||
border-color: #83ab5f;
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
.card-image {
|
||||
height: auto;
|
||||
aspect-ratio: 1;
|
||||
margin: 24px 11px 12px;
|
||||
border: 9px solid #d2b98d;
|
||||
outline: 2px solid #876e4f;
|
||||
overflow: visible;
|
||||
box-shadow: 3px 3px #0007;
|
||||
}
|
||||
.card-type {
|
||||
top: -28px;
|
||||
left: -9px;
|
||||
border: 0;
|
||||
background: #080c12;
|
||||
padding: 1px 4px;
|
||||
color: #d1d9de;
|
||||
letter-spacing: 0;
|
||||
font: 10px monospace;
|
||||
}
|
||||
.card-number {
|
||||
display: none;
|
||||
}
|
||||
.card-body {
|
||||
padding: 12px;
|
||||
background: #17212f;
|
||||
border-top: 1px solid #303a45;
|
||||
}
|
||||
.card-body .eyebrow {
|
||||
font-size: 8px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.card-body h3 {
|
||||
font-size: 26px;
|
||||
line-height: 1;
|
||||
margin-bottom: 7px;
|
||||
gap: 6px;
|
||||
}
|
||||
.card-body h3 svg {
|
||||
width: 14px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.card-body p {
|
||||
font-size: 11px;
|
||||
line-height: 1.5;
|
||||
color: #a3adb8;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
min-height: 33px;
|
||||
}
|
||||
.card-meta {
|
||||
font-size: 9px;
|
||||
padding-top: 9px;
|
||||
color: #9ba9b7;
|
||||
border-color: #35414d;
|
||||
gap: 5px;
|
||||
}
|
||||
.first-map-panel {
|
||||
display: grid;
|
||||
grid-template-columns: 210px 1fr;
|
||||
gap: 36px;
|
||||
align-items: center;
|
||||
border: 2px solid #2d3b47;
|
||||
background: #111a26;
|
||||
padding: 24px;
|
||||
box-shadow: 5px 5px #0007;
|
||||
}
|
||||
.first-map-panel h3 {
|
||||
font-size: 35px;
|
||||
margin-bottom: 9px;
|
||||
}
|
||||
.first-map-panel p {
|
||||
color: #a4aeb9;
|
||||
max-width: 620px;
|
||||
font-size: 13px;
|
||||
}
|
||||
.empty-map-art {
|
||||
position: relative;
|
||||
border: 10px solid #d4bc91;
|
||||
box-shadow: 3px 3px #7b6040;
|
||||
transform: rotate(-3deg);
|
||||
}
|
||||
.empty-map-art img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
image-rendering: pixelated;
|
||||
filter: saturate(0.65);
|
||||
}
|
||||
.empty-map-art span {
|
||||
position: absolute;
|
||||
bottom: 12px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
white-space: nowrap;
|
||||
padding: 4px 7px;
|
||||
background: #090d17dd;
|
||||
font: 11px monospace;
|
||||
color: #f5dfb4;
|
||||
}
|
||||
.home-panels {
|
||||
display: grid;
|
||||
grid-template-columns: 1.2fr 1fr;
|
||||
gap: 20px;
|
||||
padding-top: 0;
|
||||
}
|
||||
.home-panel {
|
||||
background: linear-gradient(135deg, #17222e, #101923);
|
||||
border: 2px solid #2e3a48;
|
||||
padding: 24px;
|
||||
box-shadow: 4px 4px #0007;
|
||||
}
|
||||
.home-panel h2 {
|
||||
font-size: 36px;
|
||||
margin-bottom: 22px;
|
||||
}
|
||||
.play-steps {
|
||||
list-style: none;
|
||||
margin: 0 0 20px;
|
||||
padding: 0;
|
||||
display: grid;
|
||||
gap: 18px;
|
||||
}
|
||||
.play-steps li {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.play-steps li > span {
|
||||
font: 24px MineGeoPixel;
|
||||
color: #9bbb7d;
|
||||
background: #202d23;
|
||||
border: 1px solid #43553a;
|
||||
padding: 0 6px;
|
||||
}
|
||||
.play-steps h3 {
|
||||
font-size: 25px;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
.play-steps p,
|
||||
.mode-row p {
|
||||
font-size: 12px;
|
||||
color: #a4afb9;
|
||||
margin: 0;
|
||||
}
|
||||
.mode-list {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
.mode-row {
|
||||
display: flex;
|
||||
gap: 13px;
|
||||
align-items: center;
|
||||
border: 2px solid #384651;
|
||||
background: #192430;
|
||||
padding: 12px;
|
||||
}
|
||||
.mode-row:hover {
|
||||
border-color: #84b459;
|
||||
}
|
||||
.mode-row > div {
|
||||
flex: 1;
|
||||
}
|
||||
.mode-row h3 {
|
||||
font-size: 25px;
|
||||
margin: 0 0 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
}
|
||||
.mode-row h3 span {
|
||||
font: 10px monospace;
|
||||
color: #acb9c3;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.mode-footnote {
|
||||
font-size: 11px;
|
||||
color: #899ca9;
|
||||
margin: 16px 0 0;
|
||||
}
|
||||
.contribute-banner {
|
||||
max-width: 1104px;
|
||||
padding: 25px 28px;
|
||||
margin-bottom: 48px;
|
||||
background: #131e24;
|
||||
border: 2px solid #3a5233;
|
||||
gap: 22px;
|
||||
}
|
||||
.contribute-banner > div {
|
||||
flex: 1;
|
||||
}
|
||||
.contribute-banner h2 {
|
||||
font-size: 33px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.contribute-banner > svg {
|
||||
color: var(--green);
|
||||
}
|
||||
.site-footer {
|
||||
border-color: #263440;
|
||||
}
|
||||
.site-footer .brand {
|
||||
font-size: 29px;
|
||||
}
|
||||
.site-footer p,
|
||||
.site-footer > div:nth-child(2) {
|
||||
color: #91a0ad;
|
||||
}
|
||||
.tool-card,
|
||||
.start-panel,
|
||||
.auth-card,
|
||||
.draft-row,
|
||||
.token-box,
|
||||
.result-summary,
|
||||
.round-result {
|
||||
background: var(--panel);
|
||||
border: 2px solid var(--line);
|
||||
box-shadow: 4px 4px #0007;
|
||||
}
|
||||
.badge {
|
||||
border-color: #485b3f;
|
||||
background: #1d2c22;
|
||||
color: #a9cf8d;
|
||||
}
|
||||
.empty-state {
|
||||
background: #111b25;
|
||||
border-color: #43525d;
|
||||
}
|
||||
.field input,
|
||||
.field textarea,
|
||||
.search-field {
|
||||
background: #0b121b;
|
||||
border-color: #3c4a56;
|
||||
}
|
||||
.difficulty-options button {
|
||||
background: #17232d;
|
||||
}
|
||||
.difficulty-options button.selected {
|
||||
background: #223522;
|
||||
}
|
||||
.draft-row h3 {
|
||||
font-size: 27px;
|
||||
}
|
||||
.game-info {
|
||||
background: #111b27e8;
|
||||
}
|
||||
.game-map {
|
||||
background: #111b27;
|
||||
border: 3px solid #576147;
|
||||
}
|
||||
.round-result {
|
||||
background: #111b27f5;
|
||||
}
|
||||
.page-content h1 {
|
||||
font-size: 58px;
|
||||
}
|
||||
.header-inner .mobile-nav {
|
||||
display: none;
|
||||
}
|
||||
@media (max-width: 1000px) {
|
||||
.hero {
|
||||
grid-template-columns: 1.2fr 1fr;
|
||||
gap: 15px;
|
||||
}
|
||||
.hero h1 {
|
||||
font-size: 55px;
|
||||
}
|
||||
.world-stats {
|
||||
margin-left: 28px;
|
||||
margin-right: 28px;
|
||||
padding: 17px;
|
||||
}
|
||||
.cards-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
.compass-art {
|
||||
right: 1%;
|
||||
}
|
||||
.site-header nav {
|
||||
gap: 15px;
|
||||
}
|
||||
.home-panels {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
.mode-row h3 {
|
||||
flex-wrap: wrap;
|
||||
gap: 3px;
|
||||
}
|
||||
.contribute-banner {
|
||||
margin-left: 28px;
|
||||
margin-right: 28px;
|
||||
}
|
||||
.brand sup {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@media (max-width: 700px) {
|
||||
.site-header {
|
||||
height: auto;
|
||||
min-height: 66px;
|
||||
}
|
||||
.header-inner {
|
||||
padding: 13px 18px;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
}
|
||||
.header-inner nav {
|
||||
display: flex;
|
||||
order: 3;
|
||||
flex-basis: 100%;
|
||||
justify-content: space-between;
|
||||
border-top: 1px solid #263340;
|
||||
padding-top: 9px;
|
||||
font-size: 21px;
|
||||
gap: 12px;
|
||||
}
|
||||
.brand {
|
||||
font-size: 30px;
|
||||
}
|
||||
.header-account {
|
||||
font-size: 20px;
|
||||
padding: 4px 9px;
|
||||
}
|
||||
.hero {
|
||||
padding: 32px 22px 28px;
|
||||
gap: 20px;
|
||||
}
|
||||
.hero h1 {
|
||||
font-size: 52px;
|
||||
}
|
||||
.hero p {
|
||||
font-size: 13px;
|
||||
}
|
||||
.hero-art {
|
||||
width: 100%;
|
||||
min-height: 294px;
|
||||
margin: 15px 0 0;
|
||||
}
|
||||
.map-art-frame {
|
||||
width: 254px;
|
||||
height: 254px;
|
||||
}
|
||||
.compass-art {
|
||||
right: calc(50% - 144px);
|
||||
top: 0;
|
||||
}
|
||||
.hero-actions {
|
||||
gap: 15px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.hero-notes {
|
||||
gap: 10px;
|
||||
}
|
||||
.hero-mode-note {
|
||||
font-size: 10px;
|
||||
}
|
||||
.world-stats {
|
||||
margin: 0 18px;
|
||||
padding: 18px;
|
||||
gap: 19px;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
.world-stats > div {
|
||||
gap: 9px;
|
||||
border: 0;
|
||||
}
|
||||
.world-stats strong {
|
||||
font-size: 27px;
|
||||
}
|
||||
.world-stats span:not(.live-dot) {
|
||||
font-size: 7px;
|
||||
}
|
||||
.stat-cube {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
}
|
||||
.section {
|
||||
padding: 34px 20px;
|
||||
}
|
||||
.section-heading {
|
||||
align-items: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
.section-heading h2 {
|
||||
font-size: 33px;
|
||||
}
|
||||
.section-heading .text-link {
|
||||
font-size: 10px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.first-map-panel {
|
||||
grid-template-columns: 1fr;
|
||||
padding: 21px;
|
||||
gap: 24px;
|
||||
}
|
||||
.empty-map-art {
|
||||
width: 150px;
|
||||
margin: auto;
|
||||
}
|
||||
.first-map-panel h3 {
|
||||
font-size: 31px;
|
||||
}
|
||||
.home-panels {
|
||||
grid-template-columns: 1fr;
|
||||
padding-top: 0;
|
||||
gap: 18px;
|
||||
}
|
||||
.home-panel {
|
||||
padding: 21px;
|
||||
}
|
||||
.home-panel h2 {
|
||||
font-size: 33px;
|
||||
}
|
||||
.contribute-banner {
|
||||
margin: 0 20px 32px;
|
||||
padding: 22px;
|
||||
gap: 15px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.contribute-banner > svg {
|
||||
display: none;
|
||||
}
|
||||
.cards-grid {
|
||||
gap: 12px;
|
||||
}
|
||||
.card-image {
|
||||
margin: 23px 9px 9px;
|
||||
border-width: 7px;
|
||||
aspect-ratio: 1;
|
||||
height: auto;
|
||||
}
|
||||
.card-body {
|
||||
padding: 10px;
|
||||
}
|
||||
.card-body h3 {
|
||||
font-size: 24px;
|
||||
}
|
||||
.card-body p {
|
||||
display: none;
|
||||
}
|
||||
.card-body .eyebrow {
|
||||
font-size: 7px;
|
||||
}
|
||||
.card-meta {
|
||||
font-size: 8px;
|
||||
}
|
||||
.card-meta span:last-child {
|
||||
display: none;
|
||||
}
|
||||
.page-content h1 {
|
||||
font-size: 44px;
|
||||
}
|
||||
.tool-card {
|
||||
padding: 23px;
|
||||
}
|
||||
.tool-card .button {
|
||||
font-size: 21px;
|
||||
}
|
||||
.mode-row h3 {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.game-header .brand {
|
||||
font-size: 25px;
|
||||
}
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
animation: none !important;
|
||||
transition: none !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
}
|
||||
@@ -77,13 +77,20 @@ export default function Downloads() {
|
||||
<p className="muted">The plugin build is not available yet.</p>
|
||||
)}
|
||||
<pre>
|
||||
/minegeo area world -256 -256 256 256{"\n"}/minegeo export My
|
||||
Overworld{"\n"}/minegeo link <dashboard token>{"\n"}/minegeo
|
||||
upload
|
||||
{
|
||||
"/minegeo website https://your-minegeo-site.example\n/minegeo link <dashboard token>\n/minegeo area world -64 -64 64 64\n/minegeo export My Overworld\n/minegeo status\n# Wait for Export complete, then:\n/minegeo upload"
|
||||
}
|
||||
</pre>
|
||||
<p className="muted">
|
||||
Start with a small, explored area around your builds. Exports are
|
||||
saved in <code>plugins/MineGeo/exports/export-…/</code>. The
|
||||
manifest appears when export finishes. Upload sends the latest
|
||||
completed export; it does not capture the world.
|
||||
</p>
|
||||
<p className="muted" style={{ fontSize: 11 }}>
|
||||
Put the JAR in plugins/ and restart. Set website and server-name
|
||||
in plugins/MineGeo/config.yml. Permission: minegeo.admin.
|
||||
in plugins/MineGeo/config.yml, then run /minegeo reload. HTTP LAN
|
||||
addresses are supported for testing. Permission: minegeo.admin.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { Metadata } from "next";
|
||||
import "./globals.css";
|
||||
import "./block-theme.css";
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
default: "MineGeo — Get lost in a familiar world",
|
||||
|
||||
282
app/page.tsx
282
app/page.tsx
@@ -2,190 +2,246 @@ import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import {
|
||||
ArrowRight,
|
||||
ArrowUpRight,
|
||||
Compass,
|
||||
Cuboid,
|
||||
Map,
|
||||
MapPin,
|
||||
Move,
|
||||
Timer,
|
||||
Blocks,
|
||||
Upload,
|
||||
} from "lucide-react";
|
||||
import { Header, Footer, EmptyState } from "@/components/Shell";
|
||||
import { Header, Footer } from "@/components/Shell";
|
||||
import { MapCard } from "@/components/MapCard";
|
||||
import { catalog } from "@/lib/catalog";
|
||||
export const dynamic = "force-dynamic";
|
||||
export default async function Home() {
|
||||
const maps = await catalog();
|
||||
const serverCount = new Set(maps.map((m) => m.server_id)).size;
|
||||
const locations = maps.reduce((n, m) => n + m.panorama_count, 0);
|
||||
const servers = new Set(maps.map((map) => map.server_id)).size;
|
||||
const locations = maps.reduce((total, map) => total + map.panorama_count, 0);
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
<main>
|
||||
<main className="home-page">
|
||||
<section className="hero">
|
||||
<div className="hero-grid" />
|
||||
<div className="hero-copy">
|
||||
<div className="status-label">
|
||||
<span className="live-dot" /> MINECRAFT WORLDS. REAL EXPLORATION.
|
||||
<span className="live-dot" /> MINECRAFT · EXPLORE · GUESS
|
||||
</div>
|
||||
<h1>
|
||||
Get lost in a<br />
|
||||
<span>familiar world.</span>
|
||||
Guess where you are
|
||||
<br />
|
||||
in a <span>blocky world.</span>
|
||||
</h1>
|
||||
<p>
|
||||
Somewhere between the blocks, there’s a place you know.
|
||||
<br className="desktop" /> Look around. Trust your instincts. Make
|
||||
your guess.
|
||||
Drop into a random corner of a Minecraft world.
|
||||
<br className="desktop" /> Look around, spot the landmarks, and
|
||||
place your pin
|
||||
<br className="desktop" /> before the clock runs out.
|
||||
</p>
|
||||
<div className="hero-actions">
|
||||
<Link href="/servers" className="button primary">
|
||||
Find your next world <ArrowRight size={18} />
|
||||
</Link>
|
||||
<Link href="/about" className="text-link">
|
||||
How it works <ArrowUpRight size={15} />
|
||||
Start exploring <ArrowRight size={18} />
|
||||
</Link>
|
||||
<span className="hero-mode-note">3 difficulty levels</span>
|
||||
</div>
|
||||
<div className="hero-notes">
|
||||
<span>
|
||||
<Compass size={15} /> 360° panoramas
|
||||
</span>
|
||||
<span>
|
||||
<Move size={15} /> No roads. No moving.
|
||||
</span>
|
||||
<span>
|
||||
<Cuboid size={15} /> Just you and the blocks.
|
||||
<span className="mode-dots" aria-hidden="true">
|
||||
<i />
|
||||
<i />
|
||||
<i />
|
||||
<i />
|
||||
</span>
|
||||
<span>Five rounds. No roads. Just your instincts.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="hero-art"
|
||||
aria-label="Minecraft terrain map illustration"
|
||||
>
|
||||
<div className="artifact-caption">
|
||||
YOUR NEXT ADVENTURE IS OUT THERE
|
||||
</div>
|
||||
<div className="floating-coord">
|
||||
<span className="square-dot" /> OVERWORLD
|
||||
<span className="coord-muted">X ? · Z ?</span>
|
||||
</div>
|
||||
<div className="hero-art" aria-label="Minecraft surface map">
|
||||
<div className="map-art-frame">
|
||||
<Image
|
||||
src="/images/example-map.webp"
|
||||
alt="Top-down map of the real Paper renderer test world"
|
||||
src={maps[0]?.mapImage || "/images/example-map.webp"}
|
||||
alt="A Minecraft surface map framed in parchment"
|
||||
width={1024}
|
||||
height={1024}
|
||||
priority
|
||||
unoptimized
|
||||
/>
|
||||
<div className="map-grid" />
|
||||
<div className="map-pin">
|
||||
<MapPin size={38} fill="currentColor" />
|
||||
</div>
|
||||
<div className="map-corner top-left" />
|
||||
<div className="map-corner bottom-right" />
|
||||
<span className="square-pin pin-green" />
|
||||
<span className="square-pin pin-red" />
|
||||
<span className="square-pin pin-gold" />
|
||||
</div>
|
||||
<span className="compass-art">
|
||||
<Compass size={42} />
|
||||
<span className="compass-art" aria-hidden="true">
|
||||
<Compass size={43} />
|
||||
<small>N</small>
|
||||
</span>
|
||||
<div className="floating-tag">
|
||||
<MapPin size={15} /> ONE WORLD. COUNTLESS POSSIBILITIES.
|
||||
<MapPin size={14} />
|
||||
<strong>X: ??? Z: ???</strong>
|
||||
<span>Overworld</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div className="grass-divider">
|
||||
<div className="grass-divider" aria-hidden="true">
|
||||
<span />
|
||||
</div>
|
||||
<section className="world-stats">
|
||||
<section className="world-stats" aria-label="Community statistics">
|
||||
<div>
|
||||
<strong>{serverCount}</strong>
|
||||
<span>COMMUNITY SERVERS</span>
|
||||
<i className="stat-cube green-cube" />
|
||||
<div>
|
||||
<strong>{servers.toLocaleString()}</strong>
|
||||
<span>COMMUNITY SERVERS</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<strong>{maps.length}</strong>
|
||||
<span>WORLDS TO EXPLORE</span>
|
||||
<i className="stat-cube gold-cube" />
|
||||
<div>
|
||||
<strong>{maps.length.toLocaleString()}</strong>
|
||||
<span>PUBLISHED MAPS</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<strong>{locations}</strong>
|
||||
<span>PLACES TO GET LOST</span>
|
||||
<i className="stat-cube cyan-cube" />
|
||||
<div>
|
||||
<strong>{locations.toLocaleString()}</strong>
|
||||
<span>PLACES TO DISCOVER</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="stat-note">
|
||||
<span className="live-dot" />
|
||||
Built by explorers.
|
||||
<br />
|
||||
For explorers.
|
||||
<div>
|
||||
<i className="stat-cube red-cube" />
|
||||
<div>
|
||||
<strong>5 rounds</strong>
|
||||
<span>EVERY EXPEDITION</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section className="section catalog-section">
|
||||
<div className="section-heading">
|
||||
<div>
|
||||
<span className="eyebrow">PICK A WORLD. DROP A PIN.</span>
|
||||
<h2>Where to today?</h2>
|
||||
<span className="eyebrow">COMMUNITY MAPS</span>
|
||||
<h2>Where will you go today?</h2>
|
||||
</div>
|
||||
<Link className="text-link" href="/servers">
|
||||
All worlds <ArrowRight size={16} />
|
||||
All {maps.length} maps <ArrowRight size={15} />
|
||||
</Link>
|
||||
</div>
|
||||
{maps.length ? (
|
||||
<div className="cards-grid">
|
||||
{maps.slice(0, 3).map((m, i) => (
|
||||
<MapCard map={m} index={i} key={m.id} />
|
||||
{maps.slice(0, 4).map((map, index) => (
|
||||
<MapCard map={map} index={index} key={map.id} />
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<EmptyState title="The world is yours to map">
|
||||
The catalog is waiting for its first approved community map.
|
||||
Capture a world with our mod or server plugin.
|
||||
</EmptyState>
|
||||
<div className="first-map-panel">
|
||||
<div className="empty-map-art" aria-hidden="true">
|
||||
<Image
|
||||
src="/images/example-map.webp"
|
||||
alt=""
|
||||
width={180}
|
||||
height={180}
|
||||
unoptimized
|
||||
/>
|
||||
<span>YOUR WORLD HERE</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="eyebrow">
|
||||
THE FIRST EXPEDITION STARTS WITH YOU
|
||||
</span>
|
||||
<h3>Put your server on the map.</h3>
|
||||
<p>
|
||||
No community maps have been published yet. Export your world
|
||||
with the server plugin, or capture five locations with the
|
||||
Fabric mod. Preview your map and submit it for review.
|
||||
</p>
|
||||
<Link className="button primary" href="/downloads">
|
||||
<Upload size={16} /> Get the capture tools
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
<section className="section journey">
|
||||
<div className="journey-intro">
|
||||
<span className="eyebrow">A NEW WAY TO SEE MINECRAFT</span>
|
||||
<h2>
|
||||
Every block
|
||||
<br />
|
||||
tells a story.
|
||||
</h2>
|
||||
<p>
|
||||
That mountain. That oddly placed tower. That very suspicious dirt
|
||||
hut. You’ve been here before… right?
|
||||
</p>
|
||||
<Link href="/about" className="text-link">
|
||||
Learn how to play <ArrowRight size={16} />
|
||||
<section className="section home-panels">
|
||||
<article className="home-panel">
|
||||
<span className="eyebrow">HOW TO PLAY</span>
|
||||
<h2>Know your blocks?</h2>
|
||||
<ol className="play-steps">
|
||||
<li>
|
||||
<span>01</span>
|
||||
<div>
|
||||
<h3>Pick your world</h3>
|
||||
<p>Choose a community server, map, and difficulty.</p>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<span>02</span>
|
||||
<div>
|
||||
<h3>Look for the clues</h3>
|
||||
<p>
|
||||
Rotate the panorama. Find builds, biomes, and landmarks.
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<span>03</span>
|
||||
<div>
|
||||
<h3>Make your guess</h3>
|
||||
<p>Drop a pin on the map. Closer guesses earn more points.</p>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
<Link className="text-link" href="/about">
|
||||
Read the field guide <ArrowRight size={14} />
|
||||
</Link>
|
||||
</div>
|
||||
<div className="steps">
|
||||
<article>
|
||||
<span>01</span>
|
||||
<Compass />
|
||||
<h3>Take a look around</h3>
|
||||
<p>Find clues in a full 360° view of a Minecraft world.</p>
|
||||
</article>
|
||||
<article>
|
||||
<span>02</span>
|
||||
<Map />
|
||||
<h3>Trust your coordinates</h3>
|
||||
<p>Open the map and pin the spot where you think you are.</p>
|
||||
</article>
|
||||
<article>
|
||||
<span>03</span>
|
||||
<Timer />
|
||||
<h3>Beat the clock</h3>
|
||||
<p>Five rounds. One world. How close can you get?</p>
|
||||
</article>
|
||||
</div>
|
||||
</article>
|
||||
<article className="home-panel">
|
||||
<span className="eyebrow">CHOOSE YOUR CHALLENGE</span>
|
||||
<h2>One world. Three ways.</h2>
|
||||
<div className="mode-list">
|
||||
{[
|
||||
{
|
||||
name: "Easy",
|
||||
time: "180 seconds",
|
||||
detail: "Take your time. Rotate and zoom.",
|
||||
color: "green",
|
||||
},
|
||||
{
|
||||
name: "Normal",
|
||||
time: "90 seconds",
|
||||
detail: "Trust your eye. Rotate and zoom.",
|
||||
color: "gold",
|
||||
},
|
||||
{
|
||||
name: "Hard",
|
||||
time: "30 seconds",
|
||||
detail: "Think fast. No zoom allowed.",
|
||||
color: "red",
|
||||
},
|
||||
].map((mode) => (
|
||||
<Link href="/servers" className="mode-row" key={mode.name}>
|
||||
<i className={`stat-cube ${mode.color}-cube`} />
|
||||
<div>
|
||||
<h3>
|
||||
{mode.name}
|
||||
<span>
|
||||
<Timer size={12} />
|
||||
{mode.time}
|
||||
</span>
|
||||
</h3>
|
||||
<p>{mode.detail}</p>
|
||||
</div>
|
||||
<ArrowRight size={15} />
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
<p className="mode-footnote">
|
||||
Up to 5,000 points per round. How close can you get?
|
||||
</p>
|
||||
</article>
|
||||
</section>
|
||||
<section className="section contribute-banner">
|
||||
<Blocks size={38} />
|
||||
<div>
|
||||
<span className="eyebrow">YOUR SERVER DESERVES TO BE EXPLORED</span>
|
||||
<h2>Put your world on the map.</h2>
|
||||
<p>
|
||||
Bring your builds, your landscapes, and your community to MineGeo.
|
||||
</p>
|
||||
<span className="eyebrow">BUILT BY THE COMMUNITY</span>
|
||||
<h2>Your world deserves to be explored.</h2>
|
||||
<p>Share your builds and your favorite corners of Minecraft.</p>
|
||||
</div>
|
||||
<Link href="/downloads" className="button primary">
|
||||
Create a map <ArrowUpRight size={18} />
|
||||
<Link href="/downloads" className="button">
|
||||
Create a map <ArrowRight size={16} />
|
||||
</Link>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
Reference in New Issue
Block a user