<template>
  <div>
    <!-- Already a member -->
    <template v-if="isAuthenticated">
      <div class="full-section">
        <h2>You're already a member</h2>
        <p class="section-intro">
          Welcome back, {{ memberData?.name || "member" }}. You're part of Ghost
          Guild in the
          <span class="capitalize">{{
            memberData?.circle || "community"
          }}</span>
          circle.
        </p>

        <div class="member-info-grid">
          <DashedBox :hoverable="false">
            <div class="section-label">Circle</div>
            <div class="info-value capitalize">
              {{ memberData?.circle || "Community" }}
            </div>
          </DashedBox>
          <DashedBox :hoverable="false">
            <div class="section-label">Contribution</div>
            <div class="info-value">
              {{ formatContribution(memberData?.contributionAmount ?? 0, memberData?.billingCadence) }} CAD
            </div>
          </DashedBox>
        </div>

        <div class="button-row">
          <NuxtLink to="/member/dashboard" class="form-submit"
            >Go to Dashboard</NuxtLink
          >
          <NuxtLink to="/member/profile" class="btn">Edit Profile</NuxtLink>
        </div>
      </div>

      <ParchmentInset>
        <h2>Want to change your circle or contribution?</h2>
        <p>
          You can update your circle and adjust your monthly contribution at any
          time from your profile settings.
        </p>
        <NuxtLink to="/member/profile" class="parchment-link"
          >Update Membership Settings</NuxtLink
        >
      </ParchmentInset>
    </template>

    <!-- Not authenticated: new layout -->
    <template v-else>
      <!-- HERO (split, matches about.vue) -->
      <div class="join-hero">
        <div class="join-hero-left">
          <h1>Join Ghost Guild</h1>
          <p>
            Resources, events, and a community of people figuring it out.
            Everyone gets everything. Pay what you can.
          </p>
        </div>
        <div class="join-hero-right">
          <div class="section-label">What you get</div>
          <ul>
            <li>Full access to the knowledge commons</li>
            <li>Free entry to all events and workshops</li>
            <li>Slack invite in the next monthly onboarding wave</li>
            <li>Equal access regardless of contribution</li>
            <li>Pick your circle anytime after signup</li>
          </ul>
        </div>
      </div>

      <!-- FORM + ASIDE -->
      <div class="join-grid">
        <div class="join-main">
          <div class="join-main-inner">
            <div v-if="errorMessage" class="error-box">{{ errorMessage }}</div>

            <form @submit.prevent="handleSubmit">
              <!-- About you -->
              <div class="form-block">
                <h2>About you</h2>
                <p class="form-block-intro">
                  We'll send a magic link to confirm your email. No passwords.
                </p>
                <div class="identity-grid">
                  <div class="field-row">
                    <label for="join-name">Name</label>
                    <input
                      id="join-name"
                      v-model="form.name"
                      class="form-input"
                      type="text"
                      required
                      @blur="validateName"
                      @input="fieldErrors.name && (fieldErrors.name = '')"
                    >
                    <p v-if="fieldErrors.name" class="field-error">
                      {{ fieldErrors.name }}
                    </p>
                  </div>
                  <div class="field-row">
                    <label for="join-email">Email</label>
                    <input
                      id="join-email"
                      v-model="form.email"
                      class="form-input"
                      type="email"
                      placeholder="you@example.com"
                      required
                      @blur="validateEmail"
                      @input="fieldErrors.email && (fieldErrors.email = '')"
                    >
                    <p v-if="fieldErrors.email" class="field-error">
                      {{ fieldErrors.email }}
                    </p>
                  </div>
                </div>
              </div>

              <!-- Pay what you can -->
              <div class="form-block">
                <div class="pwyc-header">
                  <h2>Pay what you can</h2>
                  <div
                    class="cadence-toggle"
                    role="group"
                    aria-label="Billing cadence"
                  >
                    <button
                      type="button"
                      data-testid="cadence-monthly"
                      :class="{ active: cadence === 'monthly' }"
                      @click="onCadenceChange('monthly')"
                    >
                      Monthly
                    </button>
                    <button
                      type="button"
                      data-testid="cadence-annual"
                      :class="{ active: cadence === 'annual' }"
                      @click="onCadenceChange('annual')"
                    >
                      Annual
                    </button>
                  </div>
                </div>
                <p class="form-block-intro">
                  Equal access for everyone. Pick what fits &mdash; these aren't
                  tiers.
                </p>

                <ul
                  class="pwyc-list"
                  role="radiogroup"
                  aria-label="Contribution amount"
                >
                  <li
                    v-for="preset in presetRows"
                    :key="preset.baseAmount"
                    :class="[
                      'pwyc-row',
                      { selected: isPresetSelected(preset) },
                    ]"
                  >
                    <input
                      :id="`pwyc-${preset.baseAmount}`"
                      v-model.number="form.contributionAmount"
                      class="pwyc-radio"
                      type="radio"
                      name="pwyc-amount"
                      :value="preset.cadenceAmount"
                      @change="customAmount = ''"
                    >
                    <label
                      :for="`pwyc-${preset.baseAmount}`"
                      class="pwyc-row-content"
                    >
                      <span class="pwyc-amt">${{ preset.cadenceAmount }}</span>
                      <span class="pwyc-label">{{ preset.label }}</span>
                      <span v-if="preset.suggested" class="pwyc-tag"
                        >Suggested</span
                      >
                    </label>
                  </li>
                  <li :class="['pwyc-row', 'pwyc-custom', { selected: isCustomSelected }]">
                    <div class="pwyc-custom-input-wrap">
                      <span class="currency">$</span>
                      <input
                        v-model="customAmount"
                        class="pwyc-custom-input"
                        type="number"
                        min="0"
                        placeholder="100"
                        aria-label="Custom contribution amount"
                        @blur="commitCustomAmount"
                      >
                    </div>
                    <span class="pwyc-label"
                      >A different amount works for me</span
                    >
                  </li>
                </ul>
              </div>

              <!-- Submit row -->
              <div class="submit-row">
                <label class="agreement-label">
                  <input
                    v-model="form.agreedToGuidelines"
                    type="checkbox"
                  >
                  <span>
                    I agree to the Ghost Guild
                    <NuxtLink to="/community-guidelines" target="_blank"
                      >Community Guidelines</NuxtLink
                    >.
                  </span>
                </label>
                <button
                  class="submit-btn"
                  type="submit"
                  :disabled="!isFormValid || isSubmitting"
                >
                  <span v-if="isSubmitting">Processing...</span>
                  <span v-else-if="needsPayment">Continue to Payment</span>
                  <span v-else>Become a Member</span>
                </button>
              </div>
            </form>
          </div>
        </div>

        <aside class="join-aside">
          <div class="join-aside-inner">
            <div class="section-label">About the money</div>
            <ul class="trust-list">
              <li>
                <strong>Pay what you can.</strong> Equal access for everyone, no
                matter the amount. If you can pay more, you're making room for
                someone who can't.
              </li>
              <li>
                <strong>Canadian charity.</strong> Baby Ghosts Studio
                Development Fund is a registered Canadian charity. We'll help
                you set up tax receipts after you join.
              </li>
              <li>
                <strong>Secure payment.</strong> Card entry handled by Helcim
                &mdash; we never see your card details.
              </li>
              <li>
                <strong>Change anytime.</strong> Adjust your contribution or
                cancel from your dashboard.
              </li>
            </ul>
          </div>
        </aside>
      </div>
    </template>

    <!-- Flow overlay: covers the page from form submit through redirect.
         Lives outside v-if/v-else so it survives the auth state flip that
         fires after checkMemberStatus() at the end of createSubscription. -->
    <SignupFlowOverlay
      :state="flowState"
      :summary="flowSummary"
      :error-message="errorMessage"
      @close="closeFlowOverlay"
    />
  </div>
