:root {
    --bg: #f4f5f7;
    --card: #ffffff;
    --text: #16181d;
    --muted: #6b7280;
    --line: #e3e5e9;
    --accent: #2563eb;
    --ok: #16a34a;
    --warn: #d97706;
    --danger: #dc2626;
    --radius: 14px;
}

@media (prefers-color-scheme: dark) {
    :root {
        --bg: #0e1116;
        --card: #171b22;
        --text: #e8eaed;
        --muted: #9aa3af;
        --line: #262c36;
        --accent: #4f8bff;
    }
}

* { box-sizing: border-box; }

/* The browser's own `[hidden] { display: none }` is a *user-agent* rule, so any author `display:`
   here silently beats it — the element stays on screen, empty. (That's how the departure chip ended
   up as a ring around nothing once a trip started.) Restate it with author weight. */
[hidden] { display: none !important; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font: 16px/1.45 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}

.wrap { max-width: 560px; margin: 0 auto; padding: 12px 12px 48px; }

h1 { font-size: 1.35rem; margin: 0 0 .3em; }
h2 { font-size: 1.05rem; margin: 0 0 .6em; }

.muted { color: var(--muted); }
.small { font-size: .85rem; }
.strong { font-weight: 600; text-decoration: none; color: var(--text); }
.center { text-align: center; }
.big { font-size: 3rem; margin: 0; }

.topbar {
    display: flex; align-items: center; justify-content: space-between;
    gap: 8px; margin-bottom: 10px;
}

.card {
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 16px;
    margin-bottom: 12px;
}

.eta-card { text-align: center; }

/* When you're leaving — worth seeing before the arrival time, since it's the bit you control. */
.start-chip {
    display: inline-block;
    margin: 2px 0 4px;
    padding: 3px 10px;
    border-radius: 999px;
    border: 1px solid var(--line);
    background: var(--bg);
    color: var(--muted);
    font-size: .85rem;
    font-weight: 600;
}
.start-chip.overdue { color: var(--warn); border-color: var(--warn); }
.eta { font-size: 2.1rem; font-weight: 700; letter-spacing: -.02em; margin: 4px 0; }

.progress {
    height: 6px; border-radius: 3px; background: var(--line);
    overflow: hidden; margin-top: 12px;
}
.progress-fill {
    height: 100%; width: 0; background: var(--accent);
    transition: width .4s ease;
}

/* ---- stage panels ---- */

.panels { list-style: none; margin: 0 0 12px; padding: 0; display: grid; gap: 8px; }

.panel {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px;
    background: var(--card);
    border: 1px solid var(--line);
    border-left: 5px solid var(--line);
    border-radius: var(--radius);
    padding: 14px 14px;
    min-height: 62px;                 /* thumb-sized target */
    cursor: pointer;
    user-select: none;
}
.panels.readonly .panel { cursor: default; }
.panel:active { transform: scale(.99); }

.panel-main { display: flex; align-items: center; gap: 10px; min-width: 0; }
.icon { font-size: 1.4rem; }
.pcol { display: flex; flex-direction: column; min-width: 0; }
.pname { font-weight: 600; overflow: hidden; text-overflow: ellipsis; }
.ptransit { line-height: 1.25; }
.ptransit.late { color: var(--warn); font-weight: 600; }

