/* Patient App — ZAR branding */

*, *::before, *::after { box-sizing: border-box; }

/* Senior-friendly base size — matches the staff view root (styles.css: html { font-size: 18px }) */
html { font-size: 18px; }

:root {
    --zar-dark-green: #087323;
    --zar-light-green: #b6c600;
    --zar-red: #d40232;
    --zar-gray: #58585a;
    --zar-bg: #f5f5f5;
}

body {
    margin: 0;
    font-family: Arial, Helvetica, sans-serif;
    background: var(--zar-bg);
    color: #222;
    min-height: 100vh;
}

/* Header */

.patient-header {
    background: var(--zar-dark-green);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: flex-start; /* logo + Abmelden packed on the left, right side of the band left free */
    gap: 1rem;
    padding: 0 1rem;
    height: 56px;
    position: sticky;
    top: 0;
    z-index: 100;
}

/* ZAR logo — staff parity (styles.css: .app-logo { height: 2.59rem; opacity: 0.75 }).
   The staff -16mm overlap hack is intentionally omitted: it would break the flex header. */
.app-logo {
    height: 2.59rem;
    width: auto;
    opacity: 0.75;
}

/* Sprint 042: on the three entry pages the logo sits at the far right of the bar, the heading at the
   far left. Scoped to the modifier rather than changing .patient-header's justify-content, because
   that rule is shared with the appointment list, where logo and "Abmelden" stay packed on the left
   (Sprint 010). AppointmentListUnchangedUiIT is the guard for exactly that. Sprint 063 removed the
   dot that originally kept the right-hand side free; the arrangement is deliberately unchanged. */
.patient-header--entry .app-logo {
    margin-left: auto;
}

.patient-header h1 {
    font-size: 1.1rem;
    font-weight: bold;
    margin: 0;
    letter-spacing: 0.02em;
}

.patient-header button {
    background: transparent;
    color: #fff;
    border: 1px solid rgba(255,255,255,0.6);
    border-radius: 4px;
    padding: 6px 14px;
    cursor: pointer;
    font-size: 1rem;
}

.patient-header button:hover {
    background: rgba(255,255,255,0.15);
}

/* Cards / containers */

.patient-card {
    background: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.08);
    padding: 2rem;
    max-width: 420px;
    margin: 2rem auto;
}

.patient-card h2 {
    color: var(--zar-dark-green);
    margin-top: 0;
    margin-bottom: 1.5rem;
    font-size: 1.3rem;
}

/* Sprint 041: the "Anmeldung läuft…" line. It is what a returning patient sees while the app hands
   over to the clinic login page, so it must read as a quiet status line and not as another screen
   asking them for something — one centred sentence, nothing to tap. */

.login-starting {
    text-align: center;
}

.login-starting p {
    margin: 0;
    color: var(--zar-gray);
    font-size: 1rem;
}

/* Form elements */

.form-group {
    margin-bottom: 1.2rem;
}

.form-group label {
    display: block;
    font-weight: bold;
    margin-bottom: 0.4rem;
    color: var(--zar-gray);
    font-size: 0.9rem;
}

.form-group input {
    width: 100%;
    padding: 0.6rem 0.8rem;
    border: 1px solid #ccc;
    border-radius: 4px;
    font-size: 1rem;
    transition: border-color 0.15s;
}

.form-group input:focus {
    outline: none;
    border-color: var(--zar-dark-green);
    box-shadow: 0 0 0 2px rgba(8,115,35,0.15);
}

.btn-primary {
    display: block;
    width: 100%;
    padding: 0.75rem;
    background: var(--zar-dark-green);
    color: #fff;
    border: none;
    border-radius: 4px;
    font-size: 1rem;
    font-weight: bold;
    cursor: pointer;
    margin-top: 0.5rem;
    min-height: 44px;
}

.btn-primary:hover {
    background: #065c1c;
}

