/* ==========================================================================
   /links - the link hub behind the social bios.

   Its address in the wild is go.soulequestrian.com, which redirects here.
   The redirect exists because Vercel checks the filesystem before it checks
   rewrites, so a host-conditioned rewrite of "/" never fires: index.html
   wins first. A redirect is evaluated before the filesystem and does.

   Self-contained on purpose. The hub never loads site.css, so every token it
   needs is redeclared here with the same value the main sheet uses. That
   duplication is the price of a page that is one small file and cannot be
   broken by an edit somewhere else in the system. If a brand colour changes
   in site.css, change it here too.

   Order: tokens -> base -> masthead -> feature -> links -> form -> footer
   -> motion -> responsive.
   ========================================================================== */

:root {
  --hub-green:      #14302A;
  --hub-green-deep: #0F241F;
  --hub-gold:       #AF874A;
  --hub-gold-soft:  #C6A470;
  --hub-ivory:      #F8F5EF;

  /* Oasis teal. The site spends this hue on the grand opening and on nothing
     else, which is what makes the opening read as news rather than as more
     chrome. Kept here so the hub says the same thing without loading the
     ribbon's stylesheet. 7.9:1 on the green, so it is safe for small text. */
  --hub-teal:      #63D6B4;
  --hub-teal-glow: rgba(99, 214, 180, 0.55);
  --hub-teal-hair: rgba(99, 214, 180, 0.42);
  --hub-teal-fill: rgba(99, 214, 180, 0.06);

  /* Ivory at measured alphas. Every one of these was checked against
     --hub-green for WCAG AA before it was used on text. */
  --hub-ivory-62:  rgba(248, 245, 239, 0.62);   /* 5.9:1 on green */
  --hub-ivory-28:  rgba(248, 245, 239, 0.28);   /* input borders */
  --hub-ivory-16:  rgba(248, 245, 239, 0.16);   /* hairlines */
  --hub-ivory-06:  rgba(248, 245, 239, 0.06);   /* input fill */

  --hub-font-display: 'Cormorant Garamond', 'Cormorant Garamond Fallback', Georgia, 'Times New Roman', serif;
  --hub-font-body:    'Plus Jakarta Sans', 'Plus Jakarta Sans Fallback', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --hub-ls-eyebrow: 0.22em;
  --hub-ls-button:  0.14em;

  /* One column, one measure. The hub is a phone page that happens to also
     open on a laptop, so the column never grows past a comfortable read. */
  --hub-col:    560px;
  --hub-gutter: clamp(20px, 6vw, 32px);
  --hub-photo-h: clamp(132px, 30vw, 200px);

  --hub-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

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

html {
  -webkit-text-size-adjust: 100%;
  overflow-x: hidden;
  overflow-x: clip;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100svh;
  background: var(--hub-green);
  color: var(--hub-ivory);
  font-family: var(--hub-font-body);
  font-weight: 300;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-wrap: break-word;
  word-wrap: break-word;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

img { max-width: 100%; display: block; }

a { color: inherit; }

:focus-visible {
  outline: 2px solid var(--hub-gold-soft);
  outline-offset: 3px;
}

.hub-vh {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

.hub-skip {
  position: absolute; left: 8px; top: -60px; z-index: 40;
  background: var(--hub-ivory); color: var(--hub-green);
  font-family: var(--hub-font-display); font-weight: 600; font-size: 14px;
  letter-spacing: var(--hub-ls-button); text-transform: uppercase;
  padding: 12px 20px; text-decoration: none;
  transition: top 150ms var(--hub-ease);
}
.hub-skip:focus { top: 8px; }

/* The page column. Padded for the notch and the home indicator so the hub
   is never clipped inside an in-app browser on iOS. */
.hub-shell {
  width: 100%;
  max-width: calc(var(--hub-col) + var(--hub-gutter) * 2);
  margin: 0 auto;
  padding-left: max(var(--hub-gutter), env(safe-area-inset-left));
  padding-right: max(var(--hub-gutter), env(safe-area-inset-right));
}

/* ==========================================================================
   Grand opening ribbon
   The component itself is /assets/anno.css, shared verbatim with the nine
   pages of the site so the two can never drift apart. The single line below
   is the only thing this page adds: links.html opts into viewport-fit=cover
   for the full-bleed photograph, which the site pages do not, so the ribbon
   has to clear the notch itself now that it sits above everything.
   ========================================================================== */
.hor-anno { padding-top: env(safe-area-inset-top); }

/* ==========================================================================
   Masthead - photograph, then identity. Left aligned, not centred: a centred
   logo over centred rows is the stock link-in-bio look, and this club does
   not look like anyone else.

   The photograph is a band at the top and no text is ever set on it. That is
   a contrast decision, not a taste one. Ivory body copy needs a scrim around
   0.62 to clear AA against a bright photo pixel, and the gold tagline needs
   about 0.86, which is opaque enough that the photograph may as well not be
   there. Rather than pick between a readable page and a visible photograph,
   the text moved below the image, where every colour clears AA against flat
   green with room to spare. Only the horse mark overlaps the image, and a
   mark is a graphical object held to 3:1, which the fade clears many times
   over.
   ========================================================================== */
.hub-masthead {
  position: relative;
  isolation: isolate;
  /* The mark rises into the last 30px of the photograph. */
  padding-top: calc(var(--hub-photo-h) - 30px);
  padding-bottom: 26px;
  text-align: center;
}

.hub-masthead__photo,
.hub-masthead__scrim {
  position: absolute;
  left: 0; right: 0; top: 0;
  height: var(--hub-photo-h);
}
.hub-masthead__photo { z-index: -2; overflow: hidden; }
.hub-masthead__scrim { z-index: -1; }

.hub-masthead__photo img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center 46%;
}

/* Light at the top so the photograph is actually a photograph, then hard
   into flat green over the last fifth so the band has no visible edge. */
.hub-masthead__scrim {
  background: linear-gradient(to bottom,
    rgba(15, 36, 31, 0.28) 0%,
    rgba(15, 36, 31, 0.34) 46%,
    rgba(20, 48, 42, 0.88) 84%,
    var(--hub-green) 100%);
}

.hub-mark {
  height: 46px;
  width: auto;
  margin: 0 auto 14px;
}

.hub-wordmark {
  font-family: var(--hub-font-display);
  font-weight: 500;
  font-size: clamp(1.85rem, 8.2vw, 2.5rem);
  line-height: 1.04;
  letter-spacing: 0.005em;
  margin: 0;
  color: var(--hub-ivory);
}
.hub-wordmark span {
  display: block;
}

.hub-tagline {
  font-family: var(--hub-font-display);
  font-size: clamp(1rem, 4vw, 1.15rem);
  font-weight: 400;
  line-height: 1.35;
  color: var(--hub-gold-soft);
  margin: 12px 0 0;
}

.hub-meta {
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
  font-size: 14px;
  line-height: 1.65;
  color: var(--hub-ivory-62);
}

/* ==========================================================================
   Buttons
   ========================================================================== */
.hub-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  min-height: 56px;
  padding: 17px 28px;
  border: 1px solid transparent;
  border-radius: 0;
  background: var(--hub-gold-soft);
  color: var(--hub-green);
  font-family: var(--hub-font-display);
  font-weight: 600;
  font-size: 16px;
  line-height: 1;
  letter-spacing: var(--hub-ls-button);
  text-transform: uppercase;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  transition: background 200ms var(--hub-ease), transform 200ms var(--hub-ease);
}
.hub-btn:hover { background: var(--hub-gold); }
.hub-btn:active { transform: translateY(1px); }
.hub-btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }

