/* ==========================================================================
   Booking Calendar — visual system
   --------------------------------------------------------------------------
   Bootstrap supplies components and layout; this file supplies the look. It
   layers four things on top of Bootstrap's defaults:

     1. Tokens. One palette, one type scale, one set of radii and shadows, all
        as custom properties, so no component invents its own colour.
     2. Controls. Form inputs, selects, menus, pagination and dialogs are
        restyled from scratch - Bootstrap's defaults are flat and cramped, and
        a booking form is the thing an operator actually uses all day.
     3. Typography. A readable base size, a real heading rhythm, and an explicit
        hierarchy of muted text, so "quiet" always means the same shade.
     4. FullCalendar. Its Classic theme is entirely token-driven, so the
        calendar is re-skinned by overriding its --fc-classic-* variables
        rather than by fighting its selectors.

   The palette is deliberately warm rather than blue-grey. This is a screen
   someone sits in front of at a front desk, and a warm canvas with a single
   deep teal accent reads as hospitality rather than as a generic admin panel.
   ========================================================================== */

:root {
    /* --- Palette ------------------------------------------------------- */
    --brand-50: #eef7f5;
    --brand-100: #d3ece7;
    --brand-200: #a7d9d0;
    --brand-400: #2f9c8b;
    --brand-500: #16897c;
    --brand-600: #12756a;
    --brand-700: #0f5f56;
    --brand-900: #0a3f39;

    --ink-900: #14181d;
    --ink-700: #363d46;
    --ink-500: #5c6672;
    --ink-400: #7d8794;
    --ink-300: #a3abb6;

    /* A warm canvas: white panels sit on it without either being grey. */
    --canvas: #f7f5f2;
    --surface: #ffffff;
    --surface-sunken: #faf9f7;

    --line: #e6e2db;
    --line-strong: #d5cfc5;

    --amber-500: #b8790c;
    --amber-50: #fdf6e7;
    --red-500: #b4332c;
    --red-50: #fdf0ef;

    /* --- Radii --------------------------------------------------------- */
    --radius-sm: 6px;
    --radius: 10px;
    --radius-lg: 14px;

    /* --- Elevation -----------------------------------------------------
       Two steps only. Panels are separated by their border; shadow is reserved
       for things that genuinely float (menus, dialogs, the app bar). */
    --shadow-panel: 0 1px 2px rgb(20 24 29 / 4%);
    --shadow-float: 0 10px 30px -8px rgb(20 24 29 / 16%), 0 2px 8px -2px rgb(20 24 29 / 8%);

    /* --- Type ----------------------------------------------------------
       16px body. A booking form is read at arm's length by someone who is also
       talking to a customer, and 15px led to too much squinting. Every input is
       also at least 16px, which is what stops iOS zooming on focus. */
    --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --text-xs: 0.8125rem;
    --text-sm: 0.875rem;
    --text-base: 1rem;
    --text-lg: 1.125rem;
    --text-xl: 1.5rem;
    --text-2xl: 1.875rem;
    --text-3xl: 2.5rem;

    --leading-tight: 1.25;
    --leading: 1.55;

    --tracking-label: 0.055em;

    /* --- Bootstrap overrides ------------------------------------------- */
    --bs-body-bg: var(--canvas);
    --bs-body-color: var(--ink-700);
    --bs-body-font-family: var(--font-sans);
    --bs-body-font-size: var(--text-base);
    --bs-body-line-height: var(--leading);
    --bs-emphasis-color: var(--ink-900);
    --bs-secondary-color: var(--ink-500);
    --bs-border-color: var(--line);
    --bs-border-radius: var(--radius);
    --bs-border-radius-sm: var(--radius-sm);
    --bs-border-radius-lg: var(--radius-lg);
    --bs-primary: var(--brand-600);
    --bs-primary-rgb: 18, 117, 106;
    --bs-link-color: var(--brand-700);
    --bs-link-color-rgb: 15, 95, 86;
    --bs-link-hover-color: var(--brand-900);
    --bs-focus-ring-color: rgb(22 137 124 / 22%);
    --bs-focus-ring-width: 3px;
}

