/*
 * Styles that sit alongside Tailwind: the motifs from the Stitch designs plus
 * the shared pieces every screen needs (toasts, skeletons, the bed map).
 */

/* ------------------------------------------------------------ Stitch motifs */

.custom-shadow { box-shadow: 0 8px 32px 0 rgba(110, 103, 94, 0.08); }
.spot-shadow   { box-shadow: 0 4px 16px 0 rgba(110, 103, 94, 0.05); }
.lift-shadow   { box-shadow: 0 12px 40px 0 rgba(74, 21, 75, 0.12); }

.glass-card {
  /* The Stitch source had an invalid rgba() here; this is the intended
     translucent cream over a blur. */
  background: rgba(253, 249, 242, 0.7);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(132, 73, 129, 0.05);
}

.hide-scrollbar::-webkit-scrollbar { display: none; }
.hide-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }

/* The asymmetric "pigeon wing" corner used on featured imagery. */
.wing-radius { border-radius: 32px 80px 32px 32px; }

.abstract-wing {
  position: absolute;
  top: -10%;
  right: -20%;
  width: 80vw;
  height: 80vw;
  background: radial-gradient(circle, rgba(229, 223, 247, 0.45) 0%, rgba(253, 249, 242, 0) 70%);
  border-radius: 40% 60% 70% 30% / 40% 50% 60% 50%;
  animation: wingFloat 20s ease-in-out infinite alternate;
  z-index: 0;
  pointer-events: none;
}

@keyframes wingFloat {
  0%   { transform: rotate(0deg) scale(1) translate(0, 0); }
  100% { transform: rotate(15deg) scale(1.1) translate(-5%, 5%); }
}

.fade-in-up {
  animation: fadeInUp 0.8s ease-out forwards;
  opacity: 0;
  transform: translateY(20px);
}
.delay-1 { animation-delay: 0.1s; }
.delay-2 { animation-delay: 0.2s; }
.delay-3 { animation-delay: 0.3s; }
.delay-4 { animation-delay: 0.4s; }

@keyframes fadeInUp {
  to { opacity: 1; transform: translateY(0); }
}

/* Anyone who has asked their system for less motion gets none of it. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .fade-in-up { opacity: 1; transform: none; }
  .abstract-wing { animation: none; }
}

/* ------------------------------------------------------------- focus states */

:focus-visible {
  outline: 3px solid #4a154b;
  outline-offset: 2px;
  border-radius: 4px;
}

/* Skip link for keyboard users - visible only once focused. */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 12px 20px;
  background: #300033;
  color: #fff;
  border-radius: 0 0 16px 0;
}
.skip-link:focus { left: 0; }

/* --------------------------------------------------------------- the beds */
/*
 * The reformer picker. Colour alone never carries the state: every bed also
 * shows an icon and its state is in the accessible name.
 */
.bed {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  aspect-ratio: 3 / 4;
  border-radius: 14px;
  border: 2px solid transparent;
  font-family: '"Plus Jakarta Sans"', system-ui, sans-serif;
  font-weight: 600;
  font-size: 13px;
  transition: transform 0.15s ease, box-shadow 0.2s ease, background-color 0.2s ease;
  cursor: pointer;
}

.bed--available {
  background: #ffffff;
  border-color: #d9e0cf;
  color: #3A3733;
  box-shadow: 0 4px 16px 0 rgba(110, 103, 94, 0.05);
}
.bed--available:hover { transform: translateY(-2px); box-shadow: 0 8px 22px rgba(74, 21, 75, 0.12); }

.bed--selected {
  background: #4a154b;
  border-color: #300033;
  color: #ffffff;
  transform: translateY(-2px);
  box-shadow: 0 10px 26px rgba(74, 21, 75, 0.28);
}

.bed--mine {
  background: #e7d1ff;
  border-color: #4a154b;
  color: #300033;
}

.bed--occupied {
  background: #ebe8e1;
  border-color: #ded9d0;
  color: #8a8580;
  cursor: not-allowed;
}
.bed--occupied:hover { transform: none; }

.bed--unavailable {
  background: repeating-linear-gradient(45deg, #ebe8e1, #ebe8e1 6px, #e2ded5 6px, #e2ded5 12px);
  border-color: #ded9d0;
  color: #9a958f;
  cursor: not-allowed;
}

.bed__label { font-size: 15px; line-height: 1; }
.bed__who {
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.02em;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  opacity: 0.85;
}
.bed__icon { font-size: 15px; line-height: 1; }

/* The front of the room, so the layout is orientable. */
.room-front {
  text-align: center;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #8a8580;
  padding: 6px 0 14px;
  border-bottom: 1px solid #e2ded5;
  margin-bottom: 18px;
}

/* ---------------------------------------------------------------- feedback */

#toast-region {
  position: fixed;
  left: 50%;
  bottom: 96px;
  transform: translateX(-50%);
  z-index: 90;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: calc(100% - 32px);
  max-width: 420px;
  pointer-events: none;
}

