@import url("styles.css");

@font-face {
  font-family: "Gambarino";
  src: url("Gambarino_Complete/Fonts/WEB/fonts/Gambarino-Regular.woff2") format("woff2"),
    url("Gambarino_Complete/Fonts/WEB/fonts/Gambarino-Regular.woff") format("woff");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* ============================================================
   LATERAL WORKSHOP — design C ("coast" hero)
   Development controls in main-coast.js override these tokens.
   ============================================================ */

:root {
  --pine: #364955; /* castle shadow / blue-slate cypress */
  --pine-deep: #2a3135;
  --brick: #b96343; /* terracotta masonry accent */
  /* Photograph grade: mutes the postcard-saturated photo so it
     sits on the page like a print instead of a paste-over. The
     "Photograph grade" sliders drive these; keep defaults in sync
     with the control panel values. */
  --photo-saturation: 0.94;
  --photo-contrast: 0.98;
  --photo-warmth: 0;
  --photo-brightness: 1;
  --hero-image-opacity: 0.93;
  --photo-grade: saturate(var(--photo-saturation)) contrast(var(--photo-contrast))
    sepia(var(--photo-warmth)) brightness(var(--photo-brightness));
  --light-pine: #d8d0c8; /* misted castle stone */
  --header-bg: rgba(246, 232, 220, 0.72);
  --hero-wash-rgb: 246, 232, 220;
  --partner-bg: rgba(246, 232, 220, 0.8);
  --switch-bg: rgba(246, 232, 220, 0.84);
  --switch-shadow: rgba(42, 49, 53, 0.2);
  --font-title: "Source Serif 4", Georgia, serif;
  --font-hero-title: var(--font-title);
  --font-hero-support: var(--font-body);
  --hero-title-weight: 600;
  --font-display: var(--font-title);
  --font-body: "Inter", Arial, sans-serif;
  --title-duration: 700ms;
  --image-duration: 3500ms;
  --text-duration: 700ms;
  --title-min: 3.26rem;
  --title-fluid-width: 5.1vw;
  --title-fluid-height: 7.65svh;
  --title-max: 10.4rem;
  --title-cap-width: 8.5vw;
  --title-cap-offset: 2.98rem;
  --hero-subtitle-min: 1.26rem;
  --hero-subtitle-fluid: 2.1vw;
  --hero-subtitle-max: 1.56rem;
  --hero-meta-min: 1.26rem;
  --hero-meta-fluid: 2.1vw;
  --hero-meta-max: 1.56rem;
  --hero-apply-min: 2rem;
  --hero-apply-fluid: 3.75vw;
  --hero-apply-max: 3rem;
  --partner-band-height: 4.75rem;

  /* 8pt spacing scale — every margin/padding in the post-hero content
     resolves to one of these, so nothing lands off-grid. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-8: 48px;
  --space-10: 64px;
  --space-12: 96px;
  --space-16: 128px;

  /* Type scale for the post-hero content. The hero keeps its own
     display sizing above. */
  --fs-lead: 20px; /* intro paragraphs (About, Fit lead-in) */
  --fs-body: 18px; /* standard body copy and lists */
  --fs-meta: 14px; /* roles, captions, eyebrows */
  --fs-h3: 20px; /* card / sub-headings */
  --fs-h2: clamp(36px, 5vw, 48px); /* section headings */

  /* The page runs on one vertical spine: --grid is the outer column
     shared by the header, every section, and the footer, so all three
     begin at the same x at every viewport width. --measure is the
     reading width, applied to the copy itself and never by recentring
     its container — that is what keeps a comfortable line length
     without knocking prose out of alignment with everything above and
     below it. --gutter matches the header's existing inline padding so
     the spine holds once the viewport drops below the grid. */
  --grid: 1180px;
  --measure: 48rem;
  --gutter: clamp(1.2rem, 3.5vw, 2.6rem);
}

:root[data-visual-theme="blue-mist"],
:root[data-visual-theme="berkeley"] {
  --pine: #29496f;
  --pine-deep: #1b3150;
  --brick: #b4675a;
  --apply-accent: #94483d;
  --offwhite: #f7f4ef;
  --black: #24354a;
  --light-pine: #d7e5f2;
  --light-grey: #eaf1f7;
  --grey: #5f7086;
  --hairline: rgba(41, 73, 111, 0.22);
  --header-bg: rgba(241, 246, 251, 0.74);
  --hero-wash-rgb: 247, 244, 239;
  --partner-bg: rgba(238, 245, 251, 0.82);
  --switch-bg: rgba(240, 246, 251, 0.88);
  --switch-shadow: rgba(27, 49, 80, 0.2);
}

body {
  background: var(--offwhite);
}

img {
  outline: 1px solid rgba(0, 0, 0, 0.1);
  outline-offset: -1px;
}

.header-wordmark,
.section-heading {
  color: var(--pine);
}

.section-heading {
  margin-bottom: var(--space-8);
  font-size: var(--fs-h2);
  line-height: 1.1;
  text-align: left;
}

/* ---------- rhythm & content tracks -------------------------
   Every .band.section shares one warm surface; separation comes
   from vertical rhythm, not color. Each section carries equal top
   and bottom padding, and its content starts on the shared spine. */
.about,
.program,
.fit,
.speakers,
.testimonials,
.faq {
  background: var(--light-grey);
}

/* The spine. Padding, rather than a centered inner box, puts the
   header, every section, and the footer on the same outer grid — so
   they keep a common left edge at every width instead of only where
   a centered grid happens to coincide with the header's gutter. The
   max() collapses to the plain gutter once the viewport is narrower
   than the grid. Backgrounds stay full-bleed. */
.site-header,
.band.section,
.site-footer {
  padding-inline: max(var(--gutter), (100% - var(--grid)) / 2);
}

.band.section {
  padding-block: clamp(56px, 7vw, 80px);
}

/* Give the intro room to emerge from the hero, then keep its transition
   into Program tighter by letting Program own that shared gap. */
.about {
  padding-top: clamp(112px, 14vw, 160px);
  padding-bottom: 0;
}

/* The section wrappers no longer carry a width of their own: the
   spine above already places and bounds them. */
.about .section-inner,
.program .section-inner,
.speakers .section-inner,
.testimonials .section-inner,
.fit .section-inner--narrow,
.faq .section-inner--narrow {
  max-width: none;
}

/* Measure belongs to the copy, not the container. Prose and lists get
   a comfortable line length; the timeline's two columns and the
   speakers row use the full grid. All of them start on the spine. */
.about-copy,
.fit-intro,
.fit-list,
.faq-list,
.faq-outro {
  max-width: var(--measure);
  margin-inline: 0;
}

.program .timeline {
  max-width: none;
  margin-inline: 0;
}

/* ---------- content typography & spacing -------------------- */
.about-copy {
  font-size: var(--fs-lead);
  line-height: 1.5;
}

.about-copy p {
  margin-bottom: var(--space-5);
}

.about-copy p:last-child {
  margin-bottom: 0;
}

.fit-intro {
  margin-bottom: var(--space-6);
  font-family: var(--font-body);
  font-size: var(--fs-lead);
  font-weight: 500;
  line-height: 1.5;
}

.fit-list {
  gap: var(--space-5);
}

.fit-list li {
  font-size: var(--fs-body);
  line-height: 1.6;
}

.faq-item p {
  font-size: var(--fs-body);
  line-height: 1.6;
}

.faq-outro {
  margin-top: var(--space-8);
  font-size: var(--fs-body);
}

/* Speakers: the header and the grid both center in the wide track,
   and each card's name / role / org read as one tight group. */
.speakers-header {
  margin-bottom: var(--space-8);
}

.speaker-name {
  margin: var(--space-3) 0 var(--space-1);
  font-size: var(--fs-h3);
  line-height: 1.25;
}

.speaker-organization {
  margin-top: var(--space-1);
}

.speaker-organization a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.16em;
  transition: color 160ms ease, text-decoration-color 160ms ease;
}