</template>

<script setup>
import { reactive, ref, computed, onMounted, onUnmounted } from "vue";
import {
  requiresPayment,
  formatContribution,
  CONTRIBUTION_PRESETS,
} from "~/config/contributions";

useSiteMeta({
  title: "Join",
  description:
    "Join Ghost Guild — a membership community for game developers exploring cooperative models. Everyone gets everything. Pay what you can, $0 to $50 per month.",
});

// Auth state
const { isAuthenticated, memberData, checkMemberStatus } = useAuth();

onMounted(async () => {
  await checkMemberStatus();
});

// Form state — circle stays "community" and is submitted to the API unchanged.
// Picker is removed from the template; selection moves to a post-signup prompt.
const form = reactive({
  email: "",
  name: "",
  circle: "community",
  contributionAmount: 15,
  agreedToGuidelines: false,
  billingAddress: {
    street: "",
    city: "",
    province: "",
    postalCode: "",
    country: "CA",
  },
});

const isSubmitting = ref(false);
const errorMessage = ref("");
const successMessage = ref("");
const cadence = ref("monthly"); // 'monthly' | 'annual'
const customAmount = ref(""); // string; the raw <input type=number> value

const fieldErrors = reactive({ name: "", email: "" });

const validateName = () => {
  fieldErrors.name = form.name.trim() ? "" : "Please enter your name.";
};

