/* ==========================================================================
   CurlCab design system
   --------------------------------------------------------------------------
   Single stylesheet, no CSS framework. Everything below is built from the
   tokens in :root — avoid literal colours, spacing or radii further down.

   Contents
     1.  Tokens
     2.  Base & reset
     3.  Typography
     4.  Layout & page header
     5.  Site header / navigation
     6.  Buttons
     7.  Forms
     8.  Cards
     9.  Tables
     10. Badges, alerts, pills
     11. Dialogs
     12. Loading & empty states
     13. Booking components
     14. Tabs, footer, legal
     15. Utilities
     17. Style photography
     18. Inline table editing
     16. Responsive
   ========================================================================== */

/* 1. Tokens ============================================================== */

:root {
  /* Brand — these names are referenced from Razor views, do not rename. */
  --primary: #7c3aed;
  --primary-dark: #5b21b6;
  --primary-soft: #f3efff;
  --primary-softer: #faf7ff;
  --accent: #f59e0b;

  /* Surfaces */
  --bg: #faf8ff;
  --surface: #ffffff;
  --surface-sunken: #f6f4fb;
  --border: #e6e3ef;
  --border-strong: #d3cfe0;

  /* Text */
  --text: #1c1b22;
  --text-secondary: #4b4a55;
  --muted: #6b6979;

  /* Status */
  --success: #047857;
  --success-bg: #ecfdf5;
  --success-border: #a7f3d0;
  --warning: #b45309;
  --warning-bg: #fffbeb;
  --warning-border: #fde68a;
  --error: #dc2626;
  --error-bg: #fef2f2;
  --error-border: #fecaca;
  --info: #1d4ed8;
  --info-bg: #eff6ff;
  --info-border: #bfdbfe;

  /* Radii — --radius is the legacy default, kept for existing markup. */
  --radius-sm: 8px;
  --radius: 12px;
  --radius-md: 12px;
  --radius-lg: 16px;
  --radius-pill: 999px;

  /* Spacing scale */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;

  /* Type scale */
  --text-xs: .75rem;
  --text-sm: .875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.375rem;
  --text-2xl: 1.75rem;
  --text-3xl: 2.25rem;

  /* Elevation */
  --shadow-sm: 0 1px 2px rgba(28, 27, 34, .06);
  --shadow-md: 0 2px 8px rgba(28, 27, 34, .07), 0 1px 2px rgba(28, 27, 34, .04);
  --shadow-lg: 0 12px 32px rgba(28, 27, 34, .12), 0 2px 8px rgba(28, 27, 34, .06);

  /* Motion */
  --transition: 180ms cubic-bezier(.4, 0, .2, 1);

  /* Focus ring — one definition, used by every interactive element. */
  --focus-ring: 0 0 0 3px rgba(124, 58, 237, .35);

  --container: 1080px;
  --container-narrow: 460px;
  --header-height: 64px;
}

/* 2. Base & reset ======================================================== */

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

/* A class that sets display beats the browser's own [hidden] rule, so buttons and
   links toggled with the hidden attribute would otherwise stay visible. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: var(--text-base);
  background: var(--bg);
  color: var(--text);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; }

a {
  color: var(--primary);
  text-decoration: none;
  transition: color var(--transition);
}
a:hover { text-decoration: underline; }

/* One consistent focus treatment. Mouse users never see it; keyboard users
   always do. */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

::selection { background: var(--primary-soft); color: var(--primary-dark); }

/* Skip link — first thing in the tab order. */
.skip-link {
  position: absolute;
  left: var(--space-4);
  top: calc(var(--space-2) * -8);
  z-index: 100;
  padding: var(--space-3) var(--space-4);
  background: var(--surface);
  color: var(--primary-dark);
  font-weight: 600;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  transition: top var(--transition);
}
.skip-link:focus { top: var(--space-2); text-decoration: none; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* 3. Typography ========================================================== */

h1, h2, h3, h4 {
  margin: 0 0 var(--space-3);
  line-height: 1.25;
  letter-spacing: -.011em;
  font-weight: 700;
  color: var(--text);
  text-wrap: balance;
}

h1 { font-size: var(--text-3xl); letter-spacing: -.02em; }
h2 { font-size: var(--text-2xl); letter-spacing: -.016em; }
h3 { font-size: var(--text-lg); }
h4 { font-size: var(--text-base); }

p { margin: 0 0 var(--space-3); }
p:last-child { margin-bottom: 0; }

strong { font-weight: 650; }

small, .text-sm { font-size: var(--text-sm); }

.muted { color: var(--muted); font-size: var(--text-sm); }

.lead {
  font-size: var(--text-lg);
  color: var(--text-secondary);
  line-height: 1.6;
}

/* 4. Layout & page header ================================================ */

.container {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--space-4);
  width: 100%;
}