/* One row per train of the journey — the changes you'd otherwise have to hold in your head. */
.pleg {
    font-size: .8rem;
    line-height: 1.35;
    color: var(--muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.pleg.current { color: var(--accent); font-weight: 600; }
.pleg.done { opacity: .45; text-decoration: line-through; }
.ptransit.pumping { color: var(--accent); font-weight: 600; }

.panel-side { text-align: right; flex: none; }
.mins { display: block; font-variant-numeric: tabular-nums; font-weight: 600; }
.state { display: block; font-size: .72rem; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }

.panel[data-state="active"] {
    border-left-color: var(--accent);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent);
}

/* ---- the current leg's icon moves, the way the leg does ----
   Only the active one, and only ever a couple of pixels: this is a status light, not a cartoon.
   A page you glance at in a car park should say "still going" without demanding attention. */

.panel[data-state="active"] .icon {
    display: inline-block;                 /* transforms don't apply to inline elements */
    will-change: transform;
    animation: 2.2s ease-in-out infinite nudge;
}

/* Things that roll on a road: a small forward push, then a drift back. */
.panel[data-state="active"][data-mode="car"] .icon,
.panel[data-state="active"][data-mode="bike"] .icon {
    animation: 1.8s cubic-bezier(.4, 0, .2, 1) infinite drive;
}

/* A bus rocks on its suspension — it pulls away, sways, settles. */
.panel[data-state="active"][data-mode="bus"][data-phase="riding"] .icon,
.panel[data-state="active"][data-mode="bus"]:not([data-phase]) .icon,
.panel[data-state="active"][data-mode="bus"][data-phase=""] .icon {
    animation: 1.5s ease-in-out infinite sway;
}

/* A train doesn't rock. It glides, with the faintest rhythm over the rail joints. */
.panel[data-state="active"][data-mode="train"][data-phase="riding"] .icon,
.panel[data-state="active"][data-mode="train"]:not([data-phase]) .icon,
.panel[data-state="active"][data-mode="train"][data-phase=""] .icon {
    animation: 2.6s cubic-bezier(.45, .05, .55, .95) infinite glide;
}

/* Not moving yet: you're on the platform watching the departure board. The icon shouldn't
   pretend to be going somewhere while you're still standing in the cold. */
.panel[data-state="active"][data-mode="bus"][data-phase="waiting"] .icon,
.panel[data-state="active"][data-mode="train"][data-phase="waiting"] .icon {
    animation: 2s ease-in-out infinite waiting;
}

/* Walking: a step-bob, with the faintest lean. */
.panel[data-state="active"][data-mode="walk"] .icon {
    animation: 0.9s ease-in-out infinite step;
}

/* A gas stop is two things, and the icon should show which: rolling toward the station… */
.panel[data-state="active"][data-mode="gas"][data-phase="travel"] .icon {
    animation: 1.8s cubic-bezier(.4, 0, .2, 1) infinite drive;
}
/* …then standing at the pump, filling. */
.panel[data-state="active"][data-mode="gas"][data-phase="service"] .icon {
    animation: 1.4s ease-in-out infinite fill;
}

@keyframes drive {
    0%   { transform: translateX(-3px); }
    60%  { transform: translateX(3px); }
    100% { transform: translateX(-3px); }
}

@keyframes step {
    0%, 100% { transform: translateY(0) rotate(-3deg); }
    50%      { transform: translateY(-3px) rotate(3deg); }
}

/* Bus: leans back as it pulls away, bounces once, settles. */
@keyframes sway {
    0%   { transform: translateX(-3px) rotate(-2deg); }
    35%  { transform: translateX(1px)  rotate(1.5deg) translateY(-1px); }
    55%  { transform: translateX(2px)  rotate(1deg)   translateY(1px); }
    75%  { transform: translateX(3px)  rotate(2deg); }
    100% { transform: translateX(-3px) rotate(-2deg); }
}

/* Train: a long, level run — no rocking, just a hint of a clack at the ends. */
@keyframes glide {
    0%   { transform: translateX(-5px); }
    48%  { transform: translateX(4px) translateY(-0.5px); }
    52%  { transform: translateX(5px) translateY(0.5px); }
    100% { transform: translateX(-5px); }
}

/* Waiting at the stop: shifting your weight, checking the board. Going nowhere. */
@keyframes waiting {
    0%, 100% { transform: rotate(-1.5deg); opacity: .65; }
    50%      { transform: rotate(1.5deg);  opacity: 1; }
}

@keyframes fill {
    0%, 100% { transform: scale(1);    opacity: .75; }
    50%      { transform: scale(1.15); opacity: 1; }
}

/* Anything else that's under way just breathes. */
@keyframes nudge {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.12); }
}