const validateEmail = () => {
  const value = form.email.trim();
  if (!value) {
    fieldErrors.email = "";
    return;
  }
  const ok = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
  fieldErrors.email = ok ? "" : "Please enter a valid email address.";
};

const flowState = ref("idle");

const customerId = ref(null);
const customerCode = ref(null);
const subscriptionData = ref(null);
const paymentToken = ref(null);

// Preset rows with cadence-adjusted display amounts.
const presetRows = computed(() =>
  CONTRIBUTION_PRESETS.map((p) => ({
    baseAmount: p.amount,
    cadenceAmount: cadence.value === "annual" ? p.amount * 12 : p.amount,
    label: p.label,
    suggested: p.amount === 15,
  })),
);

const isCustomSelected = computed(() => customAmount.value !== "");

const isPresetSelected = (preset) =>
  !isCustomSelected.value && form.contributionAmount === preset.cadenceAmount;

const onCadenceChange = (newCadence) => {
  if (newCadence === cadence.value) return;
  const next =
    newCadence === "annual"
      ? form.contributionAmount * 12
      : Math.floor(form.contributionAmount / 12);
  form.contributionAmount = next;
  if (customAmount.value !== "") {
    customAmount.value = String(next);
  }
  cadence.value = newCadence;
};

// On blur of the custom-amount input: commit to form.contributionAmount.
// If the typed value matches a preset, snap the radio selection to that
// preset row and clear the custom input.
const commitCustomAmount = () => {
  const raw = customAmount.value;
  if (raw === "" || raw === null || raw === undefined) return;
  const n = Math.max(0, Math.floor(Number(raw)));
  if (!Number.isFinite(n)) {
    customAmount.value = "";
    return;
  }
  const matched = presetRows.value.find((p) => p.cadenceAmount === n);
  if (matched) {
    form.contributionAmount = matched.cadenceAmount;
    customAmount.value = "";
  } else {
    form.contributionAmount = n;
  }
};

const {
  initializeHelcimPay,
  verifyPayment,
  cleanup: cleanupHelcimPay,
} = useHelcimPay();

const isFormValid = computed(() => {
  return (
    form.name &&
    form.email &&
    form.circle &&
    Number.isInteger(form.contributionAmount) &&
    form.contributionAmount >= 0 &&
    form.agreedToGuidelines
  );
});

const needsPayment = computed(() => {
  return requiresPayment(form.contributionAmount);
});

const flowSummary = computed(() => {
  const amount = form.contributionAmount || 0;
  return {
    name: form.name,
    email: form.email,
    circle: form.circle,
    contribution: amount > 0 ? formatContribution(amount, cadence.value) : "$0",
  };
});