.speaker-organization a:hover,
.speaker-organization a:focus-visible {
  color: var(--pine);
  text-decoration-color: currentColor;
}

/* Program stage headings share the h3 step of the scale. */
.stage-name {
  margin-bottom: var(--space-3);
  font-size: var(--fs-h3);
  line-height: 1.25;
}

/* Six compact profiles use the full desktop track. The mobile grid
   (2 columns, defined in styles.css) stays as-is below 761px. */
@media (min-width: 761px) {
  .speaker-grid {
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  }

  .speaker {
    max-width: 180px;
  }

  .speaker-photo-wrap {
    width: min(100%, 154px);
  }
}

@media (min-width: 1100px) {
  .speaker-grid {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }
}

/* Speakers hover: the photo "zoom" reads as a template default, so
   replace it with the restrained, editorial affordance — no scaling.
   The name underlines like the text link it is, with a whisper of
   feedback on the portrait, both keyed off the photo link. */
.speaker-photo-link {
  transition: opacity 160ms ease;
}

.speaker-photo-link:hover,
.speaker-photo-link:focus-visible {
  scale: 1;
  opacity: 0.9;
}

.speaker-photo-link:active {
  scale: 1;
}

.speaker:has(.speaker-photo-link:hover) .speaker-name,
.speaker:has(.speaker-photo-link:focus-visible) .speaker-name {
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--pine) 45%, transparent);
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