.hub-btn svg { width: 1.05em; height: 1.05em; flex: none; }

/* ==========================================================================
   Links - hairline rows, no cards. Elevation is reserved for the feature
   panel above, so these group with rules and space instead.
   ========================================================================== */
.hub-links {
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
}

.hub-link {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 72px;
  padding: 16px 2px;
  border-bottom: 1px solid var(--hub-ivory-16);
  text-decoration: none;
  text-align: center;
  color: var(--hub-ivory);
  transition: color 200ms var(--hub-ease);
}
.hub-link:active { opacity: 0.75; }
.hub-link:focus-visible { outline-offset: -2px; }

/* The glyph rides inside the title rather than sitting at the far right rail:
   on a centred row a right-aligned arrow reads as belonging to the rule, not
   to the words. inline-flex keeps it on the title's baseline run. */
.hub-link__title {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--hub-font-display);
  font-weight: 500;
  font-size: 1.42rem;
  line-height: 1.15;
}

.hub-link__glyph {
  flex: none;
  width: 17px; height: 17px;
  color: var(--hub-gold-soft);
  transition: transform 250ms var(--hub-ease);
}
.hub-link:hover .hub-link__glyph { transform: translate(2px, -2px); }
/* The second row scrolls down the page rather than leaving it, so its arrow
   points that way and nudges down on hover instead of up and out. */
