/*
  Styling for the public booking pages and the member-facing /dashboard
  (they share this one file). Design tokens (--ink, --cream, etc.) live in
  brand.css, loaded alongside this file in every layout; see that file's
  comment for why.
*/
* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
}

.public-header {
  max-width: 480px;
  margin: 0 auto;
  padding: 2rem 1.5rem 0;
  text-align: center;
}

.public-logo-link {
  display: inline-block;
}

.public-logo {
  height: 28px;
  width: auto;
}

.public-booking {
  max-width: 480px;
  margin: 0 auto;
  padding: 3rem 1.5rem 5rem;
}

.public-booking h1 {
  font-family: var(--font-serif);
  font-size: clamp(2rem, 5vw, 2.75rem);
  font-weight: 400;
  line-height: 1.15;
  margin-bottom: 1rem;
}

.public-booking .lead {
  font-size: 1.0625rem;
  line-height: 1.6;
  color: rgba(29, 34, 28, 0.7);
  margin-bottom: 2rem;
}

/* Pages that opt in via content_for(:body_class, "has-side-image") (and a
   content_for(:side_image) block, rendered by the layout as a sibling of
   .page-left) get a full-bleed split screen: a one-third left column
   (logo, content, legal footer, vertically distributed) and a two-thirds
   image column stretching edge-to-edge. Everything else keeps the plain
   single-column layout. .page-left/.side-image only take on this
   treatment inside the .has-side-image scope. */
body.has-side-image {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  height: 100vh;
}

/* height (not min-height) + overflow-y:auto so this column scrolls on its
   own when content is taller than the viewport, while the image column
   stays pinned at a fixed 100vh via the grid row's height. */
body.has-side-image .page-left {
  display: flex;
  flex-direction: column;
  height: 100vh;
  overflow-y: auto;
  padding: 0 2rem;
}

/* The column itself is usually narrower than the default 480px content
   width, so without this the form would just fill it edge-to-edge rather
   than reading as centered within the column. The header shares this same
   centered-block treatment so the (left-aligned) logo lines up with the
   form/legal text's own left edge, rather than the column's outer edge. */
/* width:100% matters here. Without it, .public-header's box would
   shrink-wrap around just the logo (flex cross-axis auto-margins override
   stretch when content is narrower than the container), leaving it a
   different width/position than .public-booking, whose wider form content
   naturally fills out to max-width on its own. */
body.has-side-image .public-header,
body.has-side-image .public-booking,
body.has-side-image .public-footer {
  width: 100%;
  max-width: 420px;
}

/* Vertically centers the main content between the logo and the legal
   footer, rather than it sitting flush under the logo. */
body.has-side-image .public-booking {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* This layout is more height-constrained than the default single-column
   pages get (full viewport, no page scroll expected), so the generous
   padding/margins that work fine on a normal scrolling page are trimmed
   here specifically. Top/bottom split unevenly on purpose:
   less above the title (close to the logo) and less below the button
   (close to the legal text) than the default single-column spacing. */
body.has-side-image .public-header {
  padding-top: 1.25rem;
  text-align: left;
}
body.has-side-image .public-logo { height: 60px; }
body.has-side-image .public-booking { padding: 0.75rem 1.5rem; }
body.has-side-image .public-booking .lead { margin-bottom: 1.5rem; }
body.has-side-image .field { margin-bottom: 1rem; }
body.has-side-image .public-footer { padding: 1rem 1.5rem 1.5rem; }

.side-image img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (max-width: 860px) {
  body.has-side-image {
    display: block;
    height: auto;
  }

  body.has-side-image .page-left {
    display: block;
    height: auto;
    overflow-y: visible;
  }

  body.has-side-image .public-booking {
    display: block;
  }

  .side-image {
    display: none;
  }
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  margin-bottom: 1.25rem;
}

.field label {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(29, 34, 28, 0.65);
}

.field input[type="text"],
.field input[type="email"],
.field input[type="tel"],
.field input[type="number"],
.field input[type="date"],
.field input[type="datetime-local"],
.field input[type="password"],
.field select {
  width: 100%;
  min-width: 0;
  box-sizing: border-box;
  background: #fff;
  border: 1px solid rgba(29, 34, 28, 0.2);
  border-radius: 6px;
  padding: 0.75rem 1rem;
  font-family: var(--font-sans);
  font-size: 1rem;
  color: var(--ink);
}

/* Native <select> chrome renders at a different height than a text input
   even with identical padding/border — appearance: none strips that out
   so it's box-model-identical to every other field, with our own chevron
   standing in for the native arrow this removes. */
.field select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  padding-right: 2.5rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5L6 8l3.5-3.5' stroke='%231d221c' stroke-opacity='0.55' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
}

