/* Servant Stage -- Registration Intake, shared styles.
   ============================================================================
   NOLOCO-MATCHED PALETTE (2026-09-09). Caleb asked for these pages to match
   the look of the household-intake forms in Noloco. First pass used colors
   eyeballed from two mobile screenshots; this revision replaces those with
   values pixel-sampled directly from a desktop screenshot Caleb sent of the
   real Noloco form (header bar, "Save" button, page background, and a
   selected-chip's blue text/focus color) -- see the :root comment below for
   the exact sample. Everything else in this file references the custom
   properties in :root, so a future correction is still a one-block edit,
   not a find-and-replace across the file.
   ============================================================================ */

:root {
  /* Navy + slate-blue, sampled directly (pixel-picked) from Caleb's desktop
   Noloco screenshot (2026-09-09) -- these are now measured values, not
   eyeballed guesses: header bar #354156, the "Save" button's muted
   slate-blue #65738c, the page/card near-white #fdfdfc, and the bright blue
   #2c5cf2 used for a selected chip's text/focus states. */
  --color-primary: #65738c;
  --color-primary-dark: #4d5972;
  --color-header-bg: #354156;
  --color-accent: #2c5cf2;
  --color-accent-soft: #eaf1fd;
  --color-bg: #fdfdfc;
  --color-surface: #ffffff;
  --color-text: #1f2937;
  --color-text-muted: #6b7280;
  --color-border: #e2e5ea;
  --color-success: #2e7d4f;
  --color-success-bg: #eaf6ee;
  --color-warning: #9a6700;
  --color-warning-bg: #fff6e5;
  --color-error: #b3261e;
  --color-error-bg: #fdecea;

  /* Swap for Noloco's/Servant Stage's real logo typeface once known. */
  --font-heading: Georgia, 'Times New Roman', serif;
  --font-body: system-ui, -apple-system, 'Segoe UI', sans-serif;

  --radius: 12px;
  --max-width: 640px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font-body);
  background: var(--color-bg);
  color: var(--color-text);
  line-height: 1.5;
}

.page {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 32px 20px 64px;
}

/* Full-bleed navy top bar (2026-09-09, Noloco-match pass) -- a direct child
   of <body>, ABOVE .page, so it spans the full viewport width regardless of
   .page's own max-width. Centered logo, no hamburger/nav menu (Caleb's
   call -- these are single-purpose forms, not a full app shell). Padding
   trimmed (2026-09-09 follow-up, Caleb's call) so the bar hugs the logo
   more closely instead of floating it in a lot of empty navy space. */
.brand-header {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-header-bg);
  padding: 8px 20px;
}

/* Logo mark (2026-09-09; sized up 2026-09-09 follow-up, Caleb's call). The
   source image is the full "Servant Stage" wordmark in white with a red
   accent squiggle -- the white text only looked missing when previewed
   against a white background, since the PNG is transparent and the text
   is white; it renders correctly here against the navy header. Height is
   capped to keep the header bar a fixed size regardless of the source
   image's own aspect ratio. */
.brand-header .brand-mark {
  height: 52px;
  width: auto;
  display: block;
}

h1 {
  font-family: var(--font-heading);
  color: var(--color-text);
  font-size: 1.6rem;
  margin: 0 0 6px;
}

h2 {
  font-family: var(--font-heading);
  color: var(--color-text);
  font-size: 1.15rem;
  margin: 28px 0 10px;
}

p.subtitle {
  color: var(--color-text-muted);
  margin-top: 0;
  margin-bottom: 24px;
}

.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 20px 20px 24px;
  box-shadow: 0 1px 3px rgba(31, 41, 55, 0.06);
}

label {
  display: block;
  font-size: 0.88rem;
  font-weight: 600;
  margin: 16px 0 6px;
}

label.checkbox-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 500;
}

label .hint {
  font-weight: 400;
  color: var(--color-text-muted);
}

/* Required-field marker (2026-09-09, Caleb's ask -- match Noloco's own
   intake form, which marks each required field's label with an asterisk).
   Applied statically to labels whose input is always required, and toggled
   via JS (see page1-intake.html's updateIAmAConditionalFields()) for the
   handful of fields whose required-ness depends on the "I am a..." choice. */