/* ==========================================================================
   Base
   ========================================================================== */

body {
    background-color: var(--canvas);
    line-height: var(--leading);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    color: var(--ink-900);
    font-weight: 650;
    letter-spacing: -0.015em;
    line-height: var(--leading-tight);
}

/* Figures in a column should line up. Anything read as a number gets this. */
.numeric,
.stat-value,
.timeline-time,
td.numeric {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}

/* The small uppercase caption used on stat cards and section eyebrows. */
.label-caps {
    color: var(--ink-500);
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: var(--tracking-label);
    text-transform: uppercase;
}

a {
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
}

/* ==========================================================================
   Menus — the app bar
   ========================================================================== */

.app-bar {
    background: var(--surface);
    border-bottom: 1px solid var(--line);
    position: sticky;
    top: 0;
    z-index: 1030;
}

.app-bar .container {
    gap: 1.25rem;
}

/* The brand: a small teal tile with a calendar glyph, then the wordmark.
   Cheaper than shipping a logo file and it survives any font loading state. */
.brand {
    align-items: center;
    color: var(--ink-900);
    display: inline-flex;
    font-size: var(--text-lg);
    font-weight: 650;
    gap: 0.625rem;
    letter-spacing: -0.02em;
    text-decoration: none;
}

.brand:hover {
    color: var(--ink-900);
    text-decoration: none;
}

.brand-mark {
    align-items: center;
    background: linear-gradient(145deg, var(--brand-500), var(--brand-700));
    border-radius: 9px;
    color: #fff;
    display: inline-flex;
    font-size: 1rem;
    height: 34px;
    justify-content: center;
    width: 34px;
}

/* Nav: pill-shaped links with a filled active state, rather than Bootstrap's
   underline-on-hover default, which is invisible on a white bar. */
.app-nav {
    display: flex;
    flex-wrap: wrap;
    gap: 0.125rem;
}

.app-nav a {
    border-radius: 999px;
    color: var(--ink-500);
    font-size: var(--text-sm);
    font-weight: 550;
    padding: 0.4rem 0.8rem;
    text-decoration: none;
    transition: background-color 120ms ease, color 120ms ease;
}

.app-nav a:hover {
    background: var(--surface-sunken);
    color: var(--ink-900);
}

.app-nav a[aria-current="page"] {
    background: var(--brand-50);
    color: var(--brand-700);
    font-weight: 600;
}

.app-user {
    align-items: center;
    display: flex;
    gap: 0.75rem;
}

.app-user-name {
    color: var(--ink-700);
    font-size: var(--text-sm);
    font-weight: 550;
    line-height: 1.2;
    text-align: right;
}

/* A single-letter avatar, tinted from the brand ramp. */
.avatar {
    align-items: center;
    background: var(--brand-50);
    border: 1px solid var(--brand-100);
    border-radius: 50%;
    color: var(--brand-700);
    display: inline-flex;
    font-size: var(--text-sm);
    font-weight: 650;
    height: 34px;
    justify-content: center;
    text-transform: uppercase;
    width: 34px;
}

/* ==========================================================================
   Menus — dropdowns, popovers, pagination, dialog chrome
   ========================================================================== */

.dropdown-menu,
.list-group {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-float);
    padding: 0.25rem;
}

.dropdown-item,
.list-group-item {
    border: 0;
    border-radius: var(--radius-sm);
    color: var(--ink-700);
    font-size: var(--text-sm);
    padding: 0.5rem 0.625rem;
}

.dropdown-item:hover,
.dropdown-item:focus,
.list-group-item-action:hover,
.list-group-item-action:focus {
    background: var(--brand-50);
    color: var(--brand-900);
}

.dropdown-item.active {
    background: var(--brand-600);
    color: #fff;
}