main {
  display: block;
  padding: var(--space-6) 0 var(--space-8);
  min-height: 70vh;
}

/* Standard page header: title, supporting copy, primary action. */
.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-bottom: var(--space-5);
}
.page-header__text { min-width: min(100%, 280px); flex: 1 1 320px; }
.page-header h1,
.page-header h2 { margin-bottom: var(--space-1); }
.page-header p { color: var(--muted); margin-bottom: 0; max-width: 62ch; }
.page-header__actions {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  align-items: center;
}

/* Section heading inside a page. */
.section-title {
  font-size: var(--text-xl);
  margin: var(--space-6) 0 var(--space-3);
}
.section-title:first-child { margin-top: 0; }

.hero {
  text-align: center;
  padding: var(--space-7) var(--space-4) var(--space-6);
}
.hero h1 {
  font-size: clamp(2rem, 5vw, 2.75rem);
  margin-bottom: var(--space-3);
}
.hero p {
  color: var(--text-secondary);
  font-size: var(--text-lg);
  max-width: 56ch;
  margin: 0 auto var(--space-5);
}
.hero__actions {
  display: flex;
  gap: var(--space-3);
  justify-content: center;
  flex-wrap: wrap;
}
.hero__accent { color: var(--primary); }

/* 5. Site header / navigation ============================================ */

.site-header {
  background: rgba(255, 255, 255, .92);
  backdrop-filter: saturate(180%) blur(8px);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 50;
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  min-height: var(--header-height);
  padding: var(--space-2) var(--space-4);
}

.brand {
  font-size: var(--text-xl);
  font-weight: 800;
  color: var(--text);
  letter-spacing: -.02em;
  white-space: nowrap;
}
.brand:hover { text-decoration: none; }
.brand span { color: var(--primary); }

.main-nav {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  flex-wrap: wrap;
}
.main-nav a {
  color: var(--text-secondary);
  font-weight: 550;
  font-size: var(--text-sm);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  transition: background var(--transition), color var(--transition);
}
.main-nav a:hover {
  color: var(--primary-dark);
  background: var(--primary-soft);
  text-decoration: none;
}
.main-nav a.btn { color: #fff; }
.main-nav a.btn:hover { color: #fff; background: var(--primary-dark); }

/* Notification bell with an unread dot. */
.nav-icon {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  padding: 0;
  font-size: var(--text-lg);
  line-height: 1;
}
.nav-icon__dot {
  position: absolute;
  top: 6px; right: 6px;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--error);
  border: 2px solid var(--surface);
}

.inline-form { display: inline; }

.link-btn {
  background: none;
  border: none;
  color: var(--primary);
  cursor: pointer;
  font: inherit;
  padding: 0;
  border-radius: var(--radius-sm);
}
.link-btn:hover { text-decoration: underline; }

/* Mobile menu toggle — hidden until the nav collapses. */
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--text);
  transition: background var(--transition), border-color var(--transition);
}
.nav-toggle:hover { background: var(--surface-sunken); border-color: var(--border-strong); }
.nav-toggle svg { width: 20px; height: 20px; display: block; }
/* Scoped by .nav-toggle so these out-specify the `.nav-toggle svg` rule above,
   otherwise both the open and close icons paint at once. */
.nav-toggle .nav-toggle__close { display: none; }
.nav-toggle[aria-expanded="true"] .nav-toggle__open { display: none; }
.nav-toggle[aria-expanded="true"] .nav-toggle__close { display: block; }

/* 6. Buttons ============================================================= */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 10px 20px;
  min-height: 42px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  cursor: pointer;
  font-size: var(--text-sm);
  font-weight: 600;
  font-family: inherit;
  text-align: center;
  line-height: 1.2;
  white-space: nowrap;
  transition: background var(--transition), border-color var(--transition),
              color var(--transition), box-shadow var(--transition),
              transform var(--transition);
}
.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.btn-primary {
  background: var(--primary);
  color: #fff;
  box-shadow: var(--shadow-sm);
}
.btn-primary:hover { background: var(--primary-dark); }

