/* shop.css
 *
 * The look of the ticket shop pages: start page, ticket shop, shopping
 * basket and seat reservation. One file for all of them, so that a
 * change of the colours or the card style reaches every page.
 *
 * The brand colour is the one colors.css has always used, #0053A0;
 * everything else is derived from it. Sizes are in rem so that the
 * pages follow the browser's font size, and every layout falls back to
 * one column on a narrow screen.
 */

:root {
    --tx-blue: #0053a0;
    --tx-blue-dark: #003c74;
    --tx-blue-light: #e8f0f8;
    --tx-ink: #1b1b1b;
    --tx-muted: #5a6470;
    --tx-line: #d5dce4;
    --tx-bg: #f2f5f8;
    --tx-card: #ffffff;
    --tx-ok: #0a7d33;
    --tx-warn: #b3261e;
    --tx-radius: 10px;
    --tx-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 6px 18px rgba(0, 0, 0, .06);
}

html {
    box-sizing: border-box;
}

*, *::before, *::after {
    box-sizing: inherit;
}

/* A hidden element stays hidden: the display rules below would
   otherwise override the hidden attribute. */
[hidden] {
    display: none !important;
}

body.tx-page {
    margin: 0;
    background: var(--tx-bg);
    color: var(--tx-ink);
    font-family: system-ui, -apple-system, "Segoe UI", Arial, sans-serif;
    font-size: 16px;
    line-height: 1.5;
}

/* Header: logo, title, basket badge, menu */

.tx-header {
    background: var(--tx-blue);
    color: #fff;
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: .6rem 1rem;
}

.tx-header img {
    height: 48px;
}

.tx-header .tx-title {
    font-weight: 600;
    line-height: 1.2;
}

.tx-header .tx-title span {
    display: block;
    font-weight: 400;
    font-size: .85rem;
    opacity: .85;
}

.tx-header .tx-spacer {
    flex: 1 1 auto;
}

.tx-header a,
.tx-header button {
    color: #fff;
}

/* On the blue ground the two button kinds have to swap their colours:
   the leading action is the white one, the secondary an outline. */

.tx-header .tx-button {
    background: #fff;
    border-color: #fff;
    color: var(--tx-blue);
}

.tx-header .tx-button:hover:not(:disabled) {
    background: var(--tx-blue-light);
    color: var(--tx-blue-dark);
}

.tx-header .tx-button-secondary {
    background: transparent;
    border-color: rgba(255, 255, 255, .7);
    color: #fff;
}

.tx-header .tx-button-secondary:hover:not(:disabled) {
    background: rgba(255, 255, 255, .15);
    color: #fff;
}

.tx-basket {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    text-decoration: none;
    font-weight: 600;
}

.tx-basket-count {
    background: #fff;
    color: var(--tx-blue);
    border-radius: 999px;
    min-width: 1.6rem;
    padding: 0 .4rem;
    text-align: center;
    font-size: .9rem;
    line-height: 1.6rem;
}

/* Menu: a details element, so it needs no script */

.tx-menu {
    position: relative;
}

.tx-menu > summary {
    list-style: none;
    cursor: pointer;
    padding: .2rem .5rem;
    border: 1px solid rgba(255, 255, 255, .6);
    border-radius: var(--tx-radius);
}

.tx-menu > summary::-webkit-details-marker {
    display: none;
}

.tx-menu[open] > summary {
    background: var(--tx-blue-dark);
}

.tx-menu-items {
    position: absolute;
    right: 0;
    top: calc(100% + .4rem);
    background: var(--tx-card);
    border: 1px solid var(--tx-line);
    border-radius: var(--tx-radius);
    box-shadow: var(--tx-shadow);
    min-width: 12rem;
    z-index: 50;
    overflow: hidden;
}

.tx-menu-items a {
    display: block;
    padding: .6rem .9rem;
    color: var(--tx-ink);
    text-decoration: none;
}

.tx-menu-items a:hover {
    background: var(--tx-blue-light);
}

/* Main area and cards */

.tx-main {
    max-width: 52rem;
    margin: 0 auto;
    padding: 1.2rem 1rem 3rem 1rem;
}