.dropdown-divider {
    border-top-color: var(--line);
    margin: 0.25rem 0;
}

/* The customer lookup: a list of people, each a two-line entry. */
[data-customer-results] {
    max-height: 15rem;
    overflow-y: auto;
}

[data-customer-results] .list-group-item {
    cursor: pointer;
    display: block;
    width: 100%;
    text-align: left;
}

[data-customer-results] .list-group-item + .list-group-item {
    border-top: 1px solid var(--line);
    border-radius: 0;
}

[data-customer-status] {
    min-height: 1.25rem;
}

/* Pagination, as a row of proper controls rather than Bootstrap's joined
   hairlines. */
.pagination {
    gap: 0.25rem;
}

.page-link {
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm) !important;
    color: var(--ink-700);
    font-size: var(--text-sm);
    font-weight: 550;
    min-width: 2.25rem;
    padding: 0.375rem 0.625rem;
    text-align: center;
}

.page-link:hover {
    background: var(--surface-sunken);
    border-color: var(--ink-300);
    color: var(--ink-900);
}

.page-item.active .page-link {
    background: var(--brand-600);
    border-color: var(--brand-600);
    color: #fff;
}

.page-item.disabled .page-link {
    background: var(--surface-sunken);
    border-color: var(--line);
    color: var(--ink-300);
}

/* Dialogs: a heavier radius, a header with a rule, a sunken footer. */
.modal-content {
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-float);
}

.modal-header {
    border-bottom: 1px solid var(--line);
    padding: 1rem 1.25rem;
}

.modal-title {
    font-size: var(--text-lg);
    font-weight: 650;
    letter-spacing: -0.015em;
}

.modal-body {
    padding: 1.25rem;
}

.modal-footer {
    background: var(--surface-sunken);
    border-top: 1px solid var(--line);
    gap: 0.5rem;
    padding: 0.875rem 1.25rem;
}

.modal-footer > * {
    margin: 0;
}

.btn-close {
    opacity: 0.45;
}

.btn-close:hover {
    opacity: 1;
}

/* ==========================================================================
   Page furniture
   ========================================================================== */

.page-head {
    align-items: flex-end;
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    justify-content: space-between;
    margin-bottom: 1.5rem;
}

.page-title {
    font-size: var(--text-2xl);
    font-weight: 650;
    letter-spacing: -0.025em;
    margin: 0;
}

.page-meta {
    color: var(--ink-500);
    font-size: var(--text-sm);
    margin: 0.3125rem 0 0;
}

/* Panels: the workhorse container. A hairline border does the separating, so
   stacked panels read as one surface instead of a pile of drop shadows. */
.card {
    border: 1px solid var(--line);
    box-shadow: var(--shadow-panel);
}

.card-header {
    align-items: center;
    background: var(--surface);
    border-bottom: 1px solid var(--line);
    display: flex;
    gap: 1rem;
    justify-content: space-between;
    padding: 0.875rem 1.125rem;
}

.card-header h2,
.card-header h3 {
    font-size: var(--text-base);
    font-weight: 650;
    letter-spacing: -0.01em;
    margin: 0;
}

.card-body {
    padding: 1.125rem;
}

.card-footer {
    background: var(--surface-sunken);
    border-top: 1px solid var(--line);
    padding: 0.875rem 1.125rem;
}

.section-title {
    font-size: var(--text-lg);
    font-weight: 650;
    letter-spacing: -0.015em;
    margin: 0 0 0.75rem;
}

/* ==========================================================================
   Metrics
   --------------------------------------------------------------------------
   One panel holding every figure, divided by hairlines, rather than five
   separate cards. Five bordered boxes drew five competing rectangles and left
   each one mostly empty; a single bar reads as one object, takes a third of the
   height, and leaves the tables below as the content they are.
   ========================================================================== */