/* ---------- testimonials ------------------------------------
   The section sits on the same surface as its neighbours, so the
   cards drop the tinted panel the base sheet gives them and are
   held by a hairline rule instead — two quotes side by side read
   as a spread, not as widgets. The quotes are set at the lead
   size and in the display serif: this is the one place on the
   page where someone else is speaking. */
.testimonial-grid {
  gap: var(--space-8) var(--space-10);
}

.testimonial {
  padding: var(--space-5) 0 0;
  border-top: 1px solid color-mix(in srgb, var(--brick) 55%, transparent);
  background: none;
  max-width: var(--measure);
}

.testimonial blockquote {
  margin-bottom: var(--space-5);
  font-family: var(--font-display);
  font-size: var(--fs-lead);
  line-height: 1.5;
  color: var(--pine);
  text-wrap: pretty;
}

.testimonial figcaption {
  gap: var(--space-4);
}

/* The global img outline would box a circular crop, so the ring
   here is drawn by the border instead. */
.testimonial-photo {
  width: 60px;
  height: 60px;
  border: 1px solid color-mix(in srgb, var(--pine) 14%, transparent);
  background: color-mix(in srgb, var(--pine) 6%, transparent);
}

.testimonial-photo img {
  outline: none;
  filter: var(--photo-grade);
}

.testimonial-name {
  font-size: var(--fs-body);
  line-height: 1.3;
}

.testimonial-role {
  font-family: var(--font-body);
  font-size: var(--fs-meta);
  line-height: 1.4;
}

/* The wordmark reads at the same size as the nav links (0.95rem) so
   nothing in the header sits larger than the rest of it. */
.header-wordmark {
  font-size: 0.95rem;
  font-weight: 600;
}

.header-wordmark,
.site-nav a {
  position: relative;
}

.header-wordmark::after,
.site-nav a::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: max(100%, 40px);
  height: 40px;
  transform: translate(-50%, -50%);
}

@media (pointer: coarse) {
  .header-wordmark::after,
  .site-nav a::after {
    width: max(100%, 44px);
    height: 44px;
  }
}

/* ---------- geometric bridge hero ---------------------------
   One portrait master fills every viewport so resizing never swaps artwork.
   JavaScript moves its focal point gradually as the aspect ratio changes,
   preserving the favored portrait crop while revealing the bridge on widescreen. */
.hero.hero--coast {
  position: relative;
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr);
  height: 100svh;
  min-height: 0;
  padding:
    clamp(1.8rem, 6vh, 4.6rem)
    clamp(1.6rem, 5.2vw, 5.6rem)
    calc(clamp(3.25rem, 8svh, 5.75rem) + var(--partner-band-height))
    clamp(1.2rem, 3vw, 2.4rem);
  overflow: hidden;
  isolation: isolate;
  background:
    radial-gradient(circle at 50% 18%, rgba(255, 255, 255, 0.48), transparent 38%),
    var(--offwhite);
}

.theme-switcher {
  position: absolute;
  top: clamp(1.15rem, 3vw, 2rem);
  left: clamp(1.15rem, 3vw, 2.4rem);
  z-index: 7;
  display: none;
  align-items: stretch;
  gap: 0.2rem;
  padding: 0.25rem;
  border-radius: 999px;
  background: var(--switch-bg);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.62) inset,
    0 7px 24px var(--switch-shadow);
  -webkit-backdrop-filter: blur(12px) saturate(1.08);
  backdrop-filter: blur(12px) saturate(1.08);
  transition-property: background-color, box-shadow;
  transition-duration: 200ms;
  transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

.theme-preview-enabled .theme-switcher {
  display: inline-flex;
}

.theme-switcher[hidden] {
  display: none;
}

.theme-option {
  display: inline-flex;
  min-height: 44px;
  align-items: center;
  gap: 0.4rem;
  padding: 0.55rem 0.72rem;
  border: 0;
  border-radius: 999px;
  color: var(--pine);
  background: transparent;
  font: 600 0.72rem/1 var(--font-body);
  letter-spacing: 0.025em;
  cursor: pointer;
  transition-property: color, background-color, box-shadow, scale;
  transition-duration: 180ms;
  transition-timing-function: cubic-bezier(0.2, 0, 0, 1);
}

.theme-option:hover {
  background: rgba(255, 255, 255, 0.42);
}

.theme-option[aria-pressed="true"] {
  color: var(--offwhite);
  background: var(--pine);
  box-shadow: 0 2px 8px rgba(27, 49, 80, 0.18);
}

.theme-option:active {
  scale: 0.96;
}

