/* ==========================================================================
   B VISUAL — sobo.css
   SOBO Spotlight campaign page. Reuses every token, type step, form
   primitive, pinned-track and scroller component from tokens.css / shell.css.
   Adds only what this campaign needs. No new type steps, no box-shadow.

   Colour direction: acid lime leads here (it is the campaign's attention
   colour), on the aubergine --plum rather than the site's charcoal ground,
   with violet and teal supporting.
   ========================================================================== */

/* Charcoal canvas, not plum. design-system.md reserves --plum for deliberate
   FEATURE blocks — hero, CTA band, footer — and makes --ink the ground. This
   page had plum on the body, so every section inherited it and the whole thing
   read as one purple slab. The hero and the closing band keep their plum below;
   everything between them now sits on charcoal. */
body[data-page="sobo"] { background: var(--ink); }

/* Scroll-linked progress bar ---------------------------------------------- */
/* .scroll-progress moved to shell.css — it runs on every page now. */

/* .is-placeholder moved to shell.css — About uses it too, and a component
   living in one page's stylesheet is the defect this project keeps hitting. */

/* ==========================================================================
   Hero
   ========================================================================== */

.sobo-hero {
  position: relative;
  isolation: isolate;
  overflow: clip;
  min-height: min(100dvh, 60rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-top: calc(var(--nav-h) + var(--s8));
  padding-bottom: var(--s8);
  background-image: var(--surface-plum);
}
.sobo-hero__inner { position: relative; z-index: 3; }

.sobo-hero__grid {
  position: absolute;
  inset: -10% -5%;
  z-index: 0;
  pointer-events: none;
  opacity: .55;
  /* Street-grid suggestion, not a map: an even lattice asserts no geography. */
  background-image:
    linear-gradient(to right, rgba(216,255,53,.10) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(216,255,53,.10) 1px, transparent 1px);
  background-size: clamp(42px, 6vw, 84px) clamp(42px, 6vw, 84px);
  -webkit-mask-image: radial-gradient(85% 75% at 25% 35%, #000 0%, transparent 80%);
          mask-image: radial-gradient(85% 75% at 25% 35%, #000 0%, transparent 80%);
}
.sobo-hero__glow {
  position: absolute;
  z-index: 1;
  right: -12vw; top: 4vh;
  width: min(62vw, 780px);
  aspect-ratio: 1;
  pointer-events: none;
  opacity: .20;
  background: radial-gradient(circle at 50% 50%, var(--lime) 0%, rgba(216,255,53,.35) 30%, rgba(216,255,53,0) 66%);
}

/* SOBO lockup. Sized in vw so it scales with the hero rather than sitting at
   a fixed size, and never recoloured — the heart is already the campaign
   neon in the supplied file. */
.sobo-lockup {
  position: absolute;
  z-index: 2;
  right: clamp(1rem, 5vw, 6rem);
  bottom: clamp(2rem, 8vh, 7rem);
  width: clamp(7rem, 15vw, 14rem);
  pointer-events: none;
}
.sobo-lockup img { width: 100%; height: auto; display: block; }

.sobo-eyebrow { color: var(--lime); }
.sobo-eyebrow::before { background: var(--lime); }

.sobo-hero__title { margin: var(--s6) 0 0; }
.sobo-line { display: block; color: var(--paper); }
/* The focal line: acid lime, layered over the aubergine. */
.sobo-line--hero { color: var(--lime); }

.sobo-hero__sub  { margin-top: var(--s6); color: var(--bone); }
.sobo-hero__actions {
  margin-top: var(--s7);
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3);
}
.sobo-hero__note { margin-top: var(--s5); color: var(--mute); }
.sobo-cta { min-height: 44px; }

@media (max-width: 1000px) { .sobo-lockup { display: none; } }
@media (max-width: 720px) {
  .sobo-hero { padding-top: calc(var(--nav-h) + var(--s6)); }
  .sobo-hero__glow { right: -34vw; width: 88vw; opacity: .16; }
}

/* ==========================================================================
   What you get — cards ride the shared [data-hscroll] track
   ========================================================================== */

.sobo-card {
  flex: none;
  width: clamp(15rem, 27vw, 23rem);
  min-height: clamp(17rem, 30vw, 24rem);
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  padding: var(--s6);
  border: var(--hairline);
  border-radius: var(--r-flat);
  background: rgba(255, 255, 255, .03);
  scroll-snap-align: center;
  transition: border-color var(--d-ui) var(--e-out), background-color var(--d-ui) var(--e-out);
}
.sobo-card:hover { border-color: var(--lime); background: rgba(216, 255, 53, .05); }
.sobo-card__num   { color: var(--lime); }
.sobo-card__title { color: var(--paper); margin-top: auto; }
.sobo-card__text  { color: var(--bone); }
.sobo-included__note { margin-top: var(--s8); color: var(--mute); }

/* ==========================================================================
   Why we're doing it
   ========================================================================== */

.sobo-why__grid {
  display: grid;
  grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr);
  gap: var(--s10);
  align-items: start;
}
.sobo-why__title { color: var(--paper); margin-top: var(--s3); }
.sobo-why__lead  { color: var(--paper); }
.sobo-why__body  { color: var(--bone); margin-top: var(--s5); }
@media (max-width: 900px) { .sobo-why__grid { grid-template-columns: 1fr; gap: var(--s6); } }

/* ==========================================================================
   Process stage panels (inside the shared sticky scroller)
   ========================================================================== */

.sobo-stage {
  position: relative;
  aspect-ratio: 4 / 5;
  border: var(--hairline);
  border-radius: var(--r-flat);
  overflow: hidden;
  background-image: var(--grad-field);
}
.sobo-stage__panel {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: var(--s4);
  opacity: 0;
  transform: scale(1.02);
  transition: opacity var(--d-reveal) var(--e-out), transform var(--d-reveal) var(--e-out);
}
.sobo-stage__panel.is-active { opacity: 1; transform: scale(1); }
/* Uses --t-display rather than its own clamp. The previous value resolved
   larger than the page's display type, so a step number outranked the
   headlines. Reusing the token keeps the page to the five-step scale and
   guarantees the numeral can never exceed the headline it sits beside. */
.sobo-stage__num {
  font-size: var(--t-display);
  font-weight: var(--w-max);
  line-height: .8;
  letter-spacing: var(--tr-display);
  color: var(--lime);
}
.sobo-stage__label { color: var(--paper); }
@media (max-width: 900px) { .sobo-stage { aspect-ratio: 16 / 9; } }

/* ==========================================================================
   Who it's for
   ========================================================================== */

.sobo-for__title { color: var(--paper); margin-top: var(--s3); }
.sobo-tags {
  margin: var(--s8) 0 0;
  display: flex; flex-wrap: wrap; gap: var(--s2);
}
.sobo-tag {
  padding: 10px var(--s4);
  border: var(--hairline);
  border-radius: var(--r-ui);
  color: var(--bone);
}
.sobo-tag:nth-child(3n+1) { border-color: rgba(216, 255, 53, .35); }
.sobo-tag:nth-child(3n+2) { border-color: rgba(131, 102, 255, .38); }
.sobo-tag:nth-child(3n)   { border-color: rgba(18, 219, 180, .32); }
.sobo-for__note { margin-top: var(--s8); color: var(--mute); }

/* ==========================================================================
   Placeholder collage
   ========================================================================== */

.sobo-collage { overflow: clip; }
.sobo-collage__title { color: var(--paper); margin-top: var(--s3); }
.sobo-collage__note  { color: var(--mute); margin-top: var(--s4); }

.sobo-collage__row {
  margin-top: var(--s10);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(var(--s3), 3vw, var(--s7));
  padding-inline: var(--gutter);
}
.sobo-frame { margin: 0; flex: none; width: clamp(8rem, 22vw, 19rem); }
.sobo-frame--tall { width: clamp(7rem, 18vw, 16rem); }
.sobo-frame--wide { width: clamp(11rem, 32vw, 28rem); margin-inline: calc(var(--s4) * -1); z-index: 1; }
.sobo-frame--wide figcaption { padding-left: var(--s4); }

.sobo-ph {
  display: grid;
  place-items: center;
  aspect-ratio: 1 / 1;
  padding: var(--s4);
  text-align: center;
  color: var(--bone-64);
  border: 1px dashed rgba(216, 255, 53, .40);
  border-radius: var(--r-flat);
  background-image: var(--grad-field);
}
.sobo-frame--tall .sobo-ph { aspect-ratio: 3 / 4; }
.sobo-frame--wide .sobo-ph { aspect-ratio: 16 / 10; }
.sobo-frame figcaption { margin-top: var(--s2); color: var(--mute); }
@media (max-width: 720px) {
  .sobo-collage__row { gap: var(--s2); }
  .sobo-frame--wide { margin-inline: calc(var(--s2) * -1); }
}

/* ==========================================================================
   Important details
   ========================================================================== */

.sobo-terms__title { color: var(--paper); margin-top: var(--s3); }
.sobo-facts {
  margin: var(--s8) 0 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s6);
  border-top: var(--hairline);
  padding-top: var(--s6);
}
.sobo-facts dt { color: var(--mute); }
.sobo-facts dd { color: var(--paper); margin: var(--s2) 0 0; }
@media (max-width: 760px) { .sobo-facts { grid-template-columns: 1fr; gap: var(--s5); } }