.metrics {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

.metric {
    border-right: 1px solid var(--line);
    border-top: 1px solid var(--line);
    padding: 0.875rem 1.125rem;
}

/* The grid is two-up on a phone, so alternate the right-hand border off. */
.metric:nth-child(2n) {
    border-right: 0;
}

.metric:first-child,
.metric:nth-child(2) {
    border-top: 0;
}

.metric-label {
    color: var(--ink-500);
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: var(--tracking-label);
    text-transform: uppercase;
}

.metric-value {
    color: var(--ink-900);
    font-size: var(--text-2xl);
    font-variant-numeric: tabular-nums;
    font-weight: 650;
    letter-spacing: -0.03em;
    line-height: 1.1;
    margin-top: 0.25rem;
}

.metric-hint {
    color: var(--ink-500);
    font-size: var(--text-xs);
    margin-top: 0.125rem;
}

/* Today is the number an operator checks first and the one that changes under
   them, so it gets a solid brand fill. A tint was tried first and read as an
   accidental hover state - a filled cell cannot be mistaken for one. */
.metric-hero {
    background: linear-gradient(150deg, var(--brand-600), var(--brand-700));
}

.metric-hero .metric-label {
    color: rgb(255 255 255 / 80%);
}

.metric-hero .metric-value,
.metric-hero .metric-hint {
    color: #fff;
}

@media (min-width: 992px) {
    .metrics {
        grid-template-columns: repeat(5, minmax(0, 1fr));
    }

    .metric {
        border-top: 0;
        border-right: 1px solid var(--line);
    }

    .metric:nth-child(2n) {
        border-right: 1px solid var(--line);
    }

    .metric:last-child {
        border-right: 0;
    }
}

.progress {
    background-color: var(--surface-sunken);
    border-radius: 999px;
    overflow: hidden;
}

.progress-bar {
    background-color: var(--brand-500);
}

/* ==========================================================================
   Tables
   ========================================================================== */

.table {
    --bs-table-hover-bg: var(--brand-50);
    --bs-table-border-color: var(--line);
    margin-bottom: 0;
}

.table > :not(caption) > * > * {
    padding: 0.9375rem 1.125rem;
    vertical-align: middle;
}

/* The first column is the row's identity; it does not need the full gutter. */
.table > :not(caption) > * > :first-child {
    padding-left: 1.25rem;
}

.table > :not(caption) > * > :last-child {
    padding-right: 1.25rem;
}

.table > thead > tr > th {
    background: var(--surface-sunken);
    border-bottom: 1px solid var(--line-strong);
    color: var(--ink-700);
    font-size: var(--text-xs);
    font-weight: 650;
    letter-spacing: var(--tracking-label);
    text-transform: uppercase;
    white-space: nowrap;
}

.table tbody tr:last-child > * {
    border-bottom: 0;
}

/* Row-primary text reads as a link target without becoming a link colour. */
.row-title {
    color: var(--ink-900);
    font-weight: 600;
    text-decoration: none;
}

.row-title:hover {
    color: var(--brand-700);
    text-decoration: underline;
}

.row-sub {
    color: var(--ink-500);
    font-size: var(--text-xs);
    line-height: 1.45;
    margin-top: 0.125rem;
    max-width: 34rem;
}

/* Contact details are links so they can be tapped to call or mail, but they are
   not navigation. Colouring every phone number in the brand green left nothing
   on the page to say which links actually go somewhere. */
.contact-link {
    color: inherit;
    text-decoration: none;
}

.contact-link:hover {
    color: var(--brand-700);
    text-decoration: underline;
}

/* The em dash for a value that genuinely is not set. It reads as "nothing here",
   which is information, so it is legible rather than ghosted: ink-300 measured
   2.3:1 against white. */
.absent {
    color: var(--ink-500);
}

/* ==========================================================================
   Controls — buttons
   ========================================================================== */

.btn {
    --bs-btn-padding-y: 0.5rem;
    --bs-btn-padding-x: 0.9375rem;
    --bs-btn-font-size: var(--text-sm);
    border-radius: var(--radius-sm);
    font-weight: 600;
    letter-spacing: -0.005em;
}

.btn-sm {
    --bs-btn-padding-y: 0.375rem;
    --bs-btn-padding-x: 0.6875rem;
    --bs-btn-font-size: var(--text-sm);
}

/* Buttons in a group should share a seam, not each keep a full radius. */
.btn-group > .btn {
    border-radius: 0;
}

.btn-group > .btn:first-child {
    border-bottom-left-radius: var(--radius-sm);
    border-top-left-radius: var(--radius-sm);
}

.btn-group > .btn:last-child {
    border-bottom-right-radius: var(--radius-sm);
    border-top-right-radius: var(--radius-sm);
}

.btn-primary {
    --bs-btn-bg: var(--brand-600);
    --bs-btn-border-color: var(--brand-600);
    --bs-btn-hover-bg: var(--brand-700);
    --bs-btn-hover-border-color: var(--brand-700);
    --bs-btn-active-bg: var(--brand-900);
    --bs-btn-active-border-color: var(--brand-900);
    --bs-btn-disabled-bg: var(--brand-200);
    --bs-btn-disabled-border-color: var(--brand-200);
}

.btn-outline-primary {
    --bs-btn-color: var(--brand-700);
    --bs-btn-border-color: var(--brand-200);
    --bs-btn-hover-bg: var(--brand-50);
    --bs-btn-hover-border-color: var(--brand-400);
    --bs-btn-hover-color: var(--brand-900);
    --bs-btn-active-bg: var(--brand-100);
    --bs-btn-active-border-color: var(--brand-400);
    --bs-btn-active-color: var(--brand-900);
}

.btn-outline-secondary {
    --bs-btn-color: var(--ink-700);
    --bs-btn-border-color: var(--line-strong);
    --bs-btn-hover-bg: var(--surface-sunken);
    --bs-btn-hover-border-color: var(--ink-300);
    --bs-btn-hover-color: var(--ink-900);
    --bs-btn-active-bg: var(--line);
    --bs-btn-active-color: var(--ink-900);
}

.btn-outline-danger {
    --bs-btn-color: var(--red-500);
    --bs-btn-border-color: #eccbc8;
    --bs-btn-hover-bg: var(--red-50);
    --bs-btn-hover-border-color: var(--red-500);
    --bs-btn-hover-color: var(--red-500);
    --bs-btn-active-bg: var(--red-500);
    --bs-btn-active-border-color: var(--red-500);
}

/* ==========================================================================
   Controls — text inputs, selects, textareas
   ========================================================================== */

.form-label {
    color: var(--ink-900);
    font-size: var(--text-sm);
    font-weight: 600;
    letter-spacing: -0.005em;
    margin-bottom: 0.375rem;
}

.form-control,
.form-select {
    background-color: var(--surface);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
    color: var(--ink-900);
    /* 16px minimum: anything smaller makes iOS zoom the page on focus. */
    font-size: var(--text-base);
    min-height: 2.625rem;
    padding: 0.5625rem 0.8125rem;
    transition: border-color 120ms ease, box-shadow 120ms ease;
}

textarea.form-control {
    min-height: 5.5rem;
    resize: vertical;
}

.form-control:hover:not(:disabled):not([readonly]),
.form-select:hover:not(:disabled) {
    border-color: var(--ink-300);
}

/* One focus treatment for every control, so keyboard navigation looks the
   same whether the field is a text input, a select, or a date picker. */
.form-control:focus,
.form-select:focus {
    background-color: var(--surface);
    border-color: var(--brand-500);
    box-shadow: 0 0 0 var(--bs-focus-ring-width) var(--bs-focus-ring-color);
    color: var(--ink-900);
    outline: 0;
}

.form-control::placeholder {
    /* A placeholder is a hint, not a value, so it stays quiet - but 2.3:1 was
       too faint to read at all. */
    color: var(--ink-400);
}

.form-control:disabled,
.form-select:disabled,
.form-control[readonly] {
    background-color: var(--surface-sunken);
    border-color: var(--line);
    color: var(--ink-500);
}

/* The native time/date picker glyph is small and grey by default; give it a
   click target worth aiming at. */
.form-control[type="time"]::-webkit-calendar-picker-indicator,
.form-control[type="date"]::-webkit-calendar-picker-indicator {
    cursor: pointer;
    opacity: 0.45;
    padding: 0.25rem;
}

.form-control[type="time"]::-webkit-calendar-picker-indicator:hover,
.form-control[type="date"]::-webkit-calendar-picker-indicator:hover {
    opacity: 0.9;
}

.form-control.is-invalid,
.form-control.is-invalid:hover {
    border-color: var(--red-500);
}

.form-control.is-invalid:focus {
    border-color: var(--red-500);
    box-shadow: 0 0 0 var(--bs-focus-ring-width) rgb(180 51 44 / 18%);
}

.invalid-feedback {
    color: var(--red-500);
    font-size: var(--text-xs);
    font-weight: 500;
}

/* Help text under a field. Reserves its line so showing one does not shift the
   rest of the form down. */
.form-text {
    color: var(--ink-500);
    font-size: var(--text-xs);
    min-height: 1.25rem;
}

/* A required marker, shown only for fields that genuinely are. */
.required-mark {
    color: var(--red-500);
    font-weight: 600;
    margin-left: 0.125rem;
}

.form-check-input {
    border-color: var(--line-strong);
}

.form-check-input:checked {
    background-color: var(--brand-600);
    border-color: var(--brand-600);
}

.form-check-input:focus {
    border-color: var(--brand-500);
    box-shadow: 0 0 0 var(--bs-focus-ring-width) var(--bs-focus-ring-color);
}

.input-group-text {
    background-color: var(--surface-sunken);
    border-color: var(--line-strong);
    color: var(--ink-500);
    font-size: var(--text-sm);
}

/* ==========================================================================
   Badges, alerts, toasts
   ========================================================================== */

.badge {
    font-weight: 600;
    letter-spacing: 0;
    padding: 0.3125em 0.5em;
    /* Inline badges used to hang off the baseline of the text beside them. */
    vertical-align: middle;
}

/* A badge that reads as a fact rather than a status: no fill, just a hairline. */
.badge-quiet {
    background: var(--surface-sunken);
    border: 1px solid var(--line-strong);
    color: var(--ink-500);
    font-weight: 550;
}

/* A quiet badge that has to carry meaning - "past", a count - rather than
   decorate. Darker text, because it was too faint to register as a status. */
.badge-muted {
    background: var(--line);
    border: 1px solid var(--line-strong);
    color: var(--ink-700);
    font-weight: 600;
}

/* A count, read right-aligned in a column. */
.badge-count {
    background: var(--surface-sunken);
    border: 1px solid var(--line-strong);
    color: var(--ink-700);
    font-weight: 650;
    font-variant-numeric: tabular-nums;
    min-width: 2rem;
}

.alert {
    border-radius: var(--radius);
    font-size: var(--text-sm);
    padding: 0.8125rem 1rem;
}

.alert-success {
    --bs-alert-bg: var(--brand-50);
    --bs-alert-border-color: var(--brand-100);
    --bs-alert-color: var(--brand-900);
}

.alert-danger {
    --bs-alert-bg: var(--red-50);
    --bs-alert-border-color: #f2d5d2;
    --bs-alert-color: var(--red-500);
}

.alert-warning {
    --bs-alert-bg: var(--amber-50);
    --bs-alert-border-color: #f0e0bd;
    --bs-alert-color: var(--amber-500);
}

.toast-container {
    z-index: 1090; /* above Bootstrap modals (1055) */
}

.toast {
    border-radius: var(--radius);
    box-shadow: var(--shadow-float);
}

/* ==========================================================================
   Empty states
   ========================================================================== */

.empty-state {
    color: var(--ink-500);
    padding: 2.5rem 1.5rem;
    text-align: center;
}

.empty-state-icon {
    color: var(--ink-300);
    font-size: 1.75rem;
    line-height: 1;
    margin-bottom: 0.75rem;
}

.empty-state-title {
    color: var(--ink-900);
    font-size: var(--text-base);
    font-weight: 650;
    margin-bottom: 0.25rem;
}

.empty-state-text {
    font-size: var(--text-sm);
    margin: 0 auto;
    max-width: 34rem;
}

/* ==========================================================================
   Day view — a time rail rather than a stack of cards
   ========================================================================== */

.timeline {
    list-style: none;
    margin: 0;
    padding: 0;
}

.timeline-item {
    display: grid;
    gap: 0 1.25rem;
    grid-template-columns: 5.5rem minmax(0, 1fr);
    padding-bottom: 1rem;
    position: relative;
}

/* The vertical rule, drawn from each item's marker down to the next one. */
.timeline-item::before {
    background: var(--line);
    bottom: 0;
    content: "";
    left: 5.5rem;
    position: absolute;
    top: 0.5rem;
    width: 1px;
}

.timeline-item:last-child {
    padding-bottom: 0;
}

.timeline-item:last-child::before {
    display: none;
}

.timeline-time {
    color: var(--ink-900);
    font-size: var(--text-sm);
    font-weight: 650;
    padding-top: 0.875rem;
    text-align: right;
}

.timeline-time-none {
    color: var(--ink-500);
    font-weight: 500;
}

.timeline-card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 0.875rem 1rem;
    position: relative;
}