/* Motion can be actively unpleasant for some people, and the app is still perfectly usable
   without it — the active leg is already marked by colour, border and the word "active". */
@media (prefers-reduced-motion: reduce) {
    .panel[data-state="active"] .icon,
    .panel[data-state="active"][data-mode] .icon {
        animation: none;
    }
}
.panel[data-state="active"] .state { color: var(--accent); }
.panel[data-state="done"] { opacity: .55; border-left-color: var(--ok); }
.panel[data-state="skipped"] { opacity: .4; text-decoration: line-through; }

/* ---- buttons ---- */

.btn {
    appearance: none;
    border: 1px solid var(--line);
    background: var(--card);
    color: var(--text);
    border-radius: 10px;
    padding: 12px 14px;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.danger  { background: var(--danger); border-color: var(--danger); color: #fff; }
.btn.ghost   { background: transparent; }
.btn.small   { padding: 6px 10px; font-weight: 500; font-size: .85rem; }
.btn.big     { padding: 18px; font-size: 1.05rem; }

.actionbar { display: grid; gap: 8px; margin-bottom: 12px; }
.actionbar .btn.big { width: 100%; }

/* The connection picker: each row is a whole journey, not just a departure time. */
.conn-options { display: grid; gap: 6px; margin-bottom: 10px; }
.conn-option {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    text-align: left;
    padding: 10px 12px;
    border: 1px solid var(--line);
    border-radius: 10px;
    background: var(--card);
    color: var(--text);
    font: inherit;
    cursor: pointer;
}
.conn-option.pinned { border-color: var(--accent); }
.conn-time { font-weight: 600; font-variant-numeric: tabular-nums; }
.conn-meta { color: var(--muted); font-size: .85rem; }

.chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.chip {
    border: 1px solid var(--line); background: transparent; color: var(--text);
    border-radius: 999px; padding: 8px 12px; font: inherit; font-size: .9rem; cursor: pointer;
}

/* ---- forms ---- */

/* Date + a 24-hour time, because the native datetime picker follows the browser's locale. */
.when { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.when input[type="date"] { flex: 1; min-width: 150px; }
.when-time { display: flex; align-items: center; gap: 4px; flex: none; }
.when-time select { width: auto; padding: 12px 8px; font-variant-numeric: tabular-nums; }
.when-colon { color: var(--muted); font-weight: 600; }

.stack { display: grid; gap: 10px; }
.row { display: flex; gap: 10px; }
.row > * { flex: 1; }
label { display: grid; gap: 4px; font-size: .85rem; color: var(--muted); }
label.check { display: flex; align-items: center; gap: 8px; color: var(--text); font-size: 1rem; }
label.check input { width: auto; }

input, select {
    width: 100%;
    padding: 12px;
    border: 1px solid var(--line);
    border-radius: 10px;
    background: var(--bg);
    color: var(--text);
    font: inherit;
}

/* ---- address picker ---- */

.geo { display: grid; gap: 10px; }
.row.tight { gap: 6px; }
.row.tight .geo-search { flex: 0 0 auto; }

.geo-results {
    list-style: none; margin: 0; padding: 0;
    border: 1px solid var(--line); border-radius: 10px; overflow: hidden;
    background: var(--bg);
}
.geo-result {
    padding: 12px 14px; cursor: pointer; font-size: .9rem;
    border-bottom: 1px solid var(--line);
}
.geo-result:last-child { border-bottom: 0; }
.geo-result:hover, .geo-result:active { background: var(--card); }

details.card summary { cursor: pointer; font-weight: 600; }

/* One row per stage: what it is on the left, where it goes on the right. */
.stage-head {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
}
.stage-title { flex: 1; min-width: 0; }
.stage-arrows { display: flex; gap: 4px; flex: none; }

.arrow {
    appearance: none;
    border: 1px solid var(--line);
    background: var(--bg);
    color: var(--muted);
    border-radius: 8px;
    width: 34px;
    height: 30px;
    font-size: .8rem;
    line-height: 1;
    cursor: pointer;
}
.arrow:hover:not(:disabled) { color: var(--accent); border-color: var(--accent); }
.arrow:disabled { opacity: .3; cursor: default; }

.warn-text { color: var(--warn); font-weight: 600; }
.btn:disabled { opacity: .35; cursor: default; }

.stage-edit {
    border: 1px solid var(--line);
    border-radius: 10px;
    padding: 10px 12px;
    margin-bottom: 8px;
}
.stage-edit > summary {
    cursor: pointer;
    font-weight: 600;
    display: flex;          /* keeps the arrows on the right of the row, not below it */
    align-items: center;
    gap: 8px;
}
.stage-edit > summary::-webkit-details-marker { display: none; }
.stage-edit > summary::before {
    content: '▸';
    color: var(--muted);
    flex: none;
    transition: transform .15s ease;
}
.stage-edit[open] > summary::before { transform: rotate(90deg); }
.stage-edit[open] > summary { margin-bottom: 12px; }

/* Test-mode panel: should never be mistaken for a normal control. */
details.card.test {
    border-color: var(--warn);
    border-style: dashed;
}
details.card.test > summary { color: var(--warn); }
details.card[open] summary { margin-bottom: 12px; }

/* ---- trip rows ----
   The row is one big target that opens the trip you control. The friend's link is a copy button,
   not a link: a link there is a trap, because a near-miss silently drops you on the read-only page
   and you don't notice until you wonder why nothing responds to your taps. */

.trips { gap: 8px; }

.trip-row {
    display: flex;
    align-items: stretch;
    gap: 8px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    overflow: hidden;
}

.trip-open {
    flex: 1;
    min-width: 0;
    min-height: 60px;                 /* a thumb, not a fingernail */
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    padding: 10px 14px;
    text-decoration: none;
    color: var(--text);
}
.trip-open:hover, .trip-open:active { background: var(--bg); }
.trip-name { font-weight: 600; display: flex; align-items: center; gap: 8px; min-width: 0; }
.trip-name > :first-child { overflow: hidden; text-overflow: ellipsis; }

.trip-actions {
    display: flex;
    align-items: center;
    gap: 4px;
    padding-right: 8px;
    flex: none;
}
.trip-actions .btn { white-space: nowrap; }

/* Square, thumb-sized, and out of the way — so the row itself keeps the space. */
.icon-btn {
    width: 44px;
    height: 42px;
    padding: 0;
    font-size: 1rem;
    display: flex;
    align-items: center;
    justify-content: center;
}
.danger-text { color: var(--danger); }

.list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.list-row {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 8px 0; border-bottom: 1px solid var(--line);
}
.list-row:last-child { border-bottom: 0; }

.pill {
    font-size: .7rem; text-transform: uppercase; letter-spacing: .04em;
    padding: 2px 8px; border-radius: 999px; border: 1px solid var(--line); color: var(--muted);
}
.pill.active { color: #fff; background: var(--accent); border-color: var(--accent); }

.alert {
    background: color-mix(in srgb, var(--danger) 12%, transparent);
    border: 1px solid var(--danger);
    color: var(--danger);
    border-radius: var(--radius);
    padding: 12px 14px;
    font-weight: 600;
}
.banner { margin-bottom: 12px; }

/* A late bus is worth saying out loud, but it isn't the same as "the car won't start". */
.alert.warn {
    background: color-mix(in srgb, var(--warn) 12%, transparent);
    border-color: var(--warn);
    color: var(--warn);
}

.gps {
    font-size: .75rem; padding: 4px 10px; border-radius: 999px;
    border: 1px solid var(--line); color: var(--muted);
}
.gps.ok { color: var(--ok); border-color: var(--ok); }
.gps.warn { color: var(--warn); border-color: var(--warn); }