.btn-outline {
  background: var(--surface);
  color: var(--primary-dark);
  border-color: var(--border-strong);
}
.btn-outline:hover { background: var(--primary-soft); border-color: var(--primary); }

/* Tertiary — for actions that must not compete with the primary one. */
.btn-ghost {
  background: transparent;
  color: var(--text-secondary);
  border-color: transparent;
}
.btn-ghost:hover { background: var(--surface-sunken); color: var(--text); }

.btn-danger { background: var(--error); color: #fff; }
.btn-danger:hover { background: #b91c1c; }
.btn-danger:focus-visible { box-shadow: 0 0 0 3px rgba(220, 38, 38, .35); }

/* Destructive, but not the loudest thing on a card of routine actions. */
.btn-danger-text { color: var(--error); }
.btn-danger-text:hover { background: var(--error-bg); color: #b91c1c; }

.btn-sm { padding: 6px 14px; min-height: 34px; font-size: var(--text-xs); }
.btn-lg { padding: 13px 28px; min-height: 50px; font-size: var(--text-base); }
.btn-block { display: flex; width: 100%; }

.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: .5;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

/* Loading state — driven by site.js on submit, so a slow POST always shows
   feedback and cannot be double-submitted. */
.btn.is-loading {
  color: transparent !important;
  pointer-events: none;
  position: relative;
}
.btn.is-loading::after {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  width: 16px; height: 16px;
  margin: -8px 0 0 -8px;
  border: 2px solid currentColor;
  border-radius: 50%;
  border-top-color: transparent;
  color: #fff;
  animation: spin .6s linear infinite;
}
.btn-outline.is-loading::after,
.btn-ghost.is-loading::after { color: var(--primary); }

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

/* Groups of actions — keeps spacing consistent and wraps on small screens. */
.btn-row {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  align-items: center;
}

/* 7. Forms =============================================================== */

.form-group { margin-bottom: var(--space-4); }

.form-group label,
.form-label {
  display: block;
  font-weight: 600;
  font-size: var(--text-sm);
  margin-bottom: var(--space-1);
  color: var(--text);
}

.form-group input,
.form-group select,
.form-group textarea,
.form-control {
  width: 100%;
  padding: 10px 12px;
  min-height: 42px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font-size: var(--text-base);
  font-family: inherit;
  color: var(--text);
  background: var(--surface);
  transition: border-color var(--transition), box-shadow var(--transition);
}
.form-group textarea { min-height: 88px; resize: vertical; }

.form-group input::placeholder,
.form-group textarea::placeholder { color: #9b99a8; }

.form-group input:hover,
.form-group select:hover,
.form-group textarea:hover { border-color: var(--muted); }

.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: var(--focus-ring);
}

.form-group input:disabled,
.form-group select:disabled,
.form-group textarea:disabled {
  background: var(--surface-sunken);
  color: var(--muted);
  cursor: not-allowed;
}

/* MVC adds .input-validation-error to fields that failed server validation. */
.form-group input.input-validation-error,
.form-group select.input-validation-error,
.form-group textarea.input-validation-error {
  border-color: var(--error);
  background: var(--error-bg);
}
.form-group input.input-validation-error:focus,
.form-group select.input-validation-error:focus,
.form-group textarea.input-validation-error:focus {
  box-shadow: 0 0 0 3px rgba(220, 38, 38, .3);
}

/* Help text sits under the label, above the control's error. */
.form-hint {
  display: block;
  font-size: var(--text-sm);
  color: var(--muted);
  margin-top: var(--space-1);
}

.required-mark { color: var(--error); margin-left: 2px; }

.form-check {
  display: flex;
  gap: var(--space-2);
  align-items: flex-start;
  margin-bottom: var(--space-3);
  padding: var(--space-2);
  margin-left: calc(var(--space-2) * -1);
  border-radius: var(--radius-sm);
  transition: background var(--transition);
}
.form-check:hover { background: var(--surface-sunken); }
.form-check input {
  margin-top: 3px;
  width: 18px; height: 18px;
  flex: 0 0 auto;
  accent-color: var(--primary);
  cursor: pointer;
}
.form-check label {
  font-weight: 400;
  margin-bottom: 0;
  cursor: pointer;
  line-height: 1.5;
}

/* Two fields side by side — collapses to one column on narrow screens. */
.form-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 0 var(--space-4);
}

/* A row of checkbox or radio choices that belong to one question. */
.choice-set {
  border: none;
  padding: 0;
  margin: 0 0 var(--space-4);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.choice-set legend { padding: 0; margin-bottom: var(--space-2); float: left; width: 100%; }
.choice {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  font-size: var(--text-sm);
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
}
.choice:hover { background: var(--primary-soft); border-color: var(--primary); }
.choice input { accent-color: var(--primary); cursor: pointer; margin: 0; }
.choice:has(input:checked) {
  background: var(--primary-soft);
  border-color: var(--primary);
  font-weight: 600;
}

/* Filter bars and other dense field groups. */
.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: var(--space-3) var(--space-4);
}

.field-validation-error {
  display: block;
  color: var(--error);
  font-size: var(--text-sm);
  margin-top: var(--space-1);
  font-weight: 500;
}

.validation-summary-errors {
  color: #991b1b;
  background: var(--error-bg);
  border: 1px solid var(--error-border);
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
  font-size: var(--text-sm);
}
.validation-summary-errors ul { margin: 0; padding-left: var(--space-4); }
.validation-summary-errors ul:empty { display: none; }
/* MVC always renders the summary element; hide it when it holds no errors. */
.validation-summary-valid { display: none; }

/* Form footer — separates the submit action from the fields above it. */
.form-actions {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  flex-wrap: wrap;
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
}
.form-actions--plain { border-top: none; padding-top: 0; }

/* 8. Cards =============================================================== */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  margin-bottom: var(--space-4);
  box-shadow: var(--shadow-sm);
}
.card h3 { margin-top: 0; }
.card > :last-child { margin-bottom: 0; }
/* A card that is the whole page (auth, short forms) carries the h1, but at a
   size that suits the panel rather than a full-width page header. */
.card > h1:first-child {
  font-size: var(--text-2xl);
  margin-top: 0;
  margin-bottom: var(--space-4);
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}
.card-grid:empty { display: none; }
.card-grid .card { margin-bottom: 0; display: flex; flex-direction: column; }
/* Push a card's action to the bottom so grid rows line up. */
.card-grid .card > .btn:last-child,
.card-grid .card > .btn-row:last-child { margin-top: auto; }

/* Cards that link somewhere lift slightly on hover. */
.card--interactive { transition: box-shadow var(--transition), border-color var(--transition), transform var(--transition); }
.card--interactive:hover {
  box-shadow: var(--shadow-md);
  border-color: var(--border-strong);
  transform: translateY(-2px);
}

.card__meta {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: var(--space-2);
}

.card__price {
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--text);
}