/* The marker that sits on the rule. */
.timeline-card::before {
    background: var(--brand-500);
    border: 3px solid var(--canvas);
    border-radius: 50%;
    content: "";
    height: 11px;
    left: -1.5rem;
    position: absolute;
    top: 1.125rem;
    width: 11px;
}

.timeline-name {
    font-size: var(--text-lg);
    font-weight: 650;
    letter-spacing: -0.015em;
    margin: 0;
}

.timeline-contact {
    color: var(--ink-500);
    font-size: var(--text-sm);
    margin-top: 0.125rem;
}

.timeline-notes {
    border-left: 2px solid var(--line);
    color: var(--ink-500);
    font-size: var(--text-sm);
    margin: 0.625rem 0 0;
    padding-left: 0.75rem;
    white-space: pre-wrap;
}

/* ==========================================================================
   Calendar — re-skin FullCalendar's Classic theme through its own tokens
   ========================================================================== */

#calendar {
    --fc-classic-background: var(--surface);
    --fc-classic-border: var(--line);
    --fc-classic-strong-border: var(--line-strong);
    --fc-classic-foreground: var(--ink-900);
    --fc-classic-muted-foreground: var(--ink-500);
    --fc-classic-faint-foreground: var(--ink-400);

    /* A wash for today's cell that survives being sat next to white cells. */
    --fc-classic-today: var(--brand-50);

    --fc-classic-primary: var(--brand-600);
    --fc-classic-primary-foreground: #fff;

    --fc-classic-button: var(--brand-600);
    --fc-classic-button-border: var(--brand-600);
    --fc-classic-button-strong: var(--brand-700);
    --fc-classic-button-strong-border: var(--brand-700);
    --fc-classic-button-outline: var(--line-strong);
    --fc-classic-button-foreground: #fff;

    --fc-classic-highlight: var(--brand-100);
    --fc-classic-now: var(--amber-500);

    font-family: var(--font-sans);
}