const handleSubmit = async () => {
  if (isSubmitting.value || !isFormValid.value) return;

  isSubmitting.value = true;
  errorMessage.value = "";
  flowState.value = "creating-customer";

  try {
    const response = await $fetch("/api/helcim/customer", {
      method: "POST",
      body: {
        name: form.name,
        email: form.email,
        circle: form.circle,
        contributionAmount: form.contributionAmount,
        agreedToGuidelines: form.agreedToGuidelines,
        billingAddress: form.billingAddress,
      },
    });

    if (!response.success) {
      throw new Error("Failed to create account.");
    }

    customerId.value = response.customerId;
    customerCode.value = response.customerCode;

    if (!needsPayment.value) {
      flowState.value = "creating-subscription";
      await createSubscription();
      return;
    }

    flowState.value = "opening-payment";
    await initializeHelcimPay(customerId.value, customerCode.value, 0);

    const paymentResult = await verifyPayment();
    if (!paymentResult?.success) {
      throw new Error("Payment was not completed.");
    }
    paymentToken.value = paymentResult.cardToken;

    flowState.value = "processing-payment";
    await $fetch("/api/helcim/verify-payment", {
      method: "POST",
      body: {
        cardToken: paymentResult.cardToken,
        customerId: customerId.value,
      },
    });

    flowState.value = "creating-subscription";
    const subscriptionResult = await createSubscription(
      paymentResult.cardToken,
    );

    if (!subscriptionResult || subscriptionResult.success === false) {
      successMessage.value =
        "Payment successful. Subscription setup may need manual completion.";
      flowState.value = "success";
    }
  } catch (error) {
    console.error("Join flow error:", error);
    errorMessage.value =
      error.data?.message ||
      error.message ||
      "Something went wrong. Please try again.";
    flowState.value = "error";
  } finally {
    isSubmitting.value = false;
  }
};

const createSubscription = async (cardToken = null) => {
  try {
    const response = await $fetch("/api/helcim/subscription", {
      method: "POST",
      body: {
        customerId: customerId.value,
        customerCode: customerCode.value,
        contributionAmount: form.contributionAmount,
        cadence: cadence.value,
        cardToken: cardToken,
      },
    });

    if (response.success) {
      subscriptionData.value = response.subscription;
      flowState.value = "success";
      successMessage.value = "Your membership is active.";
    } else {
      throw new Error("Subscription creation failed - response not successful");
    }
  } catch (error) {
    console.error("Subscription creation error:", error);
    console.error("Error details:", {
      message: error.message,
      statusCode: error.statusCode,
      statusMessage: error.statusMessage,
      data: error.data,
    });
    console.error(
      "Subscription creation completely failed, but payment was successful",
    );
    return {
      success: false,
      error:
        error.data?.message || error.message || "Failed to create subscription",
    };
  }
};

const closeFlowOverlay = () => {
  flowState.value = "idle";
  errorMessage.value = "";
};

onUnmounted(() => {
  cleanupHelcimPay();
});
</script>

<style scoped>
/* ---- HERO (split, matches about.vue) ---- */
.join-hero {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  align-items: stretch;
  border-bottom: 1px dashed var(--border);
}
.join-hero-left {
  padding: 32px 32px 28px;
  border-right: 1px dashed var(--border);
  align-self: stretch;
}
.join-hero-left h1 {
  font-family: "Brygada 1918", serif;
  font-size: 28px;
  font-weight: 600;
  color: var(--text-bright);
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin: 0 0 12px;
}
.join-hero-left p {
  color: var(--text-dim);
  line-height: 1.7;
  font-size: 13px;
  margin: 0;
  max-width: 460px;
}
.join-hero-right {
  padding: 32px;
  align-self: stretch;
}
.join-hero-right .section-label {
  margin-bottom: 10px;
}
.join-hero-right ul {
  list-style: none;
  padding: 0;
  margin: 0;
}
.join-hero-right li {
  font-size: 12px;
  color: var(--text-dim);
  line-height: 1.7;
  padding: 2px 0 2px 14px;
  position: relative;
}
.join-hero-right li::before {
  content: "›";
  position: absolute;
  left: 0;
  color: var(--candle-faint);
}

/* ---- TWO-COL GRID ---- */
.join-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: stretch;
  border-bottom: 1px dashed var(--border);
}
.join-main {
  border-right: 1px dashed var(--border);
  padding: 32px;
  min-width: 0;
}
.join-aside {
  padding: 32px;
  min-width: 0;
  position: relative;
}
.join-main-inner {
  max-width: 560px;
}
.join-aside-inner {
  max-width: 460px;
}

/* ---- SECTION LABEL (hero + aside + auth'd branch DashedBox) ---- */
.section-label {
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
  display: block;
  margin-bottom: 8px;
}

/* ---- FORM BLOCKS ---- */
.form-block {
  margin-bottom: 32px;
}
.form-block:last-of-type {
  margin-bottom: 0;
}
.form-block h2 {
  font-family: "Brygada 1918", serif;
  font-size: 18px;
  font-weight: 500;
  color: var(--text-bright);
  margin: 0 0 4px;
}
.form-block-intro {
  font-size: 12px;
  color: var(--text-dim);
  margin: 0 0 14px;
  line-height: 1.6;
}