.hub-link[href^="#"]:hover .hub-link__glyph { transform: translateY(2px); }

.hub-link__sub {
  display: block;
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--hub-ivory-62);
  margin-top: 5px;
}

/* ==========================================================================
   The opening - the head of the list, and the only item that is a box.

   It is a list item, not a banner: it sits inside the same <ul> as the other
   two and scrolls with them. Everything that makes it stand out is contained
   in this block, so when the date passes and the item removes itself the list
   closes up with nothing left behind.
   ========================================================================== */
.hub-link--event {
  gap: 0;
  min-height: 0;
  padding: 24px 20px 22px;
  margin-bottom: 22px;
  border: 1px solid var(--hub-teal-hair);
  background: var(--hub-teal-fill);
}
/* It carries its own border, so it opts out of the row hairline. */
.hub-link--event { border-bottom: 1px solid var(--hub-teal-hair); }
.hub-link--event:hover { background: rgba(99, 214, 180, 0.10); border-color: var(--hub-teal); }
.hub-link--event:focus-visible { outline-color: var(--hub-teal); outline-offset: 3px; }

.hub-link__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  font-family: var(--hub-font-display);
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: var(--hub-ls-eyebrow);
  text-transform: uppercase;
  color: var(--hub-teal);
}

/* The pinging diamond, the same mark the site's ribbon uses. The ring is a
   second diamond scaling out behind the first. */
.hub-pulse {
  position: relative;
  flex: none;
  width: 8px; height: 8px;
  background: var(--hub-teal);
  transform: rotate(45deg);
  box-shadow: 0 0 9px var(--hub-teal-glow);
}
.hub-pulse::after {
  content: "";
  position: absolute; inset: 0;
  background: var(--hub-teal);
}

.hub-link__date {
  display: block;
  margin-top: 12px;
  font-family: var(--hub-font-display);
  font-weight: 500;
  font-size: clamp(1.5rem, 6.4vw, 1.9rem);
  line-height: 1.1;
  color: var(--hub-ivory);
}
.hub-link--event .hub-link__sub { margin-top: 7px; }

/* Filled, because the owner's point is that this one has to stand out. It is
   the only teal fill on the page and it never shares a screen with the gold
   submit button, which sits far below the fold. */