.btn-secondary {
    display: block;
    width: 100%;
    padding: 0.75rem;
    background: var(--zar-light-green);
    color: #222;
    border: none;
    border-radius: 4px;
    font-size: 1rem;
    font-weight: bold;
    cursor: pointer;
    margin-top: 0.5rem;
    min-height: 44px;
}

.btn-secondary:hover {
    background: #9db000;
}

.divider {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 1.5rem 0;
    color: var(--zar-gray);
    font-size: 0.85rem;
}

.divider::before,
.divider::after {
    content: '';
    flex: 1;
    border-top: 1px solid #ddd;
}

/* Sprint 039: explains why the activation-code fallback has appeared. Muted like the other
   supporting copy on the card, so the passkey login stays the primary action. */
#fallback-hint {
    margin: 0 0 0.75rem;
    color: var(--zar-gray);
    font-size: 0.9rem;
    line-height: 1.4;
}

/* Error / info messages */

.error-message {
    background: #fde8ec;
    border: 1px solid var(--zar-red);
    color: var(--zar-red);
    border-radius: 4px;
    padding: 0.75rem;
    margin-bottom: 1rem;
    font-size: 0.9rem;
    display: none;
}

.error-message.visible {
    display: block;
}

/* Appointment tabs */

/* Sticky tab bar — static-page equivalent of the staff vaadin-tabsheet scroll container.
   Stays visible below the sticky header while the appointment list scrolls. */
.tab-bar-wrap {
    position: sticky;
    top: 56px;
    z-index: 120; /* above the sticky header (z-index:100). Kept as Sprint 010 set it: with the dot gone (Sprint 063) the two never overlap, and lowering it would reorder this block against the header, the error message and the expired-login message for no gain */
    background: var(--zar-bg);
}

.tab-bar {
    display: flex;
    flex-wrap: wrap; /* when the four senior-sized tabs don't fit, wrap onto more lines (stack) instead of clipping or sideways-scrolling */
    border-bottom: 2px solid var(--zar-light-green);
}

.tab-btn {
    flex: 1 1 0; /* four equal-width tabs on one line, like the staff vaadin-tab (flex:1) — so left:87.5% lands on the centre of "Gesamt" */
    min-width: max-content; /* never shrink a tab below its full label: guarantees no label is clipped and forces the row to wrap when it can't fit (replaces the old 44px floor; max-content is always wider than 44px here) */
    padding: 0.65rem 1.1rem;
    border: none;
    background: var(--zar-dark-green);
    color: #fff;
    cursor: pointer;
    font-size: 1rem;
    white-space: nowrap;
    min-height: 44px;
}

/* Sprint 045 — when the shown appointments were fetched, and the way to fetch them again.
   Sits inside .tab-bar-wrap so it stays reachable while the list scrolls, but outside .tab-bar:
   that row's children are counted by the Sprint 011 wrap checks. Since Sprint 063 this row and the
   stored-copy line below it are the only statements the page makes about how current the list is. */
.refresh-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.4rem 0.75rem;
    background: var(--zar-bg);
    border-bottom: 1px solid rgba(0,0,0,0.08);
}

.last-updated {
    font-size: 0.85rem; /* 15.3px — quieter than the appointments, still above the 14px floor */
    color: var(--zar-gray);
}

/* Sprint 058: how old the shown list is, when it came from the device rather than from the clinic.
   Deliberately as quiet as the line above it and styled identically at every age (decision E9): no
   colour that deepens with age, no border, no icon. A warning that grows would train patients to
   ignore it, and the one thing this line must do is be read. */
.cache-age {
    display: none;
    padding: 0.35rem 0.75rem;
    background: var(--zar-bg);
    border-bottom: 1px solid rgba(0,0,0,0.08);
    font-size: 0.85rem; /* the same size as "Zuletzt aktualisiert um …" — neither shouts */
    color: var(--zar-gray);
}

.cache-age.visible {
    display: block;
}