/* ---- IDENTITY GRID ---- */
.identity-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
.field-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.field-row label {
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.form-input {
  background: var(--input-bg);
  border: 1px dashed var(--border);
  color: var(--text-bright);
  font-family: "Commit Mono", monospace;
  font-size: 13px;
  padding: 10px 14px;
  width: 100%;
  outline: none;
  transition: border-color 0.15s;
}
.form-input:focus {
  border-color: var(--candle);
  border-style: solid;
}
.form-input::placeholder {
  color: var(--text-faint);
}
.field-error {
  font-size: 11px;
  color: var(--ember);
  margin: 0;
}

/* ---- PWYC ---- */
.pwyc-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 4px;
  gap: 12px;
}
.cadence-toggle {
  display: inline-flex;
  border: 1px dashed var(--border);
}
.cadence-toggle button {
  background: transparent;
  border: none;
  padding: 5px 12px;
  font-family: "Commit Mono", monospace;
  font-size: 10px;
  color: var(--text-faint);
  cursor: pointer;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.cadence-toggle button.active {
  background: var(--parch);
  color: var(--parch-text);
}

.pwyc-list {
  list-style: none;
  padding: 0;
  margin: 0;
  border-top: 1px dashed var(--border);
  border-bottom: 1px dashed var(--border);
}
.pwyc-row {
  position: relative;
  border-bottom: 1px dashed var(--border);
  transition: background 0.12s;
}
.pwyc-row:last-of-type {
  border-bottom: none;
}
.pwyc-row:hover {
  background: var(--surface);
}
.pwyc-row.selected {
  background: var(--input-bg);
}
.pwyc-row.selected::before {
  content: "›";
  position: absolute;
  left: 12px;
  color: var(--candle);
  font-size: 14px;
  top: 50%;
  transform: translateY(-50%);
  line-height: 1;
}
.pwyc-radio {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
  pointer-events: none;
}
.pwyc-radio:focus-visible + .pwyc-row-content {
  outline: 1px solid var(--candle);
  outline-offset: -2px;
}
.pwyc-row-content {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 8px 14px 8px 28px;
  cursor: pointer;
}
.pwyc-amt {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-bright);
  min-width: 36px;
  flex-shrink: 0;
}
.pwyc-row.selected .pwyc-amt {
  color: var(--candle);
}
.pwyc-label {
  font-size: 12px;
  color: var(--text-dim);
  line-height: 1.5;
  flex: 1;
}
.pwyc-row.selected .pwyc-label {
  color: var(--text-bright);
}
.pwyc-tag {
  font-size: 9px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--candle);
  border: 1px dashed var(--candle-faint);
  padding: 1px 6px;
  flex-shrink: 0;
}

/* Custom row */
.pwyc-custom {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 6px 14px 6px 28px;
  cursor: default;
}
.pwyc-custom:hover {
  background: transparent;
}
.pwyc-custom.selected {
  background: var(--input-bg);
}
.pwyc-custom-input-wrap {
  display: flex;
  align-items: center;
  border: 1px dashed var(--border);
  background: var(--input-bg);
  height: 26px;
  flex-shrink: 0;
}
.pwyc-custom-input-wrap .currency {
  padding: 0 2px 0 6px;
  color: var(--text-faint);
  font-weight: 600;
  font-size: 12px;
}
.pwyc-custom-input {
  border: none;
  background: transparent;
  font-family: "Commit Mono", monospace;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-bright);
  padding: 0 6px 0 0;
  width: 56px;
  outline: none;
  -moz-appearance: textfield;
}
.pwyc-custom-input::-webkit-outer-spin-button,
.pwyc-custom-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* ---- SUBMIT ROW ---- */
.submit-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 20px;
  flex-wrap: wrap;
}
.agreement-label {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  font-size: 12px;
  color: var(--text);
  line-height: 1.55;
  cursor: pointer;
  flex: 1;
  min-width: 240px;
}
.agreement-label input {
  margin-top: 3px;
  flex-shrink: 0;
}
.agreement-label :deep(a) {
  color: var(--candle);
  text-decoration: underline;
}
.submit-btn {
  display: inline-block;
  background: var(--parch);
  color: var(--parch-accent);
  font-family: "Commit Mono", monospace;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.04em;
  border: 1px solid var(--parch);
  padding: 12px 24px;
  cursor: pointer;
  transition: all 0.15s;
  flex-shrink: 0;
}
.submit-btn:hover {
  background: var(--parch-hover);
  color: var(--parch-text);
}
.submit-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ---- TRUST LIST (aside) ---- */
.trust-list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.trust-list li {
  font-size: 12px;
  color: var(--text-dim);
  line-height: 1.65;
  padding: 0 0 14px 14px;
  position: relative;
}
.trust-list li:last-child {
  padding-bottom: 0;
}
.trust-list li::before {
  content: "›";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--candle-faint);
}
.trust-list li :deep(strong) {
  color: var(--text-bright);
  font-weight: 600;
}