/* Selectors here target FullCalendar's *semantic* hooks - roles, data
   attributes, real button tags - not its class names. The Classic theme renames
   every logical class to an obfuscated `fc-classic-…`, so `#calendar .fc-button`
   and friends silently match nothing at all; the colour tokens above work
   because the theme's own rules consume them, but anything structural has to
   hook onto something that survives the renaming. */

/* The toolbar: real <button> elements. Prev/next hold an icon, "Today" holds
   text, so both need sizing. */
#calendar button {
    align-items: center;
    border-radius: var(--radius-sm);
    display: inline-flex;
    font-family: var(--font-sans);
    font-size: var(--text-sm);
    font-weight: 600;
    gap: 0.25rem;
    justify-content: center;
    min-height: 2.125rem;
    padding: 0.375rem 0.75rem;
    text-transform: none;
}

#calendar button svg {
    height: 1rem;
    width: 1rem;
}

/* The month title and the weekday headings. */
#calendar [role="heading"] {
    color: var(--ink-900);
    font-family: var(--font-sans);
    font-size: var(--text-xl);
    font-weight: 650;
    letter-spacing: -0.025em;
}

#calendar [role="columnheader"] {
    color: var(--ink-500);
    font-size: var(--text-xs);
    font-weight: 650;
    letter-spacing: var(--tracking-label);
    text-transform: uppercase;
}