.sobo-terms__list { margin-top: var(--s10); border-top: var(--hairline); }
.sobo-terms__list li {
  padding-block: var(--s4);
  border-bottom: var(--hairline);
  color: var(--bone);
  padding-left: var(--s6);
  position: relative;
}
.sobo-terms__list li::before {
  content: "";
  position: absolute;
  left: 0; top: calc(var(--s4) + .55em);
  width: 10px; height: 2px;
  background: var(--lime);
}

/* ==========================================================================
   Application form
   ========================================================================== */

.sobo-apply__title { color: var(--paper); margin-top: var(--s3); }
.sobo-apply__sub   { color: var(--bone); margin-top: var(--s5); }

.sobo-form { margin-top: var(--s10); display: flex; flex-direction: column; gap: var(--s5); }
.sobo-form__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s5);
}
@media (max-width: 760px) { .sobo-form__grid { grid-template-columns: 1fr; } }

.sobo-check {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s3);
  align-items: start;
  padding: var(--s4);
  border: var(--hairline);
  border-radius: var(--r-ui);
}
.sobo-check input {
  appearance: none;
  width: 24px; height: 24px;      /* comfortable touch target */
  margin-top: 2px;
  border: 2px solid rgba(255, 255, 255, .34);
  border-radius: 6px;
  background: transparent;
  display: grid; place-content: center;
  transition: border-color var(--d-ui) var(--e-out), background-color var(--d-ui) var(--e-out);
}
.sobo-check input::after {
  content: "";
  width: 10px; height: 10px;
  transform: scale(0);
  background: var(--ink);
  clip-path: polygon(14% 44%, 0 60%, 40% 100%, 100% 18%, 84% 4%, 38% 68%);
  transition: transform var(--d-ui) var(--e-out);
}
.sobo-check input:checked { background: var(--lime); border-color: var(--lime); }
.sobo-check input:checked::after { transform: scale(1); }
.sobo-check label { color: var(--bone); cursor: pointer; }
.sobo-check .field__error { grid-column: 1 / -1; display: none; color: var(--paper); }
.sobo-check.is-invalid { border-color: var(--paper); }
.sobo-check.is-invalid .field__error { display: block; }