/* ---- ERROR BOX ---- */
.error-box {
  border: 1px dashed var(--ember);
  color: var(--ember);
  padding: 12px 16px;
  font-size: 12px;
  margin-bottom: 20px;
  max-width: 560px;
}

/* ---- AUTH'D MEMBER BRANCH ---- */
.full-section {
  padding: 32px;
  border-bottom: 1px dashed var(--border);
}
.full-section h2 {
  font-family: "Brygada 1918", serif;
  font-size: 20px;
  font-weight: 500;
  color: var(--text-bright);
  margin-bottom: 16px;
}
.section-intro {
  font-size: 13px;
  color: var(--text-dim);
  line-height: 1.65;
  margin-bottom: 20px;
}
.member-info-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  max-width: 500px;
  margin-bottom: 8px;
}
.info-value {
  font-family: "Brygada 1918", serif;
  font-size: 18px;
  font-weight: 500;
  color: var(--text-bright);
  margin-top: 4px;
}
.button-row {
  display: flex;
  gap: 12px;
  align-items: center;
  margin-top: 20px;
}
.form-submit {
  display: inline-block;
  background: var(--parch);
  color: var(--parch-accent);
  font-family: "Commit Mono", monospace;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  border: 1px solid var(--parch);
  padding: 12px 28px;
  cursor: pointer;
  transition: all 0.2s;
  text-decoration: none;
  text-align: center;
}
.form-submit:hover {
  background: var(--parch-hover);
  border-color: var(--parch-hover);
  color: var(--parch-text);
  text-decoration: none;
}
.parchment-link {
  color: var(--candle-faint);
  font-size: 12px;
}
.parchment-link:hover {
  color: var(--candle-dim);
}
.capitalize {
  text-transform: capitalize;
}

/* ---- PARCHMENT LIST (only used in auth'd branch ParchmentInset) ---- */
:deep(.parchment-inset ul) {
  list-style: none;
  max-width: 560px;
  padding: 0;
}
:deep(.parchment-inset ul li) {
  font-size: 13px;
  color: var(--parch-text-dim);
  line-height: 1.75;
  padding: 4px 0;
  padding-left: 16px;
  position: relative;
}
:deep(.parchment-inset ul li::before) {
  content: "›";
  position: absolute;
  left: 0;
  color: var(--candle-faint);
  font-size: 14px;
  line-height: 1.4;
}

/* ---- RESPONSIVE ---- */
@media (max-width: 1024px) {
  .join-grid {
    grid-template-columns: 1fr;
  }
  .join-main {
    border-right: none;
    border-bottom: 1px dashed var(--border);
  }
}
@media (max-width: 768px) {
  .join-hero {
    grid-template-columns: 1fr;
  }
  .join-hero-left {
    border-right: none;
    border-bottom: 1px dashed var(--border);
    padding: 24px 20px 20px;
  }
  .join-hero-right {
    padding: 24px 20px;
  }
  .join-hero-left h1 {
    font-size: 26px;
  }
  .identity-grid {
    grid-template-columns: 1fr;
  }
  .join-main,
  .join-aside {
    padding: 24px 20px;
  }
  .full-section {
    padding: 24px 20px;
  }
  .member-info-grid {
    grid-template-columns: 1fr;
  }
}
@media (max-width: 480px) {
  .submit-row {
    flex-direction: column;
    align-items: stretch;
  }
  .submit-btn {
    width: 100%;
  }
  .button-row {
    flex-direction: column;
    align-items: stretch;
  }
}
</style>