/* Day cells are clickable: say so. Cells with bookings too, since a click there
   opens the day rather than the booking dialog.

   The day number is reached by inheritance rather than by a structural
   selector: it is generated inside the cell by FullCalendar, and the nesting is
   not part of any contract. Events reset it below. */
#calendar [data-date] {
    color: var(--ink-500);
    cursor: pointer;
    font-size: var(--text-sm);
    font-weight: 550;
    transition: background-color 110ms ease;
}

#calendar [data-date]:hover {
    background-color: var(--brand-50);
}

/* Today's own cell: the token gives it a tint, and the number agrees. */
#calendar [data-date].fc-day-today,
#calendar [data-date][class*="today"] {
    color: var(--brand-700);
    font-weight: 700;
}

/* Events and the "+N more" link. */
#calendar [role="button"] {
    border-radius: 5px;
    cursor: pointer;
    font-size: var(--text-xs);
    font-weight: 550;
}

#calendar [data-calendar-interactive="more"] {
    color: var(--brand-700);
    cursor: pointer;
    font-size: var(--text-xs);
    font-weight: 650;
}

#calendar [data-calendar-interactive="more"]:hover {
    text-decoration: underline;
}

/* ==========================================================================
   Auth screens
   ========================================================================== */

.auth-shell {
    align-items: center;
    display: flex;
    min-height: 100vh;
    padding: 2rem 1rem;
}