.required-mark {
  color: var(--color-error);
  margin-left: 2px;
  font-weight: 700;
}

input[type="text"],
input[type="email"],
input[type="tel"],
input[type="date"],
select {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--color-border);
  border-radius: 10px;
  font-size: 1rem;
  font-family: inherit;
  background: var(--color-surface);
  color: var(--color-text);
}

/* Custom stacked-chevron select arrow (2026-09-09, Noloco-match pass) --
   Noloco's dropdowns show a small up/down chevron pair, not the browser's
   default single arrow. `appearance: none` clears the native arrow so this
   inline SVG can take its place; the selected VALUE still renders as plain
   text (a native <select> can't render Noloco's colored "chip" pill for the
   chosen value without a custom JS widget -- flagged as a follow-up, not
   built here). */
select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 34px;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='16' viewBox='0 0 10 16'%3E%3Cpath fill='%236b7280' d='M5 0l4 5H1z'/%3E%3Cpath fill='%236b7280' d='M5 16l-4-5h8z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
}

input:focus,
select:focus {
  outline: 2px solid var(--color-accent);
  outline-offset: 1px;
}

input[type="checkbox"] {
  width: 18px;
  height: 18px;
  accent-color: var(--color-primary);
}

.field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

.section-hint {
  color: var(--color-text-muted);
  font-size: 0.88rem;
  margin: -4px 0 16px;
  line-height: 1.4;
}

.radio-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 16px 0;
}

.radio-option {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 500;
  font-size: 0.95rem;
  margin: 0;
}

.radio-option input[type="radio"] {
  width: 18px;
  height: 18px;
  accent-color: var(--color-primary);
}

.field-error {
  color: var(--color-error);
  font-size: 0.82rem;
  margin-top: 4px;
}

.file-drop {
  border: 2px dashed var(--color-border);
  border-radius: 10px;
  padding: 16px;
  text-align: center;
  color: var(--color-text-muted);
  font-size: 0.88rem;
}

.file-drop.has-file {
  border-color: var(--color-accent);
  color: var(--color-text);
}

.file-drop.drag-over {
  border-color: var(--color-accent);
  background: var(--color-accent-soft);
}

.file-drop-hint {
  color: var(--color-text-muted);
}

#headshot-preview-wrap {
  position: relative;
  width: 120px;
  margin: 10px auto 0;
}

#headshot-preview {
  display: block;
  width: 120px;
  height: 120px;
  object-fit: cover;
  border-radius: 10px;
}

#headshot-remove-button {
  position: absolute;
  top: -8px;
  right: -8px;
  width: 24px;
  height: 24px;
  line-height: 1;
  border: none;
  border-radius: 50%;
  background: var(--color-error, #c0392b);
  color: #fff;
  font-size: 16px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

#headshot-remove-button:hover {
  filter: brightness(1.1);
}

button.primary {
  display: block;
  width: 100%;
  margin-top: 28px;
  padding: 14px 20px;
  border: none;
  border-radius: 10px;
  background: var(--color-primary);
  color: #fff;
  font-size: 1.05rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
}

button.primary:hover { background: var(--color-primary-dark); }
button.primary:disabled { background: var(--color-border); color: var(--color-text-muted); cursor: not-allowed; }
/* §25 fix (2026-09-01, Caleb's report -- Continue kept showing even when JS
   set its `hidden` attribute, both on the existing-student picker and the
   expired-hold notice): `button.primary`'s own `display: block` above has
   higher CSS specificity (tag + class) than the browser default
   `[hidden] { display: none }` (a single attribute selector), so it was
   winning over `hidden` every time. This rule restores the expected
   behavior for this one element without touching any other button. */
button.primary[hidden] { display: none; }

.banner {
  padding: 14px 16px;
  border-radius: 10px;
  font-size: 0.92rem;
  margin-bottom: 20px;
}