.sobo-submit { align-self: flex-start; min-height: 52px; min-width: 230px; margin-top: var(--s2); }
.sobo-submit:disabled { opacity: .55; cursor: not-allowed; }

.sobo-notice {
  color: var(--paper);
  border-top: var(--hairline);
  padding-top: var(--s4);
}
.sobo-notice a { color: var(--bone); text-decoration: underline; text-underline-offset: 3px; }

.sobo-done { margin-top: var(--s10); border-top: 2px solid var(--lime); padding-top: var(--s8); }
.sobo-done__title { color: var(--lime); }
.sobo-done__body  { color: var(--bone); margin-top: var(--s4); }

/* ==========================================================================
   Final CTA
   ========================================================================== */

.sobo-final__note { margin-top: var(--s6); color: var(--mute); }
.sobo-final__note a { color: var(--bone); text-decoration: underline; text-underline-offset: 3px; }
.sobo-final__note a:hover { color: var(--lime); }

/* Touch targets. The site's default button sits at ~39px, which is fine for
   a pointer but under the 44px comfortable target on a phone. Scoped to this
   page so no existing layout shifts. */
body[data-page="sobo"] .btn {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Final CTA: copy left, mark up alongside the headline.

   An auto margin alone only pushed the mark right — it stayed in the flow
   BELOW the note, marooned at the bottom of the section with a screen of empty
   plum above it. Getting it up beside the headline needs two columns.

   Grid rather than float: the five children keep their source order (which is
   also the reading order, and what the staggered reveals animate along), and
   the mark is simply placed into the second column starting at the headline's
   row. align-items:start stops the mark stretching to the tallest row. */
.sobo-final .wrap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: var(--s8);
  align-items: start;
}
.sobo-final .wrap > .label,
.sobo-final .cta-band__title,
.sobo-final .cta-band__actions,
.sobo-final__note { grid-column: 1; }