.field input:focus,
.field select:focus {
  outline: none;
  border-color: var(--sage);
  box-shadow: 0 0 0 3px rgba(124, 154, 128, 0.25);
}

.duration-prices {
  list-style: none;
  padding: 0;
  margin: 0 0 2rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  font-size: 0.9375rem;
}

.duration-prices li {
  display: flex;
  justify-content: space-between;
  border-bottom: 1px solid rgba(29, 34, 28, 0.1);
  padding-bottom: 0.5rem;
}

.field-errors {
  color: var(--danger);
  font-size: 0.875rem;
  margin-top: 0.25rem;
}

.field-hint {
  font-size: 0.8125rem;
  color: rgba(29, 34, 28, 0.55);
  margin: 0;
}

.field-checkbox {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  margin-bottom: 1.25rem;
  font-size: 0.9375rem;
}

/* Our own `display: flex` above otherwise wins over the browser's default
   [hidden] { display: none }. Author styles always beat the UA
   stylesheet, regardless of selector specificity or source order, so the
   `hidden` attribute (used by early_performance_gate_controller.js) would
   silently do nothing without this. */
.field-checkbox[hidden] {
  display: none;
}

.field-checkbox input[type="checkbox"] {
  margin-top: 0.2em;
  flex-shrink: 0;
}

/* .time-slots and its variants now live in brand.css, shared with
   admin.css (the admin booking forms' live-availability pickers). */

.terms-privacy-note {
  font-size: 0.9375rem;
  margin: 0 0 1rem;
}

.public-booking h2 {
  font-family: var(--font-serif);
  font-size: 1.375rem;
  font-weight: 400;
  margin: 2rem 0 1rem;
}

.terms-content h2 {
  font-size: 1.0625rem;
  margin: 1.75rem 0 0.5rem;
}

.terms-content ul {
  margin: 0;
  padding-left: 1.25rem;
}

.terms-content li {
  font-size: 0.9375rem;
  line-height: 1.6;
  color: rgba(29, 34, 28, 0.8);
  margin-bottom: 0.375rem;
}

.terms-footer {
  margin-top: 2rem;
  padding-top: 1.5rem;
  border-top: 1px solid rgba(29, 34, 28, 0.1);
  font-size: 0.875rem;
  font-style: italic;
  color: rgba(29, 34, 28, 0.6);
}

.text-link {
  color: var(--moss);
  font-size: 0.9375rem;
  font-weight: 600;
  text-decoration: none;
}

.text-link:hover { text-decoration: underline; }