.banner.error { background: var(--color-error-bg); color: var(--color-error); border: 1px solid var(--color-error); }
.banner.warning { background: var(--color-warning-bg); color: var(--color-warning); border: 1px solid var(--color-warning); }
.banner.success { background: var(--color-success-bg); color: var(--color-success); border: 1px solid var(--color-success); }

/* Shared link/button style for the server-rendered probe pages
   (nolocoIntentProbe.ts) -- same look as button.primary above but usable on
   an <a> or a plain <button> alike, since some of those pages link rather
   than submit. Selector broadened from `a.button` to plain `.button`
   (2026-09-02, waiting-room sound-alert button) so a <button> that isn't a
   form submit -- e.g. one that just triggers a JS action -- can share this
   look without inheriting button.primary's full-width form-submit sizing. */
.button {
  display: inline-block;
  margin-top: 8px;
  padding: 10px 20px;
  border: none;
  border-radius: 10px;
  background: var(--color-primary);
  color: #fff;
  text-decoration: none;
  font-weight: 600;
  font: inherit;
  cursor: pointer;
}

.button:hover { background: var(--color-primary-dark); }

/* Lower-priority variant (2026-09-02, waiting-room UI pass, Caleb's call --
   turning the waiting room's three exit-path links into buttons, but at a
   visibly lower priority than the page's main "enable sound alert" call to
   action): outlined instead of solid-filled, using the same primary color so
   it still reads as "on-brand" rather than a generic gray secondary. */
.button.secondary {
  background: transparent;
  color: var(--color-primary);
  border: 1px solid var(--color-primary);
}

.button.secondary:hover {
  background: var(--color-primary);
  color: #fff;
}

/* Plain horizontal rule between a page's primary call-to-action and a lower-
   priority group of alternatives below it (2026-09-02, waiting-room UI
   pass). */
.divider {
  border: none;
  border-top: 1px solid var(--color-border);
  margin: 24px 0;
}

/* Visually pairs a short lead-in question with the button it belongs to
   (2026-09-02, waiting-room UI pass, Caleb's call -- his instinct, matching
   general UI best practice: group each label with its control via spacing/
   proximity rather than adding a rule between every option, which reads as
   more visual clutter for the same "these are separate" signal). Tight
   spacing WITHIN a group, generous spacing BETWEEN groups -- that gap
   difference is what does the grouping, no extra dividers needed. */
.option-group {
  margin-top: 20px;
}

.option-group p {
  margin: 0 0 6px;
}

.option-group .button {
  margin-top: 0;
}

/* Inline text-link-styled button, for actions embedded inside a sentence
   (checkoutTimerPage()'s "click here if it didn't open") rather than a
   standalone call to action -- a.button/button.primary both look too heavy
   sitting mid-paragraph. */
.link-button {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  color: var(--color-primary);
  text-decoration: underline;
  cursor: pointer;
}

.link-button:hover { color: var(--color-primary-dark); }

/* Visually sets apart the checkout-timer page's "Send Test Payment Webhook"
   button (2026-08-28, Caleb's live-testing request) -- only ever rendered at
   all when ALLOW_TEST_PAYMENT_WEBHOOK is on, so this dashed-border "not part
   of the real flow" treatment never shows up in a normal/production render. */
.dev-tools {
  margin-top: 28px;
  padding: 12px 16px;
  border: 1px dashed var(--color-warning);
  border-radius: 10px;
  font-size: 0.85rem;
}

.dev-tools p { margin: 4px 0; }

/* Registration-open countdown page header (2026-08-27; moved above the card
   2026-08-28 per Caleb's design call, replacing the page's plain <h1> --
   see page()'s headingHtml option in nolocoIntentProbe.ts): who/what is
   being registered on the left, the countdown-to-open "timer" on the right --
   first step of the wider atomic-hold/timer design. Reused as-is (same day)
   by checkoutTimerPage()'s own header once the hold-session timer described
   above was actually built -- no new classes needed. */