.theme-option:focus-visible {
  outline: 2px solid var(--pine);
  outline-offset: 2px;
}

.theme-option-swatch {
  width: 0.72rem;
  height: 0.72rem;
  flex: 0 0 auto;
  border-radius: 50%;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
}

.theme-option-swatch--warm {
  background: #b96343;
}

.theme-option-swatch--mist {
  background: #9fc5e7;
}

.theme-option-swatch--berkeley {
  background: linear-gradient(135deg, #d8e3f3 0 48%, #c7a86f 52% 100%);
}

/* A directional paper wash protects the right-aligned copy while keeping the
   terracotta bridge and blue-slate foreground visible. */
.hero.hero--coast::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(
    90deg,
    transparent 30%,
    rgba(var(--hero-wash-rgb), 0.05) 56%,
    rgba(var(--hero-wash-rgb), 0.12) 79%,
    rgba(var(--hero-wash-rgb), 0.42) 84%,
    rgba(var(--hero-wash-rgb), 0.76) 100%
  );
  pointer-events: none;
}

/* The image dissolves into the next section's blue-gray surface. A long,
   eased wash avoids the hard top edge produced by a rectangular blur layer. */
.hero.hero--coast::before {
  content: "";
  position: absolute;
  inset: auto 0 0;
  z-index: 2;
  height: clamp(11rem, 30svh, 18rem);
  background: linear-gradient(
    180deg,
    transparent 0%,
    color-mix(in srgb, var(--light-grey) 2%, transparent) 15%,
    color-mix(in srgb, var(--light-grey) 6%, transparent) 30%,
    color-mix(in srgb, var(--light-grey) 14%, transparent) 45%,
    color-mix(in srgb, var(--light-grey) 28%, transparent) 60%,
    color-mix(in srgb, var(--light-grey) 48%, transparent) 74%,
    color-mix(in srgb, var(--light-grey) 70%, transparent) 86%,
    color-mix(in srgb, var(--light-grey) 88%, transparent) 94%,
    var(--light-grey) 100%
  );
  pointer-events: none;
}

.coast-media {
  position: absolute;
  inset: auto 0 0;
  z-index: 0;
  width: 100%;
  height: 100%; /* full-bleed: fill the hero so there's never a gap above the photo on windows taller than 16:9 */
  margin: 0;
  overflow: hidden;
  background: var(--offwhite);
  /* The grade lives on the figure so the canvas effects and the
     plain photograph render through the same mute. */
  filter: var(--photo-grade);
  transition: opacity 180ms cubic-bezier(0.2, 0, 0, 1);
}

.hero--coast.is-theme-switching .coast-media {
  opacity: 0.18 !important;
  transition: opacity 180ms cubic-bezier(0.2, 0, 0, 1) !important;
}

.coast-media img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--hero-focal-x, center) var(--hero-focal-y, 100%);
  -webkit-user-drag: none;
  user-select: none;
}