/* Stat tiles — the number leads, the label explains it. Deliberately not
   the same component as .card, so counts don't read as content cards. */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}
.stat {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-1);
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong);
  border-radius: var(--radius-lg);
  padding: var(--space-4) var(--space-5);
  box-shadow: var(--shadow-sm);
}
.stat__value {
  font-size: var(--text-3xl);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.stat__label {
  color: var(--muted);
  font-size: var(--text-sm);
  margin-bottom: var(--space-3);
}
.stat .btn { margin-top: auto; }
/* Only queues with something in them draw the eye. */
.stat--attention { border-left-color: var(--accent); }
.stat--attention .stat__value { color: var(--warning); }
.stat--danger { border-left-color: var(--error); }
.stat--danger .stat__value { color: var(--error); }

/* 9. Tables ============================================================== */

.table-wrap {
  overflow-x: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  margin-bottom: var(--space-5);
  -webkit-overflow-scrolling: touch;
}

table.data {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  font-size: var(--text-sm);
}
table.data th,
table.data td {
  text-align: left;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
table.data thead th {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--text-secondary);
  font-weight: 650;
  background: var(--surface-sunken);
  border-bottom: 1px solid var(--border-strong);
  white-space: nowrap;
  position: sticky;
  top: 0;
  z-index: 1;
}
table.data tbody tr { transition: background var(--transition); }
table.data tbody tr:hover { background: var(--primary-softer); }
table.data tbody tr:last-child td { border-bottom: none; }

/* Money and counts read far better right-aligned. */
table.data th.num,
table.data td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Row actions are secondary to the data itself. */
table.data td.actions { text-align: right; white-space: nowrap; }
table.data td.actions a { font-weight: 600; font-size: var(--text-sm); }

/* 10. Badges, alerts, pills ============================================== */

.badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: 650;
  line-height: 1.5;
  letter-spacing: .01em;
  background: var(--primary-soft);
  color: var(--primary-dark);
  white-space: nowrap;
}
.badge-green { background: var(--success-bg); color: var(--success); }
.badge-amber { background: var(--warning-bg); color: var(--warning); }
.badge-red   { background: var(--error-bg); color: var(--error); }
.badge-grey  { background: var(--surface-sunken); color: var(--muted); }

