aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/app
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/app')
-rw-r--r--src/frontend/app/components/LineIcon.css146
-rw-r--r--src/frontend/app/components/LineIcon.tsx16
-rw-r--r--src/frontend/app/components/StopSheet.tsx2
-rw-r--r--src/frontend/app/components/Stops/ConsolidatedCirculationCard.css214
-rw-r--r--src/frontend/app/components/Stops/ConsolidatedCirculationCard.tsx26
-rw-r--r--src/frontend/app/components/Stops/ConsolidatedCirculationList.css226
-rw-r--r--src/frontend/app/root.css4
-rw-r--r--src/frontend/app/routes/estimates-$id.tsx2
-rw-r--r--src/frontend/app/routes/stops-$id.css2
-rw-r--r--src/frontend/app/routes/stops-$id.tsx2
10 files changed, 320 insertions, 320 deletions
diff --git a/src/frontend/app/components/LineIcon.css b/src/frontend/app/components/LineIcon.css
index 721de76..50f2d5f 100644
--- a/src/frontend/app/components/LineIcon.css
+++ b/src/frontend/app/components/LineIcon.css
@@ -1,72 +1,76 @@
/* Vigo line colors */
:root {
- --line-vigo-c1: rgb(237, 71, 19);
- --line-vigo-c1-text: #ffffff;
- --line-vigo-c3d: rgb(255, 204, 0);
- --line-vigo-c3i: rgb(255, 204, 0);
- --line-vigo-l4a: rgb(0, 153, 0);
- --line-vigo-l4a-text: #ffffff;
- --line-vigo-l4c: rgb(0, 153, 0);
- --line-vigo-l4c-text: #ffffff;
- --line-vigo-l5a: rgb(0, 176, 240);
- --line-vigo-l5b: rgb(0, 176, 240);
- --line-vigo-l6: rgb(204, 51, 153);
- --line-vigo-l7: rgb(150, 220, 153);
- --line-vigo-l9b: rgb(244, 202, 140);
- --line-vigo-l10: rgb(153, 51, 0);
- --line-vigo-l10-text: #ffffff;
- --line-vigo-l11: rgb(226, 0, 38);
- --line-vigo-l11-text: #ffffff;
- --line-vigo-l12a: rgb(106, 150, 190);
- --line-vigo-l12b: rgb(106, 150, 190);
- --line-vigo-l13: rgb(0, 176, 240);
- --line-vigo-l14: rgb(129, 142, 126);
- --line-vigo-l14-text: #ffffff;
- --line-vigo-l15a: rgb(216, 168, 206);
- --line-vigo-l15b: rgb(216, 168, 206);
- --line-vigo-l15c: rgb(216, 168, 168);
- --line-vigo-l16: rgb(129, 142, 126);
- --line-vigo-l16-text: #ffffff;
- --line-vigo-l17: rgb(214, 245, 31);
- --line-vigo-l18a: rgb(212, 80, 168);
- --line-vigo-l18a-text: #ffffff;
- --line-vigo-l18b: rgb(212, 80, 168);
- --line-vigo-l18b-text: #ffffff;
- --line-vigo-l18h: rgb(212, 80, 168);
- --line-vigo-l18h-text: #ffffff;
- --line-vigo-l23: rgb(0, 70, 210);
- --line-vigo-l24: rgb(191, 191, 191);
- --line-vigo-l25: rgb(172, 100, 4);
- --line-vigo-l27: rgb(112, 74, 42);
- --line-vigo-l27-text: #ffffff;
- --line-vigo-l28: rgb(176, 189, 254);
- --line-vigo-l29: rgb(248, 184, 90);
- --line-vigo-l31: rgb(255, 255, 0);
- --line-vigo-a: rgb(119, 41, 143);
- --line-vigo-a-text: #ffffff;
- --line-vigo-h: rgb(0, 96, 168);
- --line-vigo-h-text: #ffffff;
- --line-vigo-h1: rgb(0, 96, 168);
- --line-vigo-h1-text: #ffffff;
- --line-vigo-h2: rgb(0, 96, 168);
- --line-vigo-h2-text: #ffffff;
- --line-vigo-h3: rgb(0, 96, 168);
- --line-vigo-h3-text: #ffffff;
- --line-vigo-lzd: rgb(61, 78, 167);
- --line-vigo-n1: rgb(191, 191, 191);
- --line-vigo-n4: rgb(102, 51, 102);
- --line-vigo-n4-text: #ffffff;
- --line-vigo-psa1: rgb(0, 153, 0);
- --line-vigo-psa4: rgb(0, 153, 0);
- --line-vigo-ptl: rgb(150, 220, 153);
- --line-vigo-turistico: rgb(102, 51, 102);
- --line-vigo-u1: rgb(172, 100, 4);
- --line-vigo-u1-text: #ffffff;
- --line-vigo-u2: rgb(172, 100, 4);
- --line-vigo-u2-text: #ffffff;
+ --line-c1: hsl(14, 86%, 50%);
+ --line-c1-text: hsl(0, 0%, 100%);
+ --line-c3d: hsl(48, 100%, 50%);
+ --line-c3i: hsl(48, 100%, 50%);
+ --line-l4a: hsl(120, 100%, 30%);
+ --line-l4a-text: hsl(0, 0%, 100%);
+ --line-l4c: hsl(120, 100%, 30%);
+ --line-l4c-text: hsl(0, 0%, 100%);
+ --line-l5a: hsl(204, 100%, 54%);
+ --line-l5a-text: hsl(0, 0%, 100%);
+ --line-l5b: hsl(204, 100%, 54%);
+ --line-l5b-text: hsl(0, 0%, 100%);
+ --line-l6: hsl(330, 60%, 50%);
+ --line-l7: hsl(120, 60%, 70%);
+ --line-l9b: hsl(36, 83%, 75%);
+ --line-l10: hsl(30, 80%, 20%);
+ --line-l10-text: hsl(0, 0%, 100%);
+ --line-l11: hsl(0, 100%, 44%);
+ --line-l11-text: hsl(0, 0%, 100%);
+ --line-l12a: hsl(210, 40%, 56%);
+ --line-l12b: hsl(209, 39%, 58%);
+ --line-l13: hsl(196, 100%, 47%);
+ --line-l14: hsl(120, 10%, 44%);
+ --line-l14-text: hsl(0, 0%, 100%);
+ --line-l15a: hsl(313, 38%, 75%);
+ --line-l15b: hsl(313, 38%, 75%);
+ --line-l15c: #d8a8a8;
+ --line-l16: hsl(120, 10%, 44%);
+ --line-l16-text: hsl(0, 0%, 100%);
+ --line-l17: hsl(69, 91%, 54%);
+ --line-l18a: hsl(320, 61%, 57%);
+ --line-l18a-text: hsl(0, 0%, 100%);
+ --line-l18b: hsl(320, 61%, 57%);
+ --line-l18b-text: hsl(0, 0%, 100%);
+ --line-l18h: hsl(320, 61%, 57%);
+ --line-l18h-text: hsl(0, 0%, 100%);
+ --line-l23: hsl(220, 100%, 41%);
+ --line-l24: hsl(0, 0%, 75%);
+ --line-l25: hsl(34, 95%, 35%);
+ --line-l27: hsl(30, 60%, 30%);
+ --line-l27-text: hsl(0, 0%, 100%);
+ --line-l28: hsl(230, 98%, 84%);
+ --line-l29: hsl(36, 92%, 66%);
+ --line-l31: hsl(60, 100%, 50%);
+ --line-a: hsl(300, 70%, 35%);
+ --line-a-text: hsl(0, 0%, 100%);
+ --line-a1: hsl(300, 70%, 35%);
+ --line-a1-text: hsl(0, 0%, 100%);
+ --line-h: hsl(210, 100%, 33%);
+ --line-h-text: hsl(0, 0%, 100%);
+ --line-h1: hsl(210, 100%, 33%);
+ --line-h1-text: hsl(0, 0%, 100%);
+ --line-h2: hsl(210, 100%, 33%);
+ --line-h2-text: hsl(0, 0%, 100%);
+ --line-h3: hsl(210, 100%, 33%);
+ --line-h3-text: hsl(0, 0%, 100%);
+ --line-lzd: hsl(220, 60%, 50%);
+ --line-n1: hsl(0, 51%, 53%);
+ --line-n4: hsl(300, 33%, 30%);
+ --line-n4-text: hsl(0, 0%, 100%);
+ --line-psa1: hsl(120, 100%, 30%);
+ --line-psa4: hsl(120, 100%, 30%);
+ --line-ptl: hsl(120, 60%, 70%);
+ --line-tur: hsl(300, 33%, 30%);
+ --line-u1: hsl(30, 80%, 20%);
+ --line-u1-text: hsl(0, 0%, 100%);
+ --line-u2: hsl(30, 80%, 20%);
+ --line-u2-text: hsl(0, 0%, 100%);
}
-.line-icon {
+.line-icon-default {
display: inline-block;
padding: 0.25rem 0.5rem;
margin-right: 0.5rem;
@@ -81,6 +85,18 @@
border-color: var(--line-colour);
}
+.line-icon-pill {
+ display: inline-block;
+ padding: 0.25rem 0.5rem;
+ margin-right: 0.5rem;
+ font-size: 0.9rem;
+ font-weight: 600;
+ border-radius: 0.25rem;
+
+ background-color: var(--line-colour);
+ color: var(--line-text-colour);
+}
+
.line-icon-rounded {
display: block;
width: 5ch;
diff --git a/src/frontend/app/components/LineIcon.tsx b/src/frontend/app/components/LineIcon.tsx
index 8c3dbeb..5ccf80a 100644
--- a/src/frontend/app/components/LineIcon.tsx
+++ b/src/frontend/app/components/LineIcon.tsx
@@ -4,24 +4,28 @@ import "./LineIcon.css";
interface LineIconProps {
line: string;
+
+ /**
+ * @deprecated Unused since region is only Vigo
+ */
region?: RegionId;
- rounded?: boolean;
+
+ mode?: "rounded"|"pill"|"default";
}
const LineIcon: React.FC<LineIconProps> = ({
line,
- region = "vigo",
- rounded = false,
+ mode = "default",
}) => {
const formattedLine = useMemo(() => {
return /^[a-zA-Z]/.test(line) ? line : `L${line}`;
}, [line]);
- const cssVarName = `--line-${region}-${formattedLine.toLowerCase()}`;
- const cssTextVarName = `--line-${region}-${formattedLine.toLowerCase()}-text`;
+ const cssVarName = `--line-${formattedLine.toLowerCase()}`;
+ const cssTextVarName = `--line-${formattedLine.toLowerCase()}-text`;
return (
<span
- className={rounded ? "line-icon-rounded" : "line-icon"}
+ className={`line-icon-${mode}`}
style={
{
"--line-colour": `var(${cssVarName})`,
diff --git a/src/frontend/app/components/StopSheet.tsx b/src/frontend/app/components/StopSheet.tsx
index cf070e2..6d2abf0 100644
--- a/src/frontend/app/components/StopSheet.tsx
+++ b/src/frontend/app/components/StopSheet.tsx
@@ -130,7 +130,7 @@ export const StopSheet: React.FC<StopSheetProps> = ({
>
{stop.lines.map((line) => (
<div key={line} className="stop-sheet-line-icon">
- <LineIcon line={line} region={region} rounded />
+ <LineIcon line={line} region={region} mode="rounded" />
</div>
))}
</div>
diff --git a/src/frontend/app/components/Stops/ConsolidatedCirculationCard.css b/src/frontend/app/components/Stops/ConsolidatedCirculationCard.css
new file mode 100644
index 0000000..8a442c3
--- /dev/null
+++ b/src/frontend/app/components/Stops/ConsolidatedCirculationCard.css
@@ -0,0 +1,214 @@
+@reference "../../root.css";
+
+.consolidated-circulation-card {
+ all: unset;
+ flex: 0 0 auto;
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+ background-color: var(--message-background-color);
+ border-radius: 12px;
+ border: 1px solid var(--border-color);
+ padding: 0.65rem 0.85rem;
+ transition: all 0.2s ease;
+}
+
+.consolidated-circulation-card.has-gps {
+ cursor: pointer;
+}
+
+.consolidated-circulation-card.no-gps {
+ cursor: not-allowed;
+ opacity: 0.7;
+}
+
+.consolidated-circulation-card.has-gps:hover {
+ box-shadow: 0 4px 14px rgba(0, 0, 0, 0.08);
+ border-color: var(--button-background-color);
+ background-color: color-mix(
+ in oklab,
+ var(--button-background-color) 5%,
+ var(--message-background-color)
+ );
+}
+
+.consolidated-circulation-card.has-gps:active {
+ transform: scale(0.98);
+}
+
+.consolidated-circulation-card:disabled {
+ pointer-events: none;
+}
+
+
+.consolidated-circulation-card .card-row {
+ display: flex;
+ align-items: center;
+ gap: 0.65rem;
+}
+
+.consolidated-circulation-card .card-row.main {
+ min-height: 48px;
+}
+
+.consolidated-circulation-card .line-info {
+ flex-shrink: 0;
+}
+
+.consolidated-circulation-card .route-info {
+ flex: 1;
+ min-width: 0;
+}
+
+.consolidated-circulation-card .route-info strong {
+ font-size: 1rem;
+ color: var(--text-color);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ line-clamp: 2;
+ -webkit-box-orient: vertical;
+ line-height: 1.25;
+}
+
+.consolidated-circulation-card .eta-badge {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0.3rem 0.45rem;
+ border-radius: 12px;
+}
+
+.consolidated-circulation-card .eta-text {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ line-height: 1;
+}
+
+.consolidated-circulation-card .eta-value {
+ font-size: 1.15rem;
+ font-weight: 700;
+}
+
+.consolidated-circulation-card .eta-unit {
+ font-size: 0.65rem;
+ text-transform: uppercase;
+ letter-spacing: 0.08em;
+}
+
+.consolidated-circulation-card .eta-badge.time-running {
+ background: rgba(34, 197, 94, 0.12);
+ color: #1a9e56;
+}
+
+.consolidated-circulation-card .eta-badge.time-delayed {
+ background: rgba(255, 106, 0, 0.12);
+ color: #d06100;
+}
+
+.consolidated-circulation-card .eta-badge.time-scheduled {
+ background: rgba(11, 61, 145, 0.12);
+ color: #0b3d91;
+}
+
+[data-theme="dark"] .consolidated-circulation-card .eta-badge.time-scheduled {
+ color: #8fb4ff;
+}
+
+.consolidated-circulation-card .card-row.meta {
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ gap: 0.4rem;
+}
+
+.meta-chip {
+ font-size: 0.75rem;
+ padding: 0.2rem 0.55rem;
+ border-radius: 999px;
+ background: rgba(0, 0, 0, 0.03);
+
+ @apply flex items-center justify-center gap-1 flex-shrink-0 bg-gray-200/30 dark:bg-gray-600/30;
+}
+
+.meta-chip.delay-ok {
+ @apply bg-green-400/30 dark:bg-green-600/30 border-green-500 dark:border-green-700 text-green-800 dark:text-green-200;
+}
+
+.meta-chip.delay-warn {
+ @apply bg-yellow-400/30 dark:bg-yellow-600/30 border-yellow-500 dark:border-yellow-700 text-yellow-800 dark:text-yellow-200;
+}
+
+.meta-chip.delay-critical {
+ @apply bg-red-400/30 dark:bg-red-600/30 border-red-500 dark:border-red-700 text-white;
+}
+
+.meta-chip.delay-early {
+ @apply bg-blue-400/30 dark:bg-blue-600/30 border-blue-500 dark:border-blue-700 text-blue-800 dark:text-blue-200;
+}
+
+/* GPS Indicator */
+.gps-indicator {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 20px;
+ height: 20px;
+ flex-shrink: 0;
+ position: relative;
+}
+
+.gps-pulse {
+ position: absolute;
+ width: 8px;
+ height: 8px;
+ background: #22c55e;
+ border-radius: 50%;
+ box-shadow: 0 0 0 2px rgba(34, 197, 94, 0.2);
+ animation: gpsPulse 2s ease-in-out infinite;
+}
+
+.gps-pulse.previous-trip {
+ background: #ff9800;
+ box-shadow: 0 0 0 2px rgba(255, 152, 0, 0.2);
+ animation: gpsPulseOrange 2s ease-in-out infinite;
+}
+
+@keyframes gpsPulse {
+ 0% {
+ box-shadow: 0 0 0 2px rgba(34, 197, 94, 0.2);
+ }
+ 50% {
+ box-shadow: 0 0 0 6px rgba(34, 197, 94, 0.1);
+ }
+ 100% {
+ box-shadow: 0 0 0 2px rgba(34, 197, 94, 0.2);
+ }
+}
+
+@keyframes gpsPulseOrange {
+ 0% {
+ box-shadow: 0 0 0 2px rgba(255, 152, 0, 0.2);
+ }
+ 50% {
+ box-shadow: 0 0 0 6px rgba(255, 152, 0, 0.1);
+ }
+ 100% {
+ box-shadow: 0 0 0 2px rgba(255, 152, 0, 0.2);
+ }
+}
+
+@media (max-width: 480px) {
+ .consolidated-circulation-card {
+ padding: 0.65rem 0.75rem;
+ }
+
+ .consolidated-circulation-card .card-row {
+ gap: 0.5rem;
+ }
+
+ .consolidated-circulation-card .eta-badge {
+ padding: 0.25rem 0.4rem;
+ }
+}
diff --git a/src/frontend/app/components/Stops/ConsolidatedCirculationCard.tsx b/src/frontend/app/components/Stops/ConsolidatedCirculationCard.tsx
index 707ecce..0b97c11 100644
--- a/src/frontend/app/components/Stops/ConsolidatedCirculationCard.tsx
+++ b/src/frontend/app/components/Stops/ConsolidatedCirculationCard.tsx
@@ -4,7 +4,7 @@ import { type RegionConfig } from "~/config/RegionConfig";
import LineIcon from "~components/LineIcon";
import { type ConsolidatedCirculation } from "~routes/stops-$id";
-import "./ConsolidatedCirculationList.css";
+import "./ConsolidatedCirculationCard.css";
interface ConsolidatedCirculationCardProps {
estimate: ConsolidatedCirculation;
@@ -75,18 +75,6 @@ export const ConsolidatedCirculationCard: React.FC<
> = ({ estimate, regionConfig, onMapClick, readonly }) => {
const { t } = useTranslation();
- const absoluteArrivalTime = (minutes: number) => {
- const now = new Date();
- const arrival = new Date(now.getTime() + minutes * 60000);
- return Intl.DateTimeFormat(
- typeof navigator !== "undefined" ? navigator.language : "en",
- {
- hour: "2-digit",
- minute: "2-digit",
- }
- ).format(arrival);
- };
-
const formatDistance = (meters: number) => {
if (meters > 1024) {
return `${(meters / 1000).toFixed(1)} km`;
@@ -123,9 +111,12 @@ export const ConsolidatedCirculationCard: React.FC<
return null;
}
- const delta = Math.round(estimate.realTime.minutes - estimate.schedule.minutes);
+ const delta = Math.round(
+ estimate.realTime.minutes - estimate.schedule.minutes
+ );
const absDelta = Math.abs(delta);
+ // On time
if (delta === 0) {
return {
label: t("estimates.delay_on_time", "En hora (0 min)"),
@@ -133,8 +124,10 @@ export const ConsolidatedCirculationCard: React.FC<
} as const;
}
+ // Delayed
if (delta > 0) {
- const tone = delta <= 2 ? "delay-ok" : delta <= 10 ? "delay-warn" : "delay-critical";
+ const tone =
+ delta <= 2 ? "delay-ok" : delta <= 10 ? "delay-warn" : "delay-critical";
return {
label: t("estimates.delay_positive", "Retraso de {{minutes}} min", {
minutes: delta,
@@ -143,6 +136,7 @@ export const ConsolidatedCirculationCard: React.FC<
} as const;
}
+ // Early
const tone = absDelta <= 2 ? "delay-ok" : "delay-early";
return {
label: t("estimates.delay_negative", "Adelanto de {{minutes}} min", {
@@ -200,7 +194,7 @@ export const ConsolidatedCirculationCard: React.FC<
>
<div className="card-row main">
<div className="line-info">
- <LineIcon line={estimate.line} region={regionConfig.id} rounded />
+ <LineIcon line={estimate.line} region={regionConfig.id} mode="pill" />
</div>
<div className="route-info">
<strong>{estimate.route}</strong>
diff --git a/src/frontend/app/components/Stops/ConsolidatedCirculationList.css b/src/frontend/app/components/Stops/ConsolidatedCirculationList.css
index 5afdeaa..044b4a3 100644
--- a/src/frontend/app/components/Stops/ConsolidatedCirculationList.css
+++ b/src/frontend/app/components/Stops/ConsolidatedCirculationList.css
@@ -11,229 +11,3 @@
color: var(--subtitle-color);
font-size: 0.95rem;
}
-
-.consolidated-circulation-card {
- all: unset;
- flex: 0 0 auto;
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
- background-color: var(--message-background-color);
- border-radius: 12px;
- border: 1px solid var(--border-color);
- padding: 0.65rem 0.85rem;
- transition: all 0.2s ease;
-}
-
-.consolidated-circulation-card.has-gps {
- cursor: pointer;
-}
-
-.consolidated-circulation-card.no-gps {
- cursor: not-allowed;
- opacity: 0.7;
-}
-
-.consolidated-circulation-card.has-gps:hover {
- box-shadow: 0 4px 14px rgba(0, 0, 0, 0.08);
- border-color: var(--button-background-color);
- background-color: color-mix(
- in oklab,
- var(--button-background-color) 5%,
- var(--message-background-color)
- );
-}
-
-.consolidated-circulation-card.has-gps:active {
- transform: scale(0.98);
-}
-
-.consolidated-circulation-card:disabled {
- pointer-events: none;
-}
-
-
-.consolidated-circulation-card .card-row {
- display: flex;
- align-items: center;
- gap: 0.65rem;
-}
-
-.consolidated-circulation-card .card-row.main {
- min-height: 48px;
-}
-
-.consolidated-circulation-card .line-info {
- flex-shrink: 0;
-}
-
-.consolidated-circulation-card .route-info {
- flex: 1;
- min-width: 0;
-}
-
-.consolidated-circulation-card .route-info strong {
- font-size: 1rem;
- color: var(--text-color);
- overflow: hidden;
- text-overflow: ellipsis;
- display: -webkit-box;
- -webkit-line-clamp: 2;
- -webkit-box-orient: vertical;
- line-height: 1.25;
-}
-
-.consolidated-circulation-card .eta-badge {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- padding: 0.3rem 0.45rem;
- border-radius: 12px;
-}
-
-.consolidated-circulation-card .eta-text {
- display: flex;
- flex-direction: column;
- align-items: center;
- line-height: 1;
-}
-
-.consolidated-circulation-card .eta-value {
- font-size: 1.15rem;
- font-weight: 700;
-}
-
-.consolidated-circulation-card .eta-unit {
- font-size: 0.65rem;
- text-transform: uppercase;
- letter-spacing: 0.08em;
-}
-
-.consolidated-circulation-card .eta-badge.time-running {
- background: rgba(34, 197, 94, 0.12);
- color: #1a9e56;
-}
-
-.consolidated-circulation-card .eta-badge.time-delayed {
- background: rgba(255, 106, 0, 0.12);
- color: #d06100;
-}
-
-.consolidated-circulation-card .eta-badge.time-scheduled {
- background: rgba(11, 61, 145, 0.12);
- color: #0b3d91;
-}
-
-[data-theme="dark"] .consolidated-circulation-card .eta-badge.time-scheduled {
- color: #8fb4ff;
-}
-
-.consolidated-circulation-card .card-row.meta {
- flex-wrap: wrap;
- justify-content: flex-start;
- gap: 0.4rem;
-}
-
-.meta-chip {
- font-size: 0.75rem;
- padding: 0.2rem 0.55rem;
- border-radius: 999px;
- background: rgba(0, 0, 0, 0.03);
- color: var(--subtitle-color);
- border: 1px solid var(--border-color);
-}
-
-@media (prefers-color-scheme: dark) {
- .meta-chip {
- background: rgba(255, 255, 255, 0.05);
- }
-}
-
-.meta-chip.delay-ok {
- background: hsla(142, 71%, 45%, 0.15);
- border-color: hsla(142, 71%, 45%, 0.5);
- color: #1a9e56;
-}
-
-.meta-chip.delay-warn {
- background: hsla(43, 96%, 56%, 0.25);
- border-color: hsla(43, 96%, 56%, 0.6);
- color: hsl(43, 96%, 40%);
-}
-
-.meta-chip.delay-critical {
- background: hsla(0, 84%, 60%, 0.2);
- border-color: hsla(0, 84%, 60%, 0.35);
- color: hsl(0, 74%, 42%);
-}
-
-.meta-chip.delay-early {
- background: hsla(217, 91%, 60%, 0.17);
- border-color: hsla(217, 91%, 60%, 0.3);
- color: hsl(224, 90%, 50%);
-}
-
-/* GPS Indicator */
-.gps-indicator {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 20px;
- height: 20px;
- flex-shrink: 0;
- position: relative;
-}
-
-.gps-pulse {
- position: absolute;
- width: 8px;
- height: 8px;
- background: #22c55e;
- border-radius: 50%;
- box-shadow: 0 0 0 2px rgba(34, 197, 94, 0.2);
- animation: gpsPulse 2s ease-in-out infinite;
-}
-
-.gps-pulse.previous-trip {
- background: #ff9800;
- box-shadow: 0 0 0 2px rgba(255, 152, 0, 0.2);
- animation: gpsPulseOrange 2s ease-in-out infinite;
-}
-
-@keyframes gpsPulse {
- 0% {
- box-shadow: 0 0 0 2px rgba(34, 197, 94, 0.2);
- }
- 50% {
- box-shadow: 0 0 0 6px rgba(34, 197, 94, 0.1);
- }
- 100% {
- box-shadow: 0 0 0 2px rgba(34, 197, 94, 0.2);
- }
-}
-
-@keyframes gpsPulseOrange {
- 0% {
- box-shadow: 0 0 0 2px rgba(255, 152, 0, 0.2);
- }
- 50% {
- box-shadow: 0 0 0 6px rgba(255, 152, 0, 0.1);
- }
- 100% {
- box-shadow: 0 0 0 2px rgba(255, 152, 0, 0.2);
- }
-}
-
-@media (max-width: 480px) {
- .consolidated-circulation-card {
- padding: 0.65rem 0.75rem;
- }
-
- .consolidated-circulation-card .card-row {
- gap: 0.5rem;
- }
-
- .consolidated-circulation-card .eta-badge {
- padding: 0.25rem 0.4rem;
- }
-}
diff --git a/src/frontend/app/root.css b/src/frontend/app/root.css
index d718d92..c880763 100644
--- a/src/frontend/app/root.css
+++ b/src/frontend/app/root.css
@@ -1,3 +1,5 @@
+@import "tailwindcss";
+
:root {
--colour-scheme: light;
--background-color: #ffffff;
@@ -122,8 +124,6 @@ body {
overflow-x: hidden;
}
-
-
.theme-toggle {
background: none;
border: none;
diff --git a/src/frontend/app/routes/estimates-$id.tsx b/src/frontend/app/routes/estimates-$id.tsx
index b92e59d..afeb3d2 100644
--- a/src/frontend/app/routes/estimates-$id.tsx
+++ b/src/frontend/app/routes/estimates-$id.tsx
@@ -302,7 +302,7 @@ export default function Estimates() {
<div className={`estimates-lines-container`}>
{stopData.lines.map((line) => (
<div key={line} className="estimates-line-icon">
- <LineIcon line={line} region={region} rounded />
+ <LineIcon line={line} region={region} mode="rounded" />
</div>
))}
</div>
diff --git a/src/frontend/app/routes/stops-$id.css b/src/frontend/app/routes/stops-$id.css
index 782d9a1..4d204a7 100644
--- a/src/frontend/app/routes/stops-$id.css
+++ b/src/frontend/app/routes/stops-$id.css
@@ -7,7 +7,6 @@
}
.estimates-list-container {
- overflow-y: auto;
flex: 1;
min-height: 0;
@@ -47,7 +46,6 @@
display: flex;
flex-direction: column;
height: 100%;
- overflow: hidden;
padding-block: 1rem;
box-sizing: border-box;
diff --git a/src/frontend/app/routes/stops-$id.tsx b/src/frontend/app/routes/stops-$id.tsx
index 4d96928..de552bd 100644
--- a/src/frontend/app/routes/stops-$id.tsx
+++ b/src/frontend/app/routes/stops-$id.tsx
@@ -238,7 +238,7 @@ export default function Estimates() {
<div className={`estimates-lines-container scrollable`}>
{stopData.lines.map((line) => (
<div key={line} className="estimates-line-icon">
- <LineIcon line={line} region={region} rounded />
+ <LineIcon line={line} region={region} mode="rounded" />
</div>
))}
</div>