.coast-ink-canvas {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: none;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.hero--coast .hero-title {
  position: relative;
  inset: auto;
  grid-row: 1;
  justify-self: end;
  z-index: 2;
  margin: 0;
  text-align: right;
  font-family: var(--font-hero-title);
  font-weight: var(--hero-title-weight);
  color: var(--pine);
  font-size: calc(
    clamp(
      var(--title-min),
      calc(var(--title-fluid-width) + var(--title-fluid-height)),
      min(var(--title-max), calc(var(--title-cap-width) + var(--title-cap-offset)))
    ) + 6.8pt
  );
  line-height: 0.84;
  letter-spacing: 0.015em;
}

.hero--coast .hero-title span {
  margin-top: 0.16em;
  font-size: calc(0.59em + 1pt);
  font-weight: var(--hero-title-weight);
}

.hero--coast .hero-info {
  position: relative;
  inset: auto;
  grid-row: 2;
  display: grid;
  gap: clamp(0.65rem, 1.25vh, 0.9rem);
  justify-self: end;
  z-index: 2;
  width: min(clamp(29rem, 42vw, 33rem), 100%);
  margin: clamp(2rem, 4.5svh, 3.5rem) 0 0;
  text-align: right;
  font-family: var(--font-hero-support);
}

/* The info block owns the spacing so wrapped subtitle lines do not
   create a different gap than the single-line location and Apply. */
.hero--coast .hero-subtitle {
  margin: 0;
  font-size: calc(clamp(var(--hero-subtitle-min), var(--hero-subtitle-fluid), var(--hero-subtitle-max)) + 1pt);
  font-weight: 500;
  color: var(--pine);
  /* Even the line lengths so it never breaks to a long line above a
     stubby one (e.g. the mobile "...moving / into AI safety" split). */
  text-wrap: balance;
  text-shadow: 0 1px 1px rgba(var(--hero-wash-rgb), 0.84), 0 0 12px rgba(var(--hero-wash-rgb), 0.58);
}

.hero--coast .hero-meta {
  margin: 0;
  font-size: clamp(1rem, 1.35vw, 1.18rem);
  font-weight: 500;
  letter-spacing: 0.005em;
  color: var(--pine);
  text-shadow: 0 1px 1px rgba(var(--hero-wash-rgb), 0.84), 0 0 12px rgba(var(--hero-wash-rgb), 0.58);
}

.hero--coast .hero-meta .dot {
  display: inline-block;
  margin-inline: 0.16em;
  color: var(--pine);
  font-size: 0.72em;
  transform: translateY(-0.08em);
}

.hero--coast .hero-apply {
  font-size: calc(clamp(var(--hero-apply-min), var(--hero-apply-fluid), var(--hero-apply-max)) + 2pt);
  color: var(--pine);
}

.hero--coast .hero-apply .apply-link::before {
  content: "\00BB\00A0";
  display: inline-block;
  text-decoration: none;
}

.hero-partners {
  position: absolute;
  right: clamp(1.6rem, 5.2vw, 5.6rem);
  bottom: clamp(1.25rem, 3.5svh, 2.4rem);
  z-index: 2;
  display: grid;
  justify-items: end;
  gap: 0.45rem;
}

.hero-partners-heading {
  margin: 0;
  color: var(--pine);
  font-family: var(--font-body);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  line-height: 1;
  text-transform: uppercase;
}

.hero-partners .logo-row {
  flex-wrap: nowrap;
  justify-content: flex-end;
  gap: 0.55rem;
  margin: 0;
}

.hero-partners .logo-item {
  width: clamp(112px, 11vw, 136px);
  height: 36px;
  padding: 0;
  border-radius: 0;
  background: transparent;
  opacity: 0.88;
  transition-property: opacity, scale;
  transition-duration: 200ms;
  transition-timing-function: ease-out;
}

.hero-partners .logo-item img {
  outline: 0;
}

.hero-partners .logo-item img[src$="bluedot_dark.svg"] {
  transform: scale(1.4);
  transform-origin: right center;
}

.hero-partners .logo-item img[src$="kairos.png"] {
  width: 100%;
  height: 100%;
  object-position: right center;
  transform: translateX(0.2rem);
}

.hero-partners a.logo-item:hover {
  background: transparent;
  opacity: 1;
  transform: none;
}

.hero-partners a.logo-item:active {
  scale: 0.96;
}

/* ---------- entrance states --------------------------------- */
.coast-seq {
  opacity: 0;
  transform: translateY(12px);
  transition-property: opacity, transform;
  transition-duration: var(--text-duration);
  transition-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
}

/* The display title dwarfs the body copy, so the shared 12px rise
   barely registers on it and the entrance reads stiff. Give the title
   a longer travel (and match the body's timing via --title-duration,
   now 700ms) so it drifts up into place like the rest of the hero. */
#seqHero.coast-seq {
  transform: translateY(30px);
  transition-duration: var(--title-duration);
}

.coast-seq.is-visible {
  opacity: 1;
  transform: none;
}

#seqHero.coast-seq.is-visible {
  transform: none;
}

.hero--coast.is-resetting .coast-seq {
  transition: none !important;
}

/* Ink fade is simulated on the canvas in main-coast.js: the wash
   blooms out of the ink-tree nodes and floods along its edges.
   While it runs, the plain photograph stays hidden underneath. */
.hero--coast.effect-ink .coast-media {
  opacity: var(--hero-image-opacity);
  transform: none;
  transition: none;
}

.hero--coast.effect-ink .coast-media.ink-hold .coast-image--base {
  opacity: 0;
}

/* The blur/scale animate on the photograph itself so the figure's
   filter stays free for the permanent grade. */
.hero--coast.effect-blur .coast-media {
  opacity: 0;
  transform: none;
  transition: opacity var(--image-duration) ease;
  will-change: opacity;
}

.hero--coast.effect-blur .coast-image--base {
  filter: blur(30px) saturate(0.72);
  transform: scale(1.045);
  transition:
    filter var(--image-duration) cubic-bezier(0.22, 1, 0.36, 1),
    transform var(--image-duration) cubic-bezier(0.22, 1, 0.36, 1);
  will-change: filter, transform;
}

.hero--coast.effect-blur .coast-media.is-visible {
  opacity: var(--hero-image-opacity);
}

.hero--coast.effect-blur .coast-media.is-visible .coast-image--base {
  filter: blur(0) saturate(1);
  transform: none;
}