.auth-card {
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-float);
    margin: 0 auto;
    max-width: 27rem;
    overflow: hidden;
    width: 100%;
}

.auth-head {
    background: linear-gradient(140deg, var(--brand-700), var(--brand-600) 55%, var(--brand-500));
    color: #fff;
    padding: 1.75rem;
}

.auth-head .brand-mark {
    background: rgb(255 255 255 / 16%);
    border: 1px solid rgb(255 255 255 / 22%);
    margin-bottom: 0.875rem;
}

.auth-title {
    font-size: var(--text-xl);
    font-weight: 650;
    letter-spacing: -0.025em;
    margin: 0;
}

.auth-sub {
    color: rgb(255 255 255 / 82%);
    font-size: var(--text-sm);
    margin: 0.3125rem 0 0;
}

/* ==========================================================================
   Utilities
   ========================================================================== */

.text-quiet {
    color: var(--ink-500);
}

.text-faint {
    color: var(--ink-400);
}

.divider {
    border-top: 1px solid var(--line);
    margin: 1rem 0;
}

/* Bootstrap's small text is 0.875em of an already-small parent; pin it. */
.small {
    font-size: var(--text-sm);
}

@media (max-width: 575.98px) {
    .timeline-item {
        gap: 0 0.875rem;
        grid-template-columns: 4rem minmax(0, 1fr);
    }

    .timeline-item::before {
        left: 4rem;
    }

    .page-title {
        font-size: var(--text-xl);
    }

    .stat-value {
        font-size: var(--text-2xl);
    }
}