.tx-card {
    background: var(--tx-card);
    border: 1px solid var(--tx-line);
    border-radius: var(--tx-radius);
    box-shadow: var(--tx-shadow);
    padding: 1.1rem 1.2rem;
    margin-bottom: 1rem;
}

.tx-card h1,
.tx-card h2 {
    margin: 0 0 .8rem 0;
    font-size: 1.3rem;
    color: var(--tx-blue);
}

.tx-card p {
    margin: 0 0 .8rem 0;
}

.tx-note {
    color: var(--tx-muted);
    font-size: .9rem;
}

/* Form fields */

.tx-field {
    display: block;
    margin-bottom: .9rem;
}

.tx-field > span {
    display: block;
    font-size: .85rem;
    font-weight: 600;
    color: var(--tx-muted);
    letter-spacing: .02em;
    text-transform: uppercase;
    margin-bottom: .25rem;
}

.tx-field select,
.tx-field input {
    width: 100%;
    font: inherit;
    padding: .6rem .7rem;
    border: 1px solid var(--tx-line);
    border-radius: var(--tx-radius);
    background: #fff;
    color: var(--tx-ink);
}

.tx-field select:focus,
.tx-field input:focus {
    outline: 2px solid var(--tx-blue);
    outline-offset: 1px;
}

.tx-row {
    display: flex;
    gap: .9rem;
    flex-wrap: wrap;
}

.tx-row > .tx-field {
    flex: 1 1 14rem;
}

/* Buttons */

.tx-button {
    font: inherit;
    font-weight: 600;
    padding: .65rem 1.4rem;
    border-radius: var(--tx-radius);
    border: 1px solid var(--tx-blue);
    background: var(--tx-blue);
    color: #fff;
    cursor: pointer;
}

.tx-button:hover:not(:disabled) {
    background: var(--tx-blue-dark);
    border-color: var(--tx-blue-dark);
}

.tx-button:disabled {
    opacity: .5;
    cursor: default;
}

.tx-button-secondary {
    background: #fff;
    color: var(--tx-blue);
}

.tx-button-secondary:hover:not(:disabled) {
    background: var(--tx-blue-light);
    color: var(--tx-blue-dark);
}

.tx-actions {
    display: flex;
    gap: .8rem;
    flex-wrap: wrap;
    align-items: center;
}

/* Link list under the card */

.tx-links {
    display: flex;
    gap: 1.2rem;
    flex-wrap: wrap;
    padding: .2rem .2rem 0 .2rem;
}

.tx-links a {
    color: var(--tx-blue);
    text-decoration: none;
    font-weight: 600;
}

.tx-links a:hover {
    text-decoration: underline;
}

.tx-status {
    min-height: 1.5rem;
    color: var(--tx-muted);
}

.tx-status.tx-error {
    color: var(--tx-warn);
}

@media (max-width: 30rem) {
    .tx-header {
        flex-wrap: wrap;
        gap: .6rem;
    }

    .tx-header img {
        height: 36px;
    }

    .tx-main {
        padding: .8rem .7rem 2rem .7rem;
    }
}

/* The shop's five steps
 *
 * Each step is one card with three states, which the shop switches by
 * display: the closed heading, the open form, and the summary of what
 * was chosen. The heading of a closed step is a button-like line: it
 * reopens the step.
 */

.tx-step > h2 {
    margin: 0;
}

.tx-step-init {
    cursor: pointer;
}

.tx-step-init:hover h2 {
    color: var(--tx-blue-dark);
}

.tx-step-done {
    cursor: pointer;
}

.tx-step-summary {
    display: flex;
    align-items: baseline;
    gap: .6rem;
    flex-wrap: wrap;
    font-size: 1.1rem;
    margin-top: .3rem;
}

.tx-step-summary .tx-arrow {
    color: var(--tx-muted);
}

.tx-product-buttons {
    display: flex;
    gap: .6rem;
    flex-wrap: wrap;
    margin-bottom: .9rem;
}

.tx-count {
    background: var(--tx-blue);
    color: #fff;
    border-radius: 999px;
    min-width: 1.8rem;
    padding: 0 .5rem;
    text-align: center;
    font-weight: 600;
    float: right;
}

