+
diff --git a/web/src/assets/resources/brick.svg b/web/src/assets/resources/brick.svg
new file mode 100644
index 0000000..f971b08
--- /dev/null
+++ b/web/src/assets/resources/brick.svg
@@ -0,0 +1,4 @@
+
diff --git a/web/src/assets/resources/card_back.svg b/web/src/assets/resources/card_back.svg
new file mode 100644
index 0000000..c267c49
--- /dev/null
+++ b/web/src/assets/resources/card_back.svg
@@ -0,0 +1,4 @@
+
diff --git a/web/src/assets/resources/devcard.svg b/web/src/assets/resources/devcard.svg
new file mode 100644
index 0000000..a7318bd
--- /dev/null
+++ b/web/src/assets/resources/devcard.svg
@@ -0,0 +1,4 @@
+
diff --git a/web/src/assets/resources/grain.svg b/web/src/assets/resources/grain.svg
new file mode 100644
index 0000000..0b0dbad
--- /dev/null
+++ b/web/src/assets/resources/grain.svg
@@ -0,0 +1,6 @@
+
diff --git a/web/src/assets/resources/lumber.svg b/web/src/assets/resources/lumber.svg
new file mode 100644
index 0000000..980ea5a
--- /dev/null
+++ b/web/src/assets/resources/lumber.svg
@@ -0,0 +1,5 @@
+
diff --git a/web/src/assets/resources/ore.svg b/web/src/assets/resources/ore.svg
new file mode 100644
index 0000000..fb356e5
--- /dev/null
+++ b/web/src/assets/resources/ore.svg
@@ -0,0 +1,4 @@
+
diff --git a/web/src/assets/resources/wool.svg b/web/src/assets/resources/wool.svg
new file mode 100644
index 0000000..a7c6b0c
--- /dev/null
+++ b/web/src/assets/resources/wool.svg
@@ -0,0 +1,3 @@
+
diff --git a/web/src/styles.css b/web/src/styles.css
index 252d8d0..54edcda 100644
--- a/web/src/styles.css
+++ b/web/src/styles.css
@@ -855,24 +855,113 @@ textarea {
background: #d95f00;
}
-.game-layout {
- display: grid;
- grid-template-columns: 260px 1fr 260px;
- gap: 16px;
- width: 100%;
- height: 100%;
- overflow: hidden;
-}
-
-.game-panel {
+.game-shell {
display: flex;
flex-direction: column;
- gap: 16px;
- overflow: auto;
+ gap: 12px;
+ width: 100%;
+ height: 100%;
+ min-height: 0;
}
-.game-board {
+.game-topbar {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12px;
+ padding: 12px;
border-radius: 12px;
+ background: rgba(0, 0, 0, 0.2);
+}
+
+.player-chip {
+ display: flex;
+ gap: 10px;
+ align-items: center;
+ padding: 8px 12px;
+ border-radius: 12px;
+ background: rgba(0, 0, 0, 0.25);
+ min-width: 180px;
+}
+
+.player-chip-body {
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+ flex: 1;
+}
+
+.player-chip--active {
+ border: 2px solid #48ff00;
+}
+
+.player-color {
+ width: 12px;
+ height: 12px;
+ border-radius: 999px;
+}
+
+.player-name {
+ font-weight: bold;
+}
+
+.player-meta {
+ font-size: 0.85rem;
+ color: rgba(255, 255, 255, 0.7);
+}
+
+.player-hand {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.card-stack {
+ position: relative;
+ width: 44px;
+ height: 34px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.card-back {
+ width: 30px;
+ height: 30px;
+}
+
+.card-back--offset {
+ position: absolute;
+ left: 6px;
+ top: 4px;
+ opacity: 0.85;
+}
+
+.card-stack--dev {
+ width: 34px;
+}
+
+.card-count {
+ position: absolute;
+ bottom: -6px;
+ right: -6px;
+ background: rgba(0, 0, 0, 0.65);
+ color: #fff;
+ border-radius: 999px;
+ font-size: 0.7rem;
+ padding: 2px 6px;
+ border: 1px solid rgba(255, 255, 255, 0.3);
+}
+
+.game-main {
+ display: grid;
+ grid-template-columns: 1fr 300px;
+ gap: 12px;
+ flex: 1;
+ min-height: 0;
+}
+
+.game-board-area {
+ border-radius: 16px;
background: rgba(0, 0, 0, 0.15);
display: flex;
align-items: center;
@@ -881,21 +970,122 @@ textarea {
overflow: hidden;
}
-.board-svg {
- width: 100%;
- height: 100%;
+.game-side {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ overflow: auto;
}
-.player-row {
+.game-bottom {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+}
+
+.resource-bar {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+ justify-content: center;
+ padding: 10px;
+ border-radius: 12px;
+ background: rgba(0, 0, 0, 0.2);
+}
+
+.resource-card {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 4px;
+ min-width: 90px;
+ padding: 8px 10px;
+ border-radius: 12px;
+ color: #1b1b1b;
+ font-weight: bold;
+}
+
+.resource-icon {
+ width: 30px;
+ height: 30px;
+}
+
+.resource-card-label {
+ font-size: 0.8rem;
+}
+
+.resource-card-count {
+ font-size: 1.1rem;
+}
+
+.resource-card--dev {
+ background: rgba(0, 0, 0, 0.3);
+ color: #fff;
+}
+
+.action-bar {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ justify-content: center;
+}
+
+.action-button {
+ border: 0;
+ border-radius: 8px;
+ background: rgba(0, 0, 0, 0.25);
+ color: #fff;
+ font-weight: bold;
+ padding: 10px 14px;
+ cursor: pointer;
+ transition: all 0.15s ease;
+}
+
+.action-button:hover {
+ background: rgba(0, 0, 0, 0.4);
+}
+
+.action-button--primary {
+ background: #f06800;
+}
+
+.action-button--primary:hover {
+ background: #bd5200;
+}
+
+.action-button--active {
+ border: 2px solid #48ff00;
+}
+
+.action-button:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+
+.action-banner {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+ padding: 10px 14px;
+ border-radius: 12px;
+ background: rgba(0, 0, 0, 0.2);
+}
+
+.robber-panel {
display: flex;
gap: 10px;
align-items: center;
+ justify-content: center;
+ padding: 8px 12px;
+ border-radius: 12px;
+ background: rgba(0, 0, 0, 0.2);
}
-.player-dot {
- width: 12px;
- height: 12px;
- border-radius: 999px;
+.board-svg {
+ width: 100%;
+ height: 100%;
}
.trade-card {
@@ -919,6 +1109,260 @@ textarea {
overflow: auto;
}
+.trade-panel {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
+
+.trade-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+}
+
+.trade-offer-list {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+}
+
+.trade-offer {
+ border-radius: 12px;
+ padding: 10px;
+ background: rgba(0, 0, 0, 0.25);
+}
+
+.trade-offer-meta {
+ font-size: 0.85rem;
+ color: rgba(255, 255, 255, 0.7);
+ margin-bottom: 6px;
+}
+
+.trade-offer-row {
+ display: flex;
+ gap: 8px;
+ align-items: center;
+ margin-bottom: 6px;
+}
+
+.trade-offer-label {
+ font-weight: bold;
+ min-width: 60px;
+}
+
+.trade-chip-row {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 6px;
+}
+
+.trade-chip {
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
+ padding: 4px 8px;
+ border-radius: 999px;
+ background: rgba(0, 0, 0, 0.3);
+ font-size: 0.75rem;
+}
+
+.trade-chip-icon {
+ width: 16px;
+ height: 16px;
+}
+
+.trade-chip--brick {
+ background: #c46a44;
+}
+
+.trade-chip--lumber {
+ background: #4a6d4a;
+}
+
+.trade-chip--wool {
+ background: #8cc071;
+}
+
+.trade-chip--grain {
+ background: #e2c065;
+}
+
+.trade-chip--ore {
+ background: #7a7c83;
+}
+
+.modal-backdrop {
+ position: fixed;
+ inset: 0;
+ background: rgba(0, 0, 0, 0.65);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 100;
+}
+
+.trade-modal {
+ width: min(640px, 90vw);
+ max-height: 90vh;
+ overflow: auto;
+ padding: 20px;
+ border-radius: 16px;
+ background: #1062b0;
+ box-shadow: 0 12px 30px rgba(0, 0, 0, 0.4);
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+}
+
+.trade-tabs {
+ display: flex;
+ gap: 8px;
+}
+
+.trade-tab {
+ flex: 1;
+ padding: 8px 12px;
+ border-radius: 10px;
+ border: 0;
+ background: rgba(0, 0, 0, 0.2);
+ color: #fff;
+ font-weight: bold;
+ cursor: pointer;
+}
+
+.trade-tab.active {
+ background: #1e90ff;
+}
+
+.trade-tab:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+
+.trade-content {
+ display: flex;
+ flex-direction: column;
+ gap: 14px;
+}
+
+.trade-row {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+}
+
+.trade-section h4 {
+ margin-bottom: 8px;
+}
+
+.trade-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
+ gap: 10px;
+}
+
+.trade-resource {
+ padding: 8px;
+ border-radius: 10px;
+ background: rgba(0, 0, 0, 0.2);
+}
+
+.trade-resource-name {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ font-size: 0.85rem;
+ margin-bottom: 6px;
+}
+
+.trade-resource-icon {
+ width: 18px;
+ height: 18px;
+}
+
+.trade-stepper {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 6px;
+}
+
+.stepper-btn {
+ border: 0;
+ border-radius: 8px;
+ width: 28px;
+ height: 28px;
+ background: rgba(0, 0, 0, 0.3);
+ color: #fff;
+ font-weight: bold;
+ cursor: pointer;
+}
+
+.stepper-btn:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+
+.stepper-value {
+ min-width: 24px;
+ text-align: center;
+}
+
+.trade-actions-row {
+ display: flex;
+ gap: 10px;
+ justify-content: flex-end;
+}
+
+.hex {
+ transition: all 0.15s ease;
+ pointer-events: all;
+}
+
+.hex--highlight {
+ stroke: #48ff00;
+ stroke-width: 3;
+ cursor: pointer;
+}
+
+.hex--selected {
+ stroke: #f4ff00;
+ stroke-width: 4;
+}
+
+.edge-hit {
+ stroke: transparent;
+ cursor: default;
+ pointer-events: stroke;
+}
+
+.edge-hit--active {
+ stroke: rgba(255, 255, 255, 0.2);
+ cursor: pointer;
+}
+
+.edge-hit--selected {
+ stroke: rgba(244, 255, 0, 0.6);
+}
+
+.corner-hit {
+ fill: transparent;
+ stroke: transparent;
+ cursor: default;
+ pointer-events: all;
+}
+
+.corner-hit--active {
+ stroke: rgba(255, 255, 255, 0.5);
+ cursor: pointer;
+}
+
+.corner-hit--selected {
+ stroke: rgba(244, 255, 0, 0.8);
+}
+
.replay-table {
display: flex;
flex-direction: column;
@@ -1071,7 +1515,7 @@ textarea {
display: none;
}
- .game-layout {
+ .game-main {
grid-template-columns: 1fr;
}
}