.hub-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  margin-top: 18px;
  min-height: 48px;
  padding: 14px 26px;
  background: var(--hub-teal);
  color: var(--hub-green);
  font-family: var(--hub-font-display);
  font-weight: 600;
  font-size: 15px;
  line-height: 1;
  letter-spacing: var(--hub-ls-button);
  text-transform: uppercase;
  white-space: nowrap;
  transition: background 200ms var(--hub-ease), transform 200ms var(--hub-ease);
}
.hub-cta svg { width: 1.02em; height: 1.02em; flex: none; }
.hub-link--event:hover .hub-cta { background: #7FE2C6; }
.hub-link--event:active .hub-cta { transform: translateY(1px); }

/* ==========================================================================
   Form
   ========================================================================== */
/* No rule of its own. The link list already closes with one, and two hairlines
   a gap apart read as a mistake rather than as a separation. */
/* Deliberate emptiness. The owner asked for the form to be out of sight on
   arrival, so the page gives the two links the whole first screen and lets
   the form begin below it. The second link scrolls here, so nobody has to
   find it by guessing. */
.hub-form-section {
  margin-top: clamp(150px, 30vh, 260px);
}
/* It takes focus when the second link jumps here, but it is a landing place,
   not a control, so it does not draw a ring around the whole section. */
.hub-form-section:focus { outline: none; }

.hub-h2 {
  text-align: center;
  font-family: var(--hub-font-display);
  font-weight: 500;
  font-size: clamp(1.85rem, 7.6vw, 2.2rem);
  line-height: 1.1;
  margin: 0;
  color: var(--hub-ivory);
}

.hub-lede {
  font-size: 15.5px;
  line-height: 1.7;
  color: var(--hub-ivory-62);
  margin: 14px auto 0;
  max-width: 44ch;
  text-align: center;
}

.hub-form {
  display: flex;
  flex-direction: column;
  gap: 18px;
  margin-top: 26px;
  text-align: left;
}
.hub-form__submit { text-align: center; }

.hub-field { display: flex; flex-direction: column; gap: 7px; }

.hub-field__label {
  font-family: var(--hub-font-display);
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--hub-gold-soft);
}
.hub-field__req { margin-left: 3px; }

/* 16px is not a style choice. Anything smaller makes iOS Safari zoom the
   viewport on focus, and the visitor has to pinch back out to keep typing. */
.hub-input {
  width: 100%;
  min-height: 52px;
  font-family: var(--hub-font-body);
  font-weight: 300;
  font-size: 16px;
  color: var(--hub-ivory);
  background: var(--hub-ivory-06);
  border: 1px solid var(--hub-ivory-28);
  border-radius: 0;
  padding: 14px 15px;
  -webkit-appearance: none;
  appearance: none;
  transition: border-color 200ms var(--hub-ease), background 200ms var(--hub-ease);
}
.hub-input::placeholder { color: rgba(248, 245, 239, 0.62); opacity: 1; }
.hub-input:hover { border-color: rgba(248, 245, 239, 0.42); }
.hub-input:focus {
  outline: 2px solid var(--hub-gold-soft);
  outline-offset: 1px;
  border-color: var(--hub-gold-soft);
  background: rgba(248, 245, 239, 0.09);
}

textarea.hub-input { resize: vertical; min-height: 104px; line-height: 1.55; }

select.hub-input {
  cursor: pointer;
  padding-right: 42px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23C6A470' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>");
  background-repeat: no-repeat;
  background-position: right 14px center;
}
/* The native dropdown list paints on the OS surface, not ours, so its own
   options need colours that survive either system theme. */
select.hub-input option { color: #14302A; background: #F8F5EF; }

.hub-phone { display: flex; gap: 10px; }
.hub-phone select.hub-input { flex: 0 1 clamp(118px, 40%, 220px); min-width: 106px; width: auto; }
.hub-phone input.hub-input { flex: 1 1 auto; min-width: 0; width: auto; }

.hub-honeypot { position: absolute; left: -9999px; top: auto; width: 1px; height: 1px; overflow: hidden; }

/* The form is withheld until links.js has actually attached its submit
   handler, and links.js is what clears .hub-unwired. Without that gate a
   visitor whose script never arrived would see a working-looking form whose
   submit posts to /links, which Vercel answers with a bare 405: the page is
   gone and everything they typed goes with it. Withheld, they get the
   address instead, which is a worse form and a much better outcome. */
.hub-noscript { display: none; }
.hub-unwired .hub-noscript { display: block; }
.hub-unwired .hub-form { display: none; }

/* Sent / fallback confirmation, swapped in where the form was */
.hub-confirm { display: flex; flex-direction: column; gap: 14px; align-items: center; text-align: center; }
.hub-confirm__diamond {
  width: 14px; height: 14px;
  background: var(--hub-gold-soft);
  transform: rotate(45deg);
  margin: 4px 0 6px;
}
.hub-confirm p {
  margin-inline: auto;
  font-size: 15.5px;
  line-height: 1.7;
  color: var(--hub-ivory-62);
  margin: 0;
  max-width: 44ch;
}
.hub-confirm a { color: var(--hub-gold-soft); }

/* ==========================================================================
   Elsewhere - Instagram and the website, as a pair of marks rather than two
   more rows. They are the two places the club already exists, not two more
   things to read, so they get glyphs and a 52px hit box each and stay out of
   the reading order until someone is looking for them.
   ========================================================================== */
.hub-social {
  display: flex;
  justify-content: center;
  gap: 14px;
  margin-top: 30px;
}

.hub-social__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px; height: 52px;
  border: 1px solid var(--hub-ivory-28);
  color: var(--hub-ivory);
  text-decoration: none;
  transition: color 200ms var(--hub-ease), border-color 200ms var(--hub-ease),
    background 200ms var(--hub-ease);
}
.hub-social__btn svg { width: 21px; height: 21px; display: block; }
.hub-social__btn:hover {
  color: var(--hub-gold-soft);
  border-color: var(--hub-gold-soft);
  background: rgba(248, 245, 239, 0.05);
}
.hub-social__btn:active { opacity: 0.75; }