.alert {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  margin-bottom: var(--space-4);
  font-size: var(--text-sm);
  border: 1px solid transparent;
  align-items: flex-start;
}
.alert > :last-child { margin-bottom: 0; }
.alert-success { background: var(--success-bg); color: var(--success); border-color: var(--success-border); }
.alert-error   { background: var(--error-bg); color: #991b1b; border-color: var(--error-border); }
.alert-info    { background: var(--info-bg); color: var(--info); border-color: var(--info-border); word-break: break-word; }
.alert-warning { background: var(--warning-bg); color: var(--warning); border-color: var(--warning-border); }

/* 11. Dialogs ============================================================ */

/* Used by site.js to replace window.confirm() on destructive actions.
   Without JS the forms keep their native confirm() and still work. */
dialog.modal {
  border: none;
  border-radius: var(--radius-lg);
  padding: 0;
  max-width: 440px;
  width: calc(100vw - var(--space-6));
  box-shadow: var(--shadow-lg);
  color: var(--text);
  background: var(--surface);
}
dialog.modal::backdrop {
  background: rgba(28, 27, 34, .45);
  backdrop-filter: blur(2px);
}
.modal__body { padding: var(--space-5) var(--space-5) var(--space-4); }
.modal__title { font-size: var(--text-lg); margin-bottom: var(--space-2); }
.modal__text { color: var(--text-secondary); margin-bottom: 0; }
.modal__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-5);
  border-top: 1px solid var(--border);
  background: var(--surface-sunken);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
  flex-wrap: wrap;
}

/* 12. Loading & empty states ============================================= */

.empty-state {
  text-align: center;
  padding: var(--space-7) var(--space-5);
  background: var(--surface);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
  margin-bottom: var(--space-4);
}
.empty-state__icon {
  font-size: 2rem;
  line-height: 1;
  margin-bottom: var(--space-3);
  opacity: .7;
}
.empty-state h3 { margin-bottom: var(--space-2); }
.empty-state p {
  color: var(--muted);
  max-width: 44ch;
  margin: 0 auto var(--space-4);
}
.empty-state > :last-child { margin-bottom: 0; }

/* Compact variant for empty table bodies. */
.empty-row td {
  text-align: center;
  color: var(--muted);
  padding: var(--space-6) var(--space-4) !important;
}

.spinner {
  display: inline-block;
  width: 18px; height: 18px;
  border: 2px solid var(--border-strong);
  border-top-color: var(--primary);
  border-radius: 50%;
  animation: spin .6s linear infinite;
  vertical-align: -3px;
}

.loading-note {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--muted);
  font-size: var(--text-sm);
}

/* 13. Booking components ================================================= */

.price-breakdown { list-style: none; padding: 0; margin: 0; }
.price-breakdown li {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-2) 0;
  border-bottom: 1px dashed var(--border);
  font-variant-numeric: tabular-nums;
}
.price-breakdown li span:last-child { font-weight: 550; white-space: nowrap; }
.price-breakdown li.total {
  font-weight: 800;
  font-size: var(--text-lg);
  border-bottom: none;
  border-top: 2px solid var(--border-strong);
  margin-top: var(--space-2);
  padding-top: var(--space-3);
}

.calendar {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: var(--space-1);
}
.calendar .day-name {
  text-align: center;
  font-size: var(--text-xs);
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted);
  padding: var(--space-1) 0 var(--space-2);
}
.calendar button {
  padding: var(--space-3) var(--space-1);
  min-height: 44px;
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: var(--text-sm);
  font-family: inherit;
  font-weight: 550;
  color: var(--text);
  transition: background var(--transition), border-color var(--transition),
              color var(--transition);
}
.calendar button:hover:not(:disabled) {
  border-color: var(--primary);
  background: var(--primary-soft);
}
.calendar button:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.calendar button:disabled { opacity: .3; cursor: not-allowed; }
.calendar button.selected {
  background: var(--primary);
  color: #fff;
  border-color: var(--primary);
  box-shadow: var(--shadow-sm);
}