.devise-links {
  margin-top: 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.devise-links p { margin: 0; }

/* .status-badge and .notice/.alert now live in brand.css, shared with
   admin.css. Both load it already. */

.error-summary {
  background: rgba(168, 50, 50, 0.08);
  border: 1px solid rgba(168, 50, 50, 0.3);
  border-radius: 6px;
  padding: 1rem 1.25rem;
  margin-bottom: 1.5rem;
  color: var(--danger);
  font-size: 0.9375rem;
}

/* A proper welcome for founders rather than a small status pill, same
   tinted-box language as .error-summary above, in copper instead of
   danger red. */
.founder-panel {
  background: rgba(168, 109, 71, 0.08);
  border: 1px solid rgba(168, 109, 71, 0.3);
  border-radius: 6px;
  padding: 1rem 1.25rem;
  margin-bottom: 1.5rem;
  color: var(--copper);
  font-size: 0.9375rem;
}

.founder-panel strong {
  display: block;
  margin-bottom: 0.25rem;
  font-size: 1rem;
}

.founder-panel p {
  margin: 0;
}

/* Plain navigation, not an action — kept visually quieter than the .btn
   family (no fill, no border) so it reads as "go back" rather than
   competing with the page's actual buttons. Same rule as admin.css's
   .back-link. */
.back-link {
  display: inline-block;
  margin-bottom: 0.75rem;
  color: var(--sage);
  text-decoration: none;
  font-size: 0.875rem;
}

.back-link:hover { text-decoration: underline; }

/* button_to renders a block-level <form> by default, which stacks
   multiple actions vertically with no gap between them — same fix as
   admin.css. */
.button_to { display: inline-block; }

.btn-primary {
  display: inline-block;
  width: 100%;
  padding: 0.9375rem 1.5rem;
  background: var(--moss);
  color: #fff;
  border: none;
  border-radius: 6px;
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.18s;
}

.btn-primary:hover { background: var(--moss-hover); }

.btn-primary:disabled {
  background: rgba(var(--moss-rgb), 0.35);
  cursor: not-allowed;
}

.btn-primary:disabled:hover { background: rgba(var(--moss-rgb), 0.35); }

/* .btn-primary is full-width by default, correct for an actual form
   submit (e.g. "Book trial day," "Sign up"), wrong for an inline CTA link
   sitting in running text (e.g. "Add an ad hoc visit"). Additive modifier,
   doesn't touch the shared default. (admin.css's .btn-primary is
   auto-width by default instead — deliberate, see the comment there.) */
.btn-primary.btn-auto {
  display: inline-block;
  width: auto;
}

.btn {
  display: inline-block;
  width: auto;
  padding: 0.5rem 1rem;
  background: #fff;
  color: var(--ink);
  border: 1px solid rgba(29, 34, 28, 0.2);
  border-radius: 6px;
  font-family: var(--font-sans);
  font-size: 0.875rem;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}

.btn:hover { border-color: var(--sage); }

.btn-danger {
  background: var(--danger-bg);
  color: var(--danger);
  border-color: var(--danger);
}

.btn-danger:hover { background: var(--danger); color: #fff; }

.btn-warning {
  background: var(--warning-bg);
  color: var(--warning);
  border-color: var(--warning);
}

.btn-warning:hover { background: var(--warning); color: #fff; }

.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;
}

.turnstile-widget { margin-bottom: 1.25rem; }

.confirmation-card {
  text-align: center;
  padding: 2.5rem 2rem;
  background: #fff;
  border: 1px solid rgba(29, 34, 28, 0.1);
  border-radius: var(--radius-lg);
}

.public-footer {
  max-width: 720px;
  margin: 0 auto;
  padding: 0 1.5rem 3rem;
  text-align: center;
}

.public-footer-legal {
  font-size: 0.75rem;
  line-height: 1.5;
  color: rgba(29, 34, 28, 0.45);
  margin: 0;
}

.confirmation-note {
  font-size: 0.875rem;
  color: rgba(29, 34, 28, 0.6);
  margin-top: 0.75rem;
}

.confirmation-icon {
  width: 3rem;
  height: 3rem;
  margin: 0 auto 1rem;
  background: var(--sage);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 1.25rem;
  font-weight: 700;
}

/* White card, same visual language as .dashboard-card, rather than a solid
   fill — reads as "the first card on the page" instead of a bar bolted on
   top, consistent with the rest of the dashboard's light/editorial look. */
.dashboard-nav {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 1.25rem;
  max-width: 720px;
  margin: 1.5rem auto 0;
  padding: 0.875rem 1.5rem;
  background: #fff;
  border: 1px solid rgba(29, 34, 28, 0.1);
  border-radius: var(--radius-lg);
}

.dashboard-nav a {
  color: var(--ink);
  text-decoration: none;
  font-size: 0.9375rem;
  font-weight: 600;
}

.dashboard-nav a:hover {
  color: var(--sage);
}

.dashboard-nav a.current {
  color: var(--moss);
}

.dashboard-nav-home svg {
  display: block;
  width: 1.25rem;
  height: 1.25rem;
}

.dashboard-nav-account {
  position: relative;
  margin-left: auto;
}

.dashboard-nav-account summary {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  cursor: pointer;
  list-style: none;
  color: var(--ink);
  font-size: 0.9375rem;
  font-weight: 600;
}

.dashboard-nav-account summary::-webkit-details-marker {
  display: none;
}

.dashboard-nav-account summary:hover {
  color: var(--sage);
}

.dashboard-nav-account-chevron {
  width: 1rem;
  height: 1rem;
  transition: transform 0.15s ease;
}

.dashboard-nav-account[open] .dashboard-nav-account-chevron {
  transform: rotate(180deg);
}

.dashboard-nav-account-menu {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
}

/* The floating panel chrome only applies to the copy nested inside the
   <details> (the desktop dropdown) — the always-visible mobile copy below
   reuses .dashboard-nav-account-menu purely for its link layout/typography. */
.dashboard-nav-account > .dashboard-nav-account-menu {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 0.5rem;
  background: #fff;
  border: 1px solid rgba(29, 34, 28, 0.1);
  border-radius: var(--radius-sm);
  padding: 0.75rem;
  min-width: 160px;
  box-shadow: 0 4px 12px rgba(29, 34, 28, 0.08);
}

/* Sign out is a button_to form, not a link, but should read as one of the
   nav's plain text links rather than a bordered pill. */
.dashboard-nav-account-menu a,
.dashboard-nav-account-menu button {
  background: none;
  border: none;
  margin: 0;
  padding: 0;
  font: inherit;
  color: var(--ink);
  font-size: 0.9375rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}

.dashboard-nav-account-menu a:hover,
.dashboard-nav-account-menu button:hover {
  color: var(--sage);
}

/* The always-visible mobile stand-in for the Account dropdown (see the
   comment on .dashboard-nav-account-mobile below for why a real dropdown
   won't do here). Hidden on desktop; swapped in below 720px. */
.dashboard-nav-account-mobile {
  display: none;
}

/* Below this, the nav card's own edges start touching the viewport edges
   (it has no outer margin once the viewport is narrower than its 720px
   max-width) — stack every item vertically rather than wrapping run-on
   groups. The Account dropdown is swapped for plain always-visible links:
   Chromium keeps a closed <details>'s content unpainted even when its
   `display` is forced open via author CSS (the closed state is enforced
   below the CSS box model, not just via a plain `display: none` a media
   query could override), so a real dropdown can't be forced into an
   always-open mobile state — hence the separate .dashboard-nav-account-mobile
   block with its own copy of the links instead. */
@media (max-width: 720px) {
  .dashboard-nav {
    flex-direction: column;
    align-items: center;
  }

  .dashboard-nav-account {
    display: none;
  }

  .dashboard-nav-account-mobile {
    display: flex;
    align-items: center;
    gap: 1.25rem;
  }
}

.dashboard-card {
  background: #fff;
  border: 1px solid rgba(29, 34, 28, 0.1);
  border-radius: var(--radius-lg);
  padding: 1.5rem;
  margin-bottom: 1.5rem;
}

.dashboard-card h2 {
  font-family: var(--font-serif);
  font-size: 1.375rem;
  font-weight: 400;
  margin: 0 0 1rem;
}

.dashboard-card table {
  width: 100%;
  border-collapse: collapse;
}

.dashboard-card th, .dashboard-card td {
  text-align: left;
  padding: 0.5rem 0;
  border-bottom: 1px solid rgba(29, 34, 28, 0.08);
  font-size: 0.9375rem;
}

.dashboard-card th {
  color: rgba(29, 34, 28, 0.55);
  font-weight: 600;
  width: 40%;
}

/* "Need to change..." reads too close to the rows above it with the
   default zero top margin .field-hint uses elsewhere (e.g. directly under
   a form input, where that's correct). This scoped rule only affects a
   hint immediately following a stacked-row list inside a dashboard-card. */
.dashboard-card .stacked-row + .field-hint {
  margin-top: 0.75rem;
}

/* One shared row shape for every dashboard-card list (memberships,
   hot-desk visits, invoices, upcoming bookings): a bold title line, an
   optional muted secondary line, a badge+amount meta line (badge always
   first), then any action button(s) on their own line — all of it always
   stacked (rather than only wrapping when it doesn't fit) so every row's
   shape stays predictable regardless of how long its content is, and
   every list in the dashboard reads the same way at a glance. */
.stacked-row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
  padding: 0.75rem 0;
  border-bottom: 1px solid rgba(29, 34, 28, 0.08);
  font-size: 0.9375rem;
}

.stacked-row:last-child {
  border-bottom: none;
}

.stacked-row-secondary {
  color: rgba(29, 34, 28, 0.55);
  font-size: 0.875rem;
}

.stacked-row-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
}

/* Action button(s) (View, Download PDF, Reschedule/Cancel) sit on their
   own line like everything else in .stacked-row, but pulled to the right
   edge (align-self, since the row itself is a column flex container) to
   read as the row's action rather than another line of information. */
.stacked-row-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  align-self: flex-end;
}