.refresh-btn {
    flex: 0 0 auto;
    min-height: 44px; /* thumb-sized, same floor as the category buttons */
    padding: 0.4rem 1.1rem;
    border: 1px solid var(--zar-dark-green);
    border-radius: 4px;
    background: #fff;
    color: var(--zar-dark-green);
    font-size: 1rem;
    font-weight: bold;
    cursor: pointer;
}

.refresh-btn:hover {
    background: var(--zar-dark-green);
    color: #fff;
}

/* The message after a refresh that did not work. Uses the page's existing error styling, so it
   looks like every other thing that goes wrong in this app; it is hidden until it has something
   to say and disappears again on the next successful fetch. */
#refresh-error {
    margin: 0;
    padding: 0.5rem 0.75rem;
    font-size: 0.9rem;
}

/* Sprint 047: the expired-login notice. Not styled as an error, deliberately — nothing has gone
   wrong, a login has simply run out, and red would tell an elderly patient that they broke
   something. It sits in the sticky block so it is readable at any scroll position, and it wraps
   onto two rows on a narrow phone so the button never gets squeezed below thumb size. */
.session-expired {
    display: none;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem 0.75rem;
    margin: 0;
    padding: 0.5rem 0.75rem;
    background: #fff8e1;
    border-top: 1px solid rgba(0,0,0,0.08);
    border-bottom: 2px solid var(--zar-dark-green);
    color: #4a3b00;
    font-size: 0.9rem;
    line-height: 1.35;
}

.session-expired.visible {
    display: flex;
}

#session-expired-text {
    flex: 1 1 12rem; /* keeps the sentence and the button on one row when there is room, wraps when not */
}

.relogin-btn {
    flex: 0 0 auto;
    min-height: 44px; /* thumb-sized, same floor as "Aktualisieren" and the category buttons */
    padding: 0.4rem 1.1rem;
    border: 1px solid var(--zar-dark-green);
    border-radius: 4px;
    background: var(--zar-dark-green);
    color: #fff;
    font-size: 1rem;
    font-weight: bold;
    cursor: pointer;
}

.relogin-btn:hover {
    background: #fff;
    color: var(--zar-dark-green);
}

.tab-btn.active {
    background: var(--zar-light-green);
    color: #222;
    font-weight: bold;
}

.tab-btn:hover:not(.active) {
    background: #065c1c;
}

.tab-panel {
    display: none;
    padding: 1rem;
}

.tab-panel.active {
    display: block;
}

/* Appointment cards */

.day-heading {
    background: var(--zar-light-green);
    color: #222;
    font-weight: bold;
    padding: 0.4rem 0.75rem;
    margin: 0.75rem 0 0.4rem;
    border-radius: 4px 4px 0 0;
    font-size: 1rem;
}

.appointment-card {
    background: #fff;
    border-left: 4px solid var(--zar-dark-green);
    padding: 0.5rem 0.75rem;
    margin-bottom: 0.4rem;
    border-radius: 0 4px 4px 0;
    font-size: 1rem;
}

.appointment-card .time-treatment {
    font-weight: bold;
    color: #222;
}

.appointment-card .room {
    color: var(--zar-gray);
    font-size: 0.95rem;
    margin-top: 2px;
}

.appointment-card .hinweistext-highlight {
    font-style: italic;
    background: #edf7e8;
    border-radius: 3px;
    padding: 2px 5px;
    margin-top: 4px;
    display: inline-block;
    color: #222;
}

.no-appointments {
    color: var(--zar-gray);
    font-style: italic;
    padding: 1rem 0;
    text-align: center;
}

/* Spinner */

.spinner {
    text-align: center;
    padding: 2rem;
    color: var(--zar-gray);
}

/* Ended screen */

.ended-screen {
    text-align: center;
    padding: 3rem 1rem;
}

.ended-screen .ended-icon {
    font-size: 3rem;
    color: var(--zar-dark-green);
    margin-bottom: 1rem;
}

.ended-screen h2 {
    color: var(--zar-dark-green);
    font-size: 1.4rem;
}

.ended-screen p {
    color: var(--zar-gray);
}