.sobo-final__mark {
  width: clamp(8rem, 18vw, 16rem);
  height: auto;
  display: block;
  grid-column: 2;
  grid-row: 2 / span 3;      /* from the headline's row down past the note */
  align-self: start;
  margin: 0;
}

/* One column on a phone: side by side would leave the headline about 40% of a
   390px screen, which is unreadable at head size. Back to stacked, mark last
   and still set right. */
@media (max-width: 860px) {
  .sobo-final .wrap { display: block; }
  .sobo-final__mark { margin-top: var(--s8); margin-left: auto; }
}

/* This headline is a 67-character sentence; every other .cta-band__title on
   the site is 9-14 characters ("WORK WITH US", "READY WHEN YOU ARE").
   --t-display is calibrated for those, and at 11vw a sentence this long ran
   past the bottom of the screen. It uses --t-head instead — the existing step
   below, not a new size, so the scale stays at five steps (M1).

   18ch was a measure for display-sized fragments. At head size that would
   wrap far too tight, so it opens up to a proper reading measure. */
.sobo-final .cta-band__title { max-width: 26ch; }

/* ==========================================================================
   Campaign intro
   ========================================================================== */

.sobo-intro {
  position: fixed;
  inset: 0;
  z-index: 120;                 /* above the page, below the nav's own layer */
  display: grid;
  place-items: center;
  overflow: hidden;
}
html.sobo-intro-open { overflow: hidden; }

.sobo-intro__panel {
  position: absolute;
  inset: 0;
  background: var(--plum);
  background-image: var(--surface-plum);
  clip-path: inset(0 0 0 0);
}
.sobo-intro__mark {
  position: relative;
  width: clamp(11rem, 34vw, 26rem);
  /* Padding keeps the clip-path wipe clear of the artwork's own edges, so
     the heart's sides are never shaved by the reveal. */
  padding: 2%;
  will-change: transform, clip-path;
}
.sobo-intro__mark svg { width: 100%; height: auto; display: block; }

/* Draw-on outlines, same idea as the B Visual loader: the lockup is traced
   before it fills.

   NO vector-effect: non-scaling-stroke. getTotalLength() reports user units —
   this file has a 2250-wide viewBox — but non-scaling-stroke resolves the dash
   pattern in screen pixels. The mark renders around 416px, so the dash would
   come out roughly five times shorter than the path and the outline would stop
   most of the way round. Keeping the stroke in user space makes dash and path
   share one coordinate system.

   stroke-width is therefore in user units too: 10 here is ~1.8px on screen. */
.sobo-intro__mark .trace {
  fill: none;
  stroke-width: 10;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.sobo-intro__mark .trace-letter { stroke: var(--paper); }
.sobo-intro__mark .trace-heart  { stroke: var(--neon); }

/* Reduced motion never builds it (see sobo-intro.js), but belt and braces:
   if it somehow exists, it must not cover the page. */
@media (prefers-reduced-motion: reduce) {
  .sobo-intro { display: none !important; }
  html.sobo-intro-open { overflow: auto !important; }
}

/* --- Surface rhythm -------------------------------------------------------
   Charcoal canvas throughout, with two raised --ink-lift panels so the page
   has some structure rather than being one flat field. Hairlines, no shadows.
   -------------------------------------------------------------------------- */

/* "Why we're doing this" and the terms both read as asides to the main pitch,
   so they get the raised treatment; the pitch sections stay on the canvas. */
.sobo-why,
.sobo-terms {
  background: var(--ink-lift);
  border-block: var(--hairline);
}

/* The stage panels sat on a purple field that only worked against a plum body.
   On charcoal they need their own edge to separate. */
.sobo-stage {
  border: var(--hairline);
  border-radius: var(--r-flat);
}

/* Card fills were tuned against plum; on charcoal they want a touch more lift
   to stay visible without becoming grey boxes. */
.sobo-card { background: rgba(255, 255, 255, .045); }