.gateway_option {
    display: block;
    padding: .35rem 0;
}

/* Full-page dialogs: session expired, purchase running, purchase done */

.tx-dialog {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, .55);
    visibility: hidden;
    z-index: 900;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
}

.tx-dialog-expiry {
    z-index: 1001;
}

/* Messages and progress must be readable over anything else, the
   full-screen ticket included. */

.tx-dialog-top {
    z-index: 2100;
}

.tx-dialog-box {
    background: var(--tx-card);
    border-radius: var(--tx-radius);
    box-shadow: var(--tx-shadow);
    padding: 1.5rem;
    max-width: 30rem;
    width: 100%;
    text-align: center;
}

.tx-dialog-box h2 {
    margin-top: 0;
    color: var(--tx-blue);
}

/* The busy indicator of the shop */

.tx-spinner {
    position: fixed;
    left: 50%;
    top: 50%;
    width: 4rem;
    height: 4rem;
    margin: -2rem 0 0 -2rem;
    border: .5rem solid var(--tx-blue-light);
    border-top-color: var(--tx-blue);
    border-radius: 50%;
    animation: tx-spin 1.2s linear infinite;
    display: none;
    z-index: 800;
}

@keyframes tx-spin {
    to { transform: rotate(360deg); }
}

/* Dialogs of the browser (login, passenger names) */

dialog {
    border: 1px solid var(--tx-line);
    border-radius: var(--tx-radius);
    box-shadow: var(--tx-shadow);
    padding: 1.2rem;
    max-width: 30rem;
}

dialog::backdrop {
    background: rgba(0, 0, 0, .5);
}

dialog label {
    display: block;
    margin-bottom: .7rem;
}

dialog label input {
    width: 100%;
    font: inherit;
    padding: .5rem .6rem;
    border: 1px solid var(--tx-line);
    border-radius: var(--tx-radius);
}

dialog input[type="submit"] {
    font: inherit;
    font-weight: 600;
    padding: .55rem 1.2rem;
    border-radius: var(--tx-radius);
    border: 1px solid var(--tx-blue);
    background: var(--tx-blue);
    color: #fff;
    cursor: pointer;
}

/* The seat map
 *
 * Instead of paging through legs and coaches with arrows, both are
 * shown as rows of chips: what there is, where the traveller is, and
 * how far each part has got. The colour of a leg chip is the state of
 * its reservations, the same colours as the seats themselves.
 */

.tx-chips {
    display: flex;
    gap: .5rem;
    flex-wrap: wrap;
}

.tx-chip {
    font: inherit;
    text-align: left;
    padding: .45rem .8rem;
    border: 1px solid var(--tx-line);
    border-radius: var(--tx-radius);
    background: #fff;
    color: var(--tx-ink);
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: .5rem;
}

.tx-chip:hover {
    border-color: var(--tx-blue);
}

.tx-chip-current {
    border-color: var(--tx-blue);
    background: var(--tx-blue-light);
    font-weight: 600;
}

.tx-chip-label {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
}

.tx-chip-label small {
    font-weight: 400;
    color: var(--tx-muted);
}

/* The state of one part of the journey, as a dot on its chip */

.tx-dot {
    width: .8rem;
    height: .8rem;
    border-radius: 50%;
    border: 1px solid var(--tx-line);
    flex: 0 0 auto;
}