.toast {
  pointer-events: auto;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 14px 16px;
  border-radius: 18px;
  font-family: '"Plus Jakarta Sans"', system-ui, sans-serif;
  font-size: 15px;
  line-height: 1.45;
  box-shadow: 0 12px 34px rgba(58, 55, 51, 0.18);
  animation: toastIn 0.25s ease-out;
}
.toast--success { background: #2f3d22; color: #f2f7ea; }
.toast--error   { background: #93000a; color: #ffffff; }
.toast--info    { background: #31302c; color: #f4f0e9; }

@keyframes toastIn {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* --------------------------------------------------------------- skeletons */

.skeleton {
  background: linear-gradient(90deg, #efebe4 25%, #f7f4ee 50%, #efebe4 75%);
  background-size: 200% 100%;
  animation: shimmer 1.4s infinite;
  border-radius: 14px;
}
@keyframes shimmer {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}

/* A button that is mid-request: visibly busy and not clickable again. */
.is-busy {
  position: relative;
  color: transparent !important;
  pointer-events: none;
}
.is-busy::after {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 18px;
  height: 18px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  color: #ffffff;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

button[disabled], .btn[disabled] { opacity: 0.45; cursor: not-allowed; }

/* ------------------------------------------------------------------ dialog */

dialog::backdrop { background: rgba(28, 28, 24, 0.45); backdrop-filter: blur(2px); }
dialog { border: none; padding: 0; background: transparent; }
dialog[open] { animation: fadeInUp 0.2s ease-out forwards; opacity: 1; transform: none; }

/* ------------------------------------------------------------- misc layout */

body { min-height: 100dvh; }

/*
 * Keeps content clear of the fixed bottom navigation.
 *
 * The bar is ~83px tall, and on a phone with a home indicator it grows by
 * env(safe-area-inset-bottom) (~34px) because the nav itself carries
 * `pb-safe`. The clearance below the last card is therefore built the same
 * way the nav's own height is - a base gap plus that same safe-area inset -
 * so the breathing room is the same on every device rather than collapsing
 * to a sliver on the handsets people actually hold.
 *
 * There is deliberately no `min-width: 768px` override any more. The
 * customer bottom nav has no responsive hiding - it is fixed at the bottom
 * at every width - so an earlier desktop rule of 48px was leaving the last
 * ~35px of every customer screen tucked behind it on a wide window. Admin
 * and instructor screens do swap their bar for a side rail on desktop and
 * so carry a little unused space at the very bottom now; that is invisible
 * next to content that was being clipped.
 *
 * !important is deliberate, not a habit: the compiled Tailwind stylesheet
 * (/css/tailwind.css) is linked *after* this one, exactly where the old CDN
 * script used to inject its styles, so a page that also
 * carries a plain Tailwind padding utility on the same element - `py-8` is
 * the common one, on every admin and instructor screen - ends up with that
 * utility's padding-bottom landing later in the cascade and silently
 * winning at equal specificity, cutting this back to 32px. That is exactly
 * what was quietly clipping the last card in the clients and staff lists.
 * This class exists specifically to guarantee real clearance regardless of
 * whatever else is on the element, so it has to always win.
 */
.pb-nav { padding-bottom: calc(150px + env(safe-area-inset-bottom, 0px)) !important; }

.pb-safe { padding-bottom: env(safe-area-inset-bottom, 0px); }

/* The same margin, for a screen that has no bottom nav but still ends in a
   fixed action bar or is simply the last thing on the page. */
.pb-clear { padding-bottom: calc(120px + env(safe-area-inset-bottom, 0px)) !important; }
@media (min-width: 768px) { .pb-clear { padding-bottom: 32px !important; } }

/* reCAPTCHA v3's floating badge would sit over the bottom nav and the action
   bars on a phone. Google allows hiding it on condition the form shows its
   privacy/terms notice instead - see UI.mountRecaptchaNotices. */
.grecaptcha-badge { visibility: hidden; }

/* Tables on admin screens scroll rather than pushing the page sideways. */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Inside the phone app, anything meant only for a browser (the Web Push toggle,
   a "get the app" banner) is hidden. native.js sets html.in-app. */
.in-app .web-only { display: none !important; }