.slot-grid {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-3);
}
.slot-grid button {
  padding: var(--space-2) var(--space-4);
  min-height: 40px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  border-radius: var(--radius-pill);
  cursor: pointer;
  font-size: var(--text-sm);
  font-family: inherit;
  font-weight: 550;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  transition: background var(--transition), border-color var(--transition),
              color var(--transition);
}
.slot-grid button:hover:not(:disabled) {
  border-color: var(--primary);
  background: var(--primary-soft);
}
.slot-grid button:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.slot-grid button:disabled { opacity: .3; cursor: not-allowed; }
.slot-grid button.selected {
  background: var(--primary);
  color: #fff;
  border-color: var(--primary);
}

/* Shown until a date is chosen, then replaced by the slot buttons. */
.slot-placeholder {
  color: var(--muted);
  font-size: var(--text-sm);
  padding: var(--space-3) 0;
  margin: 0;
}

.wizard-steps {
  display: flex;
  gap: var(--space-2);
  margin-bottom: var(--space-5);
  flex-wrap: wrap;
  list-style: none;
  padding: 0;
}
.wizard-steps span,
.wizard-steps li {
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--surface);
  border: 1px solid var(--border);
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--muted);
}
.wizard-steps span.active,
.wizard-steps li.active {
  background: var(--primary);
  color: #fff;
  border-color: var(--primary);
}
.wizard-steps span.done,
.wizard-steps li.done {
  background: var(--primary-soft);
  color: var(--primary-dark);
  border-color: transparent;
}

.countdown {
  font-size: var(--text-2xl);
  font-weight: 800;
  color: var(--primary);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}

.status-timeline { list-style: none; padding: 0; margin: 0; }
.status-timeline li {
  padding: var(--space-2) 0 var(--space-2) var(--space-6);
  position: relative;
  color: var(--muted);
}
/* Connecting line between the dots. */
.status-timeline li:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 10px;
  top: 26px;
  bottom: -6px;
  width: 2px;
  background: var(--border);
}
.status-timeline li::before {
  content: "";
  position: absolute;
  left: 5px;
  top: 14px;
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--border-strong);
  z-index: 1;
}
.status-timeline li.done { color: var(--text-secondary); }
.status-timeline li.done::before { background: var(--success); border-color: var(--success); }
.status-timeline li.done:not(:last-child)::after { background: var(--success); }
.status-timeline li.current { color: var(--text); font-weight: 600; }
.status-timeline li.current::before {
  background: var(--primary);
  border-color: var(--primary);
  box-shadow: 0 0 0 4px var(--primary-soft);
}

/* 14. Tabs, footer, legal ================================================ */

.tabs {
  display: flex;
  gap: var(--space-1);
  margin-bottom: var(--space-5);
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}
.tabs a {
  padding: var(--space-3) var(--space-3);
  color: var(--muted);
  font-weight: 600;
  font-size: var(--text-sm);
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color var(--transition), border-color var(--transition);
}
.tabs a:hover { color: var(--text); text-decoration: none; }
.tabs a.active { color: var(--primary); border-bottom-color: var(--primary); }

.site-footer {
  border-top: 1px solid var(--border);
  background: var(--surface);
  padding: var(--space-6) 0;
  font-size: var(--text-sm);
}
.site-footer p { color: var(--text-secondary); }
.site-footer .muted { max-width: 74ch; }
.footer-links { margin-top: var(--space-3); }
.footer-links a { color: var(--muted); font-size: var(--text-sm); text-decoration: underline; }
.footer-links a:hover { color: var(--primary); }

.legal-page { max-width: 70ch; margin: 0 auto var(--space-7); }
.legal-page h1 { margin-bottom: var(--space-1); }
.legal-page h2 { font-size: var(--text-lg); margin: var(--space-6) 0 var(--space-2); }
.legal-page p, .legal-page li { line-height: 1.7; color: var(--text-secondary); }
.legal-page ul { padding-left: var(--space-5); }
.legal-page li { margin-bottom: var(--space-2); }

/* 15. Utilities ========================================================== */

/* Narrow single-column pages: login, register, short forms. */
.narrow { max-width: var(--container-narrow); margin-left: auto; margin-right: auto; }
.narrow-md { max-width: 620px; margin-left: auto; margin-right: auto; }
/* Left-aligned form panel — settings pages rather than centred auth pages. */
.card--form { max-width: 620px; }