.registration-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 16px;
  margin-bottom: 18px;
}
/* 2026-09-12 fix (Caleb's report -- the waitlist page's "Join the Waitlist
   for [Show]" title still had the Show name shown again above it, over
   "Not this show? Choose another"): same class of bug as §25's
   button.primary[hidden] fix above -- this rule's own `display: flex` wins
   over the browser default `[hidden] { display: none }`, so page1-intake.html
   setting #hold-header's `hidden` attribute (its default state for the
   isWaitlistTrack case -- see that file's own comment on holdHeader.hidden)
   never actually hid it visually. */
.registration-header[hidden] { display: none; }

.registration-header .registration-who {
  font-family: var(--font-heading);
  color: var(--color-text);
  font-size: 1.3rem;
  font-weight: 700;
}

.registration-header .registration-timer {
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--color-primary);
  white-space: nowrap;
}

.show-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.show-card {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 16px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
  cursor: pointer;
  font-family: inherit;
  text-align: left;
  width: 100%;
  font-size: 1rem;
  color: var(--color-text);
}

.show-card:hover:not(:disabled) { border-color: var(--color-accent); }

.show-card:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.show-card .show-name {
  font-weight: 600;
}

.show-card .show-meta {
  font-size: 0.82rem;
  color: var(--color-text-muted);
}

.show-card .show-note {
  font-size: 0.8rem;
  color: var(--color-text-muted);
}

.show-card .chevron {
  color: var(--color-accent);
  font-size: 1.2rem;
}

/* "Show Full" card (2026-09-04 -- see claude/status-and-decisions.md).
   Deliberately NOT .show-card:disabled's opacity/not-allowed treatment --
   this card stays fully clickable (it leads into the same flow as any other
   show, landing on the waiting room's own "all slots are filled" terminal
   state), so it needs its own muted-but-still-inviting look rather than the
   "this option is unavailable" signal a disabled card sends. */
.show-card-sold-out {
  background: var(--color-surface-muted, #f5f5f5);
  border-color: var(--color-border);
}

.show-card-sold-out .show-name {
  color: var(--color-text-muted);
}

.show-card-sold-out .show-note {
  color: var(--color-warning, var(--color-text-muted));
  font-weight: 600;
}

/* The obvious "Join Waitlist" call-to-action inside a sold-out show card --
   styled like .button but as a plain <span>, since a <button> can't be
   nested inside this card's own outer <button> element. The whole card
   handles the click either way (see selectShow() in
   page0-show-select.html), so this is a visual affordance only. */
.show-card-cta {
  display: inline-block;
  padding: 6px 14px;
  border-radius: 10px;
  background: var(--color-primary);
  color: #fff;
  font-weight: 600;
  font-size: 0.85rem;
  white-space: nowrap;
}

/* "Register Another Show" Page 1 existing-students picker (2026-08-29 UI
   polish -- see claude/register-another-show-spec.md §9.2-§9.3): built
   directly on .show-card above (same button, same border/radius/hover
   treatment) rather than a parallel visual language, so it reads as the same
   "tap this card to instantly pick it" affordance as Page 0/Page 2's show
   cards -- deliberately since picking any existing student here auto-
   advances immediately, exactly like picking a show does there. Replaces an
   earlier radio+label version of this picker (built the same day) that read
   as a form field rather than a tappable action. */
.student-picker {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 8px;
}

.student-card {
  /* .show-card already provides the border/radius/hover/layout -- nothing to add for the instant-pick cards themselves. */
}

/* The trailing "Add a new student" card is deliberately NOT an instant pick
   (it reveals #student-section below instead of auto-advancing) -- dashed
   border + muted text sets it apart from the solid-bordered picks above, so
   it reads as "this opens something" rather than "this is another instant
   pick". */
.student-card-new {
  border-style: dashed;
  color: var(--color-text-muted);
}

.student-card-new .show-name {
  color: var(--color-text-muted);
  font-weight: 600;
}

.student-card-new:hover:not(:disabled) { border-color: var(--color-accent); }

.spinner {
  display: inline-block;
  width: 16px;
  height: 16px;
  border: 2px solid rgba(255,255,255,0.4);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
  vertical-align: -3px;
  margin-right: 6px;
}

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