/* ==========================================================================
   Footer
   ========================================================================== */
/* Vertical padding only. The footer also carries .hub-shell, and the padding
   shorthand would reset that class's left and right gutters to zero, pushing
   the footer text out of line with every other row on the page. */
.hub-footer {
  position: relative;
  margin-top: 34px;
  padding-top: 26px;
  padding-bottom: max(34px, calc(env(safe-area-inset-bottom) + 24px));
  font-size: 13.5px;
  color: var(--hub-ivory-62);
}
.hub-footer::before {
  content: "";
  position: absolute; top: 0; height: 1px;
  left: max(var(--hub-gutter), env(safe-area-inset-left));
  right: max(var(--hub-gutter), env(safe-area-inset-right));
  background: var(--hub-ivory-16);
}
.hub-footer p { margin: 0; }
.hub-footer { text-align: center; }

/* ==========================================================================
   Motion - opted into, never out of. With no media query support, or with
   reduced motion asked for, the page simply renders finished. The stagger
   earns its place by walking the eye down the one path this page has:
   who we are, what is happening next, where to go.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  .hub-rise {
    opacity: 0;
    transform: translateY(12px);
    animation: hub-rise 620ms var(--hub-ease) forwards;
  }
  .hub-rise--1 { animation-delay:  60ms; }
  .hub-rise--2 { animation-delay: 150ms; }
  .hub-rise--3 { animation-delay: 240ms; }
  .hub-rise--4 { animation-delay: 330ms; }
}

@keyframes hub-rise {
  to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: no-preference) {
  .hub-pulse::after { animation: hubPing 2400ms var(--hub-ease) infinite; }
}
@keyframes hubPing {
  0%   { transform: scale(1);   opacity: .6; }
  70%  { transform: scale(3.4); opacity: 0; }
  100% { transform: scale(3.4); opacity: 0; }
}

/* ==========================================================================
   Responsive
   ========================================================================== */

/* Narrow phones: the country-code select and the number stop sharing a row
   before either becomes too cramped to read. */
@media (max-width: 400px) {
  .hub-phone { flex-direction: column; }
  .hub-phone select.hub-input,
  .hub-phone input.hub-input { flex: 1 1 auto; width: 100%; }
}

/* From tablet up the column stops growing and gains air instead. The photo
   band gets taller so it does not read as a thin strip on a wide screen. */
@media (min-width: 700px) {
  .hub-masthead { padding-bottom: 34px; }
  .hub-mark { height: 56px; }
  .hub-links { margin-top: 24px; }
  .hub-link { min-height: 84px; padding: 20px 2px; }
  .hub-link__title { font-size: 1.55rem; }
  .hub-btn { width: auto; min-width: 260px; }

}

/* Pointer-less devices get no hover offsets, which would otherwise stick
   after a tap on some mobile browsers. */
@media (hover: none) {
  .hub-link:hover .hub-link__glyph,
  .hub-link[href^="#"]:hover .hub-link__glyph { transform: none; }
  .hub-btn:hover { background: var(--hub-gold-soft); }
}