.text-center { text-align: center; }
.text-right { text-align: right; }

.mt-0 { margin-top: 0; }
.mt-2 { margin-top: var(--space-2); }
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }
.mt-5 { margin-top: var(--space-5); }
.mb-0 { margin-bottom: 0; }
.mb-3 { margin-bottom: var(--space-3); }
.mb-4 { margin-bottom: var(--space-4); }

/* Vertical rhythm for a run of blocks. */
.stack > * + * { margin-top: var(--space-3); }

.cluster {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  align-items: center;
}

.booking-actions {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  align-items: center;
  margin-top: var(--space-4);
}

/* 16. Responsive ========================================================= */

/* The collapsing nav is JS-only. Without the .js class the header keeps its
   original wrapping row, so navigation still works with scripting off. */
@media (max-width: 860px) {
  .js .nav-toggle { display: inline-flex; }

  /* The nav becomes a drop panel under the header. */
  .js .main-nav {
    display: none;
    position: absolute;
    left: 0; right: 0;
    top: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-1);
    padding: var(--space-3) var(--space-4) var(--space-4);
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow-lg);
  }
  .js .main-nav.is-open { display: flex; }
  .main-nav a,
  .main-nav .link-btn {
    padding: var(--space-3);
    font-size: var(--text-base);
    text-align: left;
    width: 100%;
    border-radius: var(--radius-sm);
  }
  .main-nav .inline-form { display: block; width: 100%; }
  .main-nav .link-btn { color: var(--text-secondary); font-weight: 550; }
  .main-nav .nav-icon { width: 100%; justify-content: flex-start; }

  .header-inner { position: relative; }
}

@media (max-width: 640px) {
  main { padding: var(--space-5) 0 var(--space-7); }

  h1 { font-size: var(--text-2xl); }
  h2 { font-size: var(--text-xl); }

  .hero { padding: var(--space-6) var(--space-2) var(--space-5); }
  .hero__actions .btn { width: 100%; }

  .card { padding: var(--space-4); }

  .page-header__actions { width: 100%; }
  .page-header__actions .btn { flex: 1 1 auto; }

  /* Full-width actions are easier to hit than a row of small buttons. */
  .form-actions { flex-direction: column; align-items: stretch; }
  .form-actions .btn { width: 100%; }

  .modal__actions { flex-direction: column-reverse; }
  .modal__actions .btn { width: 100%; }

  .calendar button { padding: var(--space-2) 0; font-size: var(--text-xs); }

  table.data th,
  table.data td { padding: var(--space-3); }
}

/* Respect the OS "reduce motion" setting. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .card--interactive:hover { transform: none; }
}

/* 18. Style photography ==================================================
   Cover thumbnails on cards, and the gallery on a style's page. Every frame
   reserves its aspect ratio so images cannot shift layout as they load. */

.style-thumb {
  position: relative;
  aspect-ratio: 4 / 3;
  border-radius: calc(var(--radius-lg) - 1px) calc(var(--radius-lg) - 1px) 0 0;
  overflow: hidden;
  background: var(--surface-sunken);
  margin: calc(var(--space-5) * -1) calc(var(--space-5) * -1) var(--space-4);
  border-bottom: 1px solid var(--border);
}
.style-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Cards must share one shape for the grid, so photos are cropped. Bias the crop
     upward: in a hair photo the subject is the head, and a centred crop on a portrait
     shot cuts it off. */
  object-position: center 28%;
  display: block;
  transition: transform var(--transition);
}
.card--interactive:hover .style-thumb img { transform: scale(1.03); }

/* No photo yet: a quiet branded frame, never a broken image. */
.style-thumb--empty {
  display: grid;
  place-items: center;
  background: linear-gradient(135deg, var(--primary-softer), var(--primary-soft));
  color: var(--primary);
}
.style-thumb__placeholder { width: 40%; max-width: 72px; opacity: .55; }

/* Gallery ---------------------------------------------------------------- */

.gallery { margin-bottom: var(--space-5); }
/* The main image is never cropped: someone choosing a hairstyle has to see the
   whole hairstyle, and hair photos are usually portrait. The frame shrinks to the
   image rather than the image sitting inside a fixed box, so a portrait shot gets a
   tall frame and a landscape one a wide frame, with no empty ground either side. */