/* Bloom down: the image starts overexposed and slightly soft —
   condensed out of the page's own light — and settles to true
   exposure. The figure itself never animates; the grade lives on
   the photograph. */
.hero--coast.effect-bloom .coast-media {
  opacity: var(--hero-image-opacity);
  transform: none;
  transition: none;
}

.hero--coast.effect-bloom .coast-image--base {
  opacity: 0;
  filter: brightness(var(--bloom-exposure, 1.2)) blur(var(--bloom-blur, 3px));
  transition:
    opacity calc(var(--image-duration) * 0.3) ease-out,
    filter var(--image-duration) cubic-bezier(0.33, 1, 0.68, 1);
  will-change: opacity, filter;
}

.hero--coast.effect-bloom .coast-media.is-visible .coast-image--base {
  opacity: 1;
  filter: brightness(1) blur(0);
}

/* Dawn ramp: the image is present from the first frame but
   underexposed, desaturated, and under a blue-hour tint (the
   ::after overlay); everything ramps to final grade together. */
.hero--coast.effect-dawn .coast-media {
  opacity: var(--hero-image-opacity);
  transform: none;
  transition: none;
}

.hero--coast.effect-dawn .coast-image--base {
  filter: brightness(var(--dawn-exposure, 0.25)) saturate(var(--dawn-saturation, 0.2));
  transition: filter var(--image-duration) cubic-bezier(0.45, 0.05, 0.35, 1);
  will-change: filter;
}

.hero--coast.effect-dawn .coast-media.is-visible .coast-image--base {
  filter: brightness(1) saturate(1);
}

.hero--coast.effect-dawn .coast-media::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: #3a5170;
  opacity: var(--dawn-tint, 0.35);
  transition: opacity var(--image-duration) cubic-bezier(0.45, 0.05, 0.35, 1);
  pointer-events: none;
}

.hero--coast.effect-dawn .coast-media.is-visible::after {
  opacity: 0;
}

/* Illuminate is simulated on the canvas in main-coast.js: pixels
   reveal in order of their own luminance. Reuses the ink-hold
   mechanics to keep the plain photograph hidden while it runs. */
.hero--coast.effect-lumen .coast-media {
  opacity: var(--hero-image-opacity);
  transform: none;
  transition: none;
}

.hero--coast.effect-lumen .coast-media.ink-hold .coast-image--base {
  opacity: 0;
}

/* Replay reset must also silence the transitions that live on the
   photograph and the dawn overlay, not just on .coast-seq. */
.hero--coast.is-resetting .coast-image--base,
.hero--coast.is-resetting .coast-media::after {
  transition: none !important;
}

@media (prefers-reduced-motion: reduce) {
  .coast-seq,
  .hero--coast .coast-media {
    opacity: var(--hero-image-opacity) !important;
    filter: none !important;
    transform: none !important;
    clip-path: none !important;
    transition: none !important;
  }

  /* The grade is a static treatment, not motion — keep it. */
  .hero--coast .coast-media {
    filter: var(--photo-grade) !important;
  }

  .hero--coast .coast-image--base {
    display: block !important;
    opacity: 1 !important;
    filter: none !important;
    transform: none !important;
  }

  .hero--coast .coast-media::after {
    opacity: 0 !important;
    transition: none !important;
  }

  .hero--coast .coast-ink-canvas {
    display: none !important;
  }
}