.tx-dot-open { background: #fff; }
.tx-dot-waiting { background: #f2c200; }
.tx-dot-done { background: var(--tx-ok); }
.tx-dot-denied { background: var(--tx-warn); }
.tx-dot-none { background: var(--tx-line); }

.tx-seat-status {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .6rem;
    margin-bottom: .8rem;
}

.tx-seat-status strong {
    font-size: 1.1rem;
    color: var(--tx-blue);
}

.tx-legend {
    display: flex;
    flex-wrap: wrap;
    gap: .9rem;
    margin: .9rem 0;
    font-size: .85rem;
    color: var(--tx-muted);
}

.tx-legend span {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
}

.tx-swatch {
    width: .9rem;
    height: .9rem;
    border-radius: 3px;
    border: 1px solid var(--tx-line);
    display: inline-block;
}

.tx-swatch-free { background: #fff; }
.tx-swatch-mine { background: #0a7d33; }
.tx-swatch-waiting { background: #f2c200; }
.tx-swatch-denied { background: #b3261e; }
.tx-swatch-taken { background: #333a42; }
.tx-swatch-other { background: #5a6470; }

/* The seat plan itself: a wide drawing that may scroll vertically */

.tx-canvas-box {
    background: #e4e8ee;
    border-radius: var(--tx-radius);
    padding: .5rem;
    max-height: 60vh;
    overflow-y: auto;
    width: fit-content;
    max-width: 100%;
    margin: 0 auto;
}

.tx-canvas-box canvas {
    display: block;
    margin: 0 auto;
    touch-action: manipulation;
}

/* Step 3: one tally per travel class
 *
 * The count is a circle in the class colour, next to the class name and
 * the minus button that takes one passenger off the list again. There is
 * deliberately no clear-all: at step 4 the tickets have seats, and
 * dropping all of them at one tap would throw those away unnoticed.
 */

.tx-tallies {
    display: flex;
    flex-direction: column;
    gap: .6rem;
    margin: 1rem 0;
}

.tx-tally {
    display: flex;
    align-items: center;
    gap: .8rem;
    padding: .5rem .6rem;
    border: 1px solid var(--tx-line);
    border-radius: var(--tx-radius);
    background: #fff;
    max-width: 30rem;
}

.tx-tally-count {
    flex: 0 0 auto;
    width: 2.4rem;
    height: 2.4rem;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    color: #fff;
    background: var(--tx-blue);
}

.tx-tally-c1 { background: var(--tx-blue); }
.tx-tally-c2 { background: #0a7d33; }
.tx-tally-c3 { background: #a05a00; }
.tx-tally-c4 { background: #5b3a9e; }

.tx-tally-label {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
    flex: 1 1 auto;
    font-weight: 600;
}

.tx-tally-label small {
    font-weight: 400;
    color: var(--tx-muted);
}

.tx-tally-remove {
    flex: 0 0 auto;
    font: inherit;
    font-size: 1.3rem;
    line-height: 1;
    width: 2.2rem;
    height: 2.2rem;
    border-radius: 50%;
    border: 1px solid var(--tx-line);
    background: #fff;
    color: var(--tx-ink);
    cursor: pointer;
}

.tx-tally-remove:hover {
    border-color: var(--tx-warn);
    color: var(--tx-warn);
}

/* The purchased tickets
 *
 * One card per ticket: when and where on the head line, the reservations
 * folded out below it, and the two actions at the bottom. The head is a
 * button, so it works by keyboard as well as by tap.
 */

.tx-purchase-head {
    font-size: 1rem;
    font-weight: 600;
    color: var(--tx-muted);
    margin: 1.4rem 0 .6rem 0;
}

.tx-ticket {
    background: var(--tx-card);
    border-radius: var(--tx-radius);
    box-shadow: var(--tx-shadow);
    margin-bottom: 1rem;
    overflow: hidden;
}

/* The head of a ticket card is two rows, which is what a phone needs:
   when and in what state on the first, where and what on the second,
   full width. The wide screen keeps the same shape -- one layout is
   easier to keep right than two. */

.tx-ticket-head {
    font: inherit;
    text-align: left;
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: .35rem;
    padding: 1rem;
    border: 0;
    background: none;
    color: var(--tx-ink);
    cursor: pointer;
}

.tx-ticket-topline {
    display: flex;
    align-items: center;
    gap: .8rem;
    width: 100%;
}

.tx-ticket-head:hover {
    background: var(--tx-blue-light);
}

.tx-ticket-when {
    flex: 1 1 auto;
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: .5rem;
    line-height: 1.3;
}

.tx-ticket-when strong {
    color: var(--tx-blue);
}

.tx-ticket-what {
    display: flex;
    flex-direction: column;
    line-height: 1.35;
    width: 100%;
}

/* On a wide screen everything fits on one line, and that reads better:
   when, where, state. The markup stays as it is -- the row that groups
   date and state for the phone dissolves into its parent with
   display:contents, and the order puts the pieces back in place. */

@media (min-width: 700px) {
    .tx-ticket-head {
        flex-direction: row;
        align-items: center;
        gap: 1rem;
    }

    .tx-ticket-topline {
        display: contents;
    }

    .tx-ticket-when {
        order: 1;
        flex: 0 0 auto;
        flex-direction: column;
        align-items: flex-start;
        gap: 0;
        min-width: 7rem;
    }

    .tx-ticket-what {
        order: 2;
        width: auto;
        flex: 1 1 auto;
    }

    .tx-ticket-status {
        order: 3;
    }

    .tx-ticket-caret {
        order: 4;
    }
}

.tx-ticket-when small,
.tx-ticket-what small {
    color: var(--tx-muted);
}

.tx-ticket-caret {
    flex: 0 0 auto;
    color: var(--tx-blue);
    font-size: 1.2rem;
}

.tx-ticket-details {
    padding: 0 1rem 1rem 1rem;
}

.tx-ticket-actions {
    display: flex;
    flex-wrap: wrap;
    gap: .8rem;
    padding: 0 1rem 1rem 1rem;
}

.tx-rv-head {
    font-weight: 600;
    color: var(--tx-blue);
    border-top: 1px solid var(--tx-line);
    padding-top: .8rem;
    margin-bottom: .4rem;
}

.tx-rv-line {
    display: flex;
    flex-wrap: wrap;
    gap: .6rem;
    margin-top: .5rem;
}

.tx-rv-line span:first-child {
    font-weight: 600;
    min-width: 7rem;
}

.tx-rv-seat {
    display: flex;
    flex-wrap: wrap;
    gap: .6rem;
    color: var(--tx-muted);
}

.tx-rv-seat span:first-child {
    min-width: 7rem;
}

.tx-rv-none {
    color: var(--tx-muted);
    border-top: 1px solid var(--tx-line);
    padding-top: .8rem;
}

/* A card that carries a warning rather than a step */

.tx-card-warn {
    border-left: 4px solid var(--tx-warn);
}

/* The bar that fills while a ticket PDF is being built */

.tx-progress {
    height: 1rem;
    border-radius: var(--tx-radius);
    background: var(--tx-blue-light);
    overflow: hidden;
    margin: 1rem 0;
}

.tx-progress-fill {
    height: 100%;
    width: 0;
    background: var(--tx-blue);
}

/* The ticket shown full screen, for the conductor to scan */

.tx-dialog-full {
    padding: 0;
    z-index: 2000;
}

.tx-dialog-fullbox {
    position: relative;
    width: 100%;
    height: 100%;
    background: var(--tx-card);
}

/* What the passenger is told about his ticket. Green while the ticket is
   his to use, grey once it is spent, red when something is wrong with
   it. The conductor's finer distinctions are not shown here; see the
   comment in purchasedtickets.js. */

.tx-ticket-status {
    flex: 0 0 auto;
    font-size: .85rem;
    font-weight: 600;
    padding: .2rem .6rem;
    border-radius: 999px;
    white-space: nowrap;
}

.tx-ticket-good {
    background: #e4f2e8;
    color: #0a7d33;
}

.tx-ticket-spent {
    background: var(--tx-blue-light);
    color: var(--tx-muted);
}

.tx-ticket-bad {
    background: #fbe6e4;
    color: var(--tx-warn);
}

/* A ticket the server has not been asked about yet: the page must not
   call it valid on its own authority. */

.tx-ticket-unchecked {
    background: var(--tx-blue-light);
    color: var(--tx-muted);
}

/* The purchase code, shown with each purchase */

.tx-purchase-code {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .6rem;
    margin-bottom: .8rem;
}

.tx-code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: .08em;
    background: #fff;
    border: 1px solid var(--tx-line);
    border-radius: var(--tx-radius);
    padding: .3rem .7rem;
    user-select: all;
}

.tx-purchase-code .tx-button {
    padding: .35rem .9rem;
}

.tx-purchase-code-hint {
    flex-basis: 100%;
}

/* Numbered instructions, as on the install hint */

.tx-steps {
    margin: .8rem 0;
    padding-left: 1.3rem;
    line-height: 1.5;
}

.tx-steps li {
    margin-bottom: .4rem;
}