.gallery__main {
  width: fit-content;
  max-width: 100%;
  margin-inline: auto;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--surface-sunken);
  border: 1px solid var(--border);
  line-height: 0;
}
.gallery__main img {
  max-width: 100%;
  max-height: min(70vh, 620px);
  width: auto;
  height: auto;
  display: block;
}

.gallery__thumbs {
  display: flex;
  gap: var(--space-2);
  justify-content: center;
  margin-top: var(--space-2);
  overflow-x: auto;
  padding-bottom: var(--space-1);
  scrollbar-width: thin;
}
.gallery__thumb {
  flex: 0 0 84px;
  aspect-ratio: 1;
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 2px solid transparent;
  background: var(--surface-sunken);
  padding: 0;
  cursor: pointer;
  transition: border-color var(--transition);
}
.gallery__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gallery__thumb:hover { border-color: var(--border-strong); }
.gallery__thumb[aria-current="true"] { border-color: var(--primary); }
.gallery__thumb:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* Admin photo management -------------------------------------------------- */

.photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: var(--space-4);
}
.photo-tile {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--surface);
  display: flex;
  flex-direction: column;
}
.photo-tile--primary { border-color: var(--primary); box-shadow: var(--focus-ring); }
.photo-tile__img { aspect-ratio: 4 / 3; background: var(--surface-sunken); }
.photo-tile__img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photo-tile__body {
  padding: var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  flex: 1;
}
.photo-tile__alt {
  font-size: var(--text-xs);
  color: var(--muted);
  margin: 0;
  /* Alt text can be long; keep tiles the same height. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.photo-tile__actions { display: flex; gap: var(--space-2); margin-top: auto; }

/* The chosen file, shown after picking so the admin can confirm before upload. */
.file-chosen { font-size: var(--text-sm); color: var(--text-secondary); margin-top: var(--space-2); }
.file-chosen:empty { display: none; }

@media (max-width: 640px) {
  .gallery__thumb { flex-basis: 64px; }
}

/* 19. Inline editing in tables ===========================================
   Numeric inputs sitting inside a data table: narrow, right-aligned, and
   visually quieter than a standalone form field. */

.input-num {
  width: 8rem;
  max-width: 100%;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
table.data td .input-num { margin: 0; }

.checkbox-inline {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: 400;
  margin: 0;
  cursor: pointer;
}
.checkbox-inline input { margin: 0; }

/* 20. Share =============================================================== */

.share__actions {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  align-items: center;
}
.share__status { margin: var(--space-2) 0 0; min-height: 1.2em; }
.share__status:empty { min-height: 0; }

/* 21. Featured grid =======================================================
   An admin may feature up to ten styles, but the landing page shows only as
   many as fill whole rows at the current width — a half-empty last row looks
   like something failed to load.

   The grid is repeat(auto-fill, minmax(260px, 1fr)) inside a 1080px container,
   which gives 1 column below ~568px, 2 below ~844px and 3 above it. The
   breakpoints below sit clear of those thresholds, and each count divides
   evenly by every column count possible in its range, so the last row is
   always full whichever way the browser rounds.

   Done in CSS rather than by measuring in script: no flash of extra cards,
   and it still works with JavaScript off. The cards stay in the markup, so
   search engines and no-CSS readers still see the full set. */

/* 1 column (and 2 between 568 and 599) — 4 divides by both. */
@media (max-width: 599px) {
  .card-grid--featured > :nth-child(n+5) { display: none; }
}

/* 2 columns (3 between 844 and 879) — 6 divides by both. */
@media (min-width: 600px) and (max-width: 879px) {
  .card-grid--featured > :nth-child(n+7) { display: none; }
}

/* 3 columns. */
@media (min-width: 880px) {
  .card-grid--featured > :nth-child(n+10) { display: none; }
}

/* Booking message thread. Sender-aligned so a glance tells you who said what, without
   needing colour alone to carry that meaning. */
.message-thread { list-style: none; margin: 0 0 16px; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.message { max-width: 85%; padding: 10px 12px; border-radius: 14px; border: 1px solid var(--border); }
.message--mine { align-self: flex-end; background: var(--info-bg); border-color: var(--info-border); }
.message--theirs { align-self: flex-start; background: var(--surface-2, #faf8ff); }
.message__meta { display: flex; gap: 8px; align-items: baseline; font-size: .78rem; margin-bottom: 4px; }
.message__body { white-space: pre-wrap; overflow-wrap: anywhere; font-size: .95rem; line-height: 1.5; }