/* ---------- ink tree overlay --------------------------------- */
.ink-tree-overlay {
  position: absolute;
  inset: 0;
  z-index: 6;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.ink-tree-overlay.is-hidden {
  display: none;
}

body.tree-tooling .ink-tree-overlay {
  pointer-events: auto;
  cursor: crosshair;
  touch-action: none;
}

body.tree-tooling.tree-tool-move .ink-tree-overlay {
  cursor: grab;
}

/* ---------- development controls ----------------------------
   The on-page control panels and the tree-editing overlay (the
   red node dots) are dev-only — they show only with ?dev=1
   (body.dev). Using body:not(.dev) leaves the rules inert in dev
   mode, so the overlay's own show/hide logic still applies there.
   The canvas ink entrance is NOT gated: it runs for everyone. */
body:not(.dev) .coast-controls,
body:not(.dev) .ink-tree-overlay {
  display: none !important;
}

.coast-controls {
  position: fixed;
  left: 14px;
  bottom: 14px;
  z-index: 300;
  width: min(330px, calc(100vw - 28px));
  color: #f6f3ec;
  font: 12px/1.35 "Inter", ui-sans-serif, system-ui, sans-serif;
}

.coast-controls--right {
  left: auto;
  right: 14px;
}

.coast-controls details {
  max-height: calc(100svh - 28px);
  overflow: auto;
  background: rgba(17, 37, 33, 0.94);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 12px;
  box-shadow: 0 16px 50px rgba(10, 25, 22, 0.24);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}

.coast-controls summary {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 10px 12px;
  cursor: pointer;
  list-style: none;
  background: rgba(17, 37, 33, 0.96);
  border-radius: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.coast-controls summary::-webkit-details-marker {
  display: none;
}

.coast-controls summary::after {
  content: "+";
  float: right;
  color: var(--brick);
  font-size: 16px;
  line-height: 1;
}

.coast-controls details[open] summary::after {
  content: "\2212";
}

.controls-body {
  padding: 0 12px 12px;
}

.coast-controls [hidden] {
  display: none !important;
}

.coast-controls fieldset {
  min-width: 0;
  margin: 8px 0 12px;
  padding: 9px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 8px;
}

.coast-controls legend {
  padding: 0 5px;
  color: rgba(255, 255, 255, 0.66);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.coast-controls label {
  display: block;
  margin: 0 0 9px;
}

.coast-controls label:last-child {
  margin-bottom: 0;
}

.control-help,
.param-help {
  color: rgba(255, 255, 255, 0.58);
  font-size: 10.5px;
  font-weight: 400;
  line-height: 1.42;
}

.control-help {
  grid-column: 1 / -1;
  margin: 0 0 10px;
}

.param-help {
  display: block;
  clear: both;
  margin-top: 2px;
}

.coast-controls output {
  float: right;
  color: rgba(255, 255, 255, 0.62);
  font-variant-numeric: tabular-nums;
}

.coast-controls select,
.coast-controls input[type="range"] {
  width: 100%;
  margin-top: 4px;
}

.coast-controls select {
  padding: 5px 7px;
  color: #f6f3ec;
  background: rgba(255, 255, 255, 0.09);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 6px;
  font: inherit;
}

.coast-controls input {
  accent-color: var(--brick);
}

.segmented {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}

.segmented--effects {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.segmented--effects label {
  padding-inline: 3px;
  text-align: center;
}

.segmented label {
  margin: 0;
  padding: 6px;
  background: rgba(255, 255, 255, 0.07);
  border-radius: 6px;
  cursor: pointer;
}

.color-controls {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.color-controls legend {
  grid-column: 1 / -1;
}

.color-controls input[type="color"] {
  display: block;
  width: 100%;
  height: 30px;
  margin-top: 4px;
  padding: 2px;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 6px;
  cursor: pointer;
}

.tool-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px;
  margin-bottom: 8px;
}

.tool-grid--2 {
  grid-template-columns: 1fr 1fr;
  margin: 8px 0 0;
}

.tool-button {
  padding: 6px 4px;
  color: #f6f3ec;
  background: rgba(255, 255, 255, 0.09);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 6px;
  font: 600 11px/1.2 "Inter", ui-sans-serif, system-ui, sans-serif;
  cursor: pointer;
}

.tool-button:hover {
  background: rgba(255, 255, 255, 0.16);
}

.tool-button.is-active {
  background: var(--brick);
  border-color: var(--brick);
}

.tool-button--wide {
  display: block;
  width: 100%;
}

.tool-hint {
  min-height: 2.6em;
  margin: 0 0 8px;
}

.check-label {
  display: flex;
  gap: 7px;
  align-items: center;
}

.replay-button {
  width: 100%;
  padding: 8px 10px;
  color: #fff;
  background: var(--brick);
  border: 0;
  border-radius: 7px;
  font: 700 12px/1.2 "Inter", ui-sans-serif, system-ui, sans-serif;
  cursor: pointer;
}

.replay-button:hover {
  filter: brightness(1.08);
}

.replay-button--compact {
  display: none;
  width: auto;
  margin-top: 8px;
  margin-left: auto;
  box-shadow: 0 8px 28px rgba(10, 25, 22, 0.2);
}

.coast-controls details:not([open]) + .replay-button--compact {
  display: block;
}

/* Local-only background picker, created by main-coast.js when
   ?backgroundlab=1 is present on localhost. */
.background-lab {
  position: fixed;
  right: 12px;
  bottom: 12px;
  z-index: 9000;
  width: min(220px, calc(100vw - 24px));
  max-height: min(360px, calc(100vh - 24px));
  padding: 0.55rem;
  border: 1px solid rgba(30, 37, 39, 0.18);
  border-radius: 7px;
  color: var(--pine);
  background: rgba(246, 232, 220, 0.96);
  box-shadow: 0 8px 24px rgba(23, 30, 32, 0.18);
  font: 500 0.62rem/1.2 "Inter", Arial, sans-serif;
  backdrop-filter: blur(10px);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.background-lab h2 {
  margin: 0 0 0.4rem;
  font: inherit;
  font-size: 0.68rem;
  font-weight: 600;
}

.background-lab-options {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.3rem;
}

.background-lab-options button {
  min-width: 0;
  padding: 0;
  border: 2px solid transparent;
  border-radius: 5px;
  color: var(--pine);
  background: var(--offwhite);
  font: inherit;
  text-align: left;
  cursor: pointer;
  overflow: hidden;
}

.background-lab-options button:hover,
.background-lab-options button.is-active {
  border-color: var(--brick);
}

.background-lab-options img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  object-position: center 56%;
}

.background-lab-options span {
  display: block;
  padding: 0.22rem 0.28rem 0.26rem;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}

/* ---------- scroll polish ------------------------------------ */

/* A touch more breathing room in the header. */
.site-header {
  padding-top: 1.15rem;
  padding-bottom: 1.15rem;
}

/* Scrollspy: the section under the reader gets a quiet underline.
   Underlines don't affect layout, so nothing in the header moves. */
.site-nav a.is-current {
  color: var(--pine);
  text-decoration: underline;
  text-underline-offset: 5px;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, var(--pine) 55%, transparent);
}

/* Anchor jumps land with the fixed header accounted for, so the top
   of the target section sits flush against the header's bottom edge
   with no gap. --header-h is the header's measured height, kept in
   sync by main-coast.js; 5rem is a safe fallback before it runs. */
main section[id] {
  scroll-margin-top: var(--header-h, 5rem);
}

/* Fade-up reveals: elements rise 14px and fade in once as they
   enter (main-coast.js tags targets and staggers siblings). Once
   revealed they stay at full opacity — text never fades back out on
   scroll, so the hero and every section behave the same way. */
.scroll-reveal {
  opacity: 0;
  transform: translateY(8px);
  transition:
    opacity 0.6s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}

.scroll-reveal.is-revealed {
  opacity: 1;
  transform: none;
}

/* Reduced motion: never withhold content behind a transition. Every
   reveal is shown outright and all animation is silenced. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }

  .scroll-reveal,
  .coast-seq {
    opacity: 1 !important;
    transform: none !important;
  }
}

@media (max-width: 760px) {
  :root {
    --partner-band-height: 4.5rem;
  }

  /* Keep the mobile hierarchy editorial without carrying the desktop
     supporting-copy scale into a much narrower measure. */
  .hero--coast .hero-title {
    line-height: 0.88;
    letter-spacing: 0.005em;
  }

  .hero--coast .hero-info {
    gap: 0.7rem;
    width: min(100%, 21rem);
    margin-top: clamp(1.5rem, 4svh, 2.25rem);
  }

  .hero--coast .hero-subtitle {
    font-size: clamp(1.05rem, 4.8vw, 1.18rem);
    line-height: 1.42;
    text-wrap: balance;
  }

  .hero--coast .hero-meta {
    font-size: clamp(0.92rem, 4vw, 1rem);
    line-height: 1.35;
    white-space: nowrap;
  }

  .hero--coast .hero-apply {
    font-size: clamp(1.75rem, 8vw, 2.1rem);
    line-height: 1.1;
  }

  .header-wordmark::after,
  .site-nav a::after {
    width: max(100%, 44px);
    height: 44px;
  }

  .hero-partners {
    right: 1rem;
    bottom: 1rem;
    gap: 0.35rem;
  }

  .hero-partners-heading {
    font-size: 0.75rem;
  }

  .hero-partners .logo-row {
    gap: 0.5rem;
  }

  .hero-partners .logo-item {
    width: clamp(94px, 27vw, 112px);
    height: 28px;
  }

  .hero.hero--coast::after {
    background: linear-gradient(
      180deg,
      rgba(var(--hero-wash-rgb), 0.52) 0%,
      rgba(var(--hero-wash-rgb), 0.14) 47%,
      rgba(var(--hero-wash-rgb), 0.48) 100%
    );
  }

  .theme-switcher {
    top: 0.9rem;
    left: 0.9rem;
  }

  .theme-preview-enabled .hero.hero--coast {
    padding-top: 5.75rem;
  }

  .theme-option {
    gap: 0.3rem;
    padding-inline: 0.56rem;
    font-size: 0.66rem;
  }

  .coast-controls {
    left: 10px;
    bottom: 10px;
    width: min(330px, calc(100vw - 20px));
  }

  .coast-controls--right {
    left: auto;
    right: 10px;
  }

  .background-lab {
    bottom: 10px;
    right: 10px;
    width: min(220px, calc(100vw - 20px));
    max-height: 46vh;
  }
}
