/* ---------- Tokens ---------- */
/* Weight range 500-700: the Figma design uses 65 Medium throughout, so
   bolder usages render the true Medium glyphs instead of synthetic bold. */
@font-face {
  font-family: "Neue Haas Grotesk Display Pro";
  src: url("assets/fonts/NHaasGroteskDSPro-65Md.woff2") format("woff2");
  font-weight: 500 700;
  font-style: normal;
  font-display: swap;
}

:root {
  --yellow: #FFD618;
  --orange: #F59A00;
  --ink: #0A0A0A;
  --black: #000000;
  --gray: #9A9A9A;
  --pink: #FF00B3;
  --white: #FFFFFF;

  /* Figma spec: Neue Haas Grotesk Display Pro (licensed; needs webfont
     files or an Adobe Fonts kit to render for visitors). The Adobe
     Fonts family name is "neue-haas-grotesk-display". */
  --font-display: "Neue Haas Grotesk Display Pro", "neue-haas-grotesk-display", "Helvetica Neue", Helvetica, Arial, sans-serif;

  --container-max: 2000px; /* side margins only appear beyond 2000px */
  --container-pad: clamp(1.25rem, 4vw, 3rem);

  --gap-xl: clamp(4rem, 4rem + 8vw, 12rem);
  --gap-lg: clamp(3rem, 3rem + 5vw, 8.5rem);
  --gap-md: clamp(2rem, 2rem + 3vw, 5rem);

  /* The Figma type system: exactly three sizes, anchored to the two
     design frames (393px mobile / 1512px desktop) and growing linearly
     until 2000px. H1 37->70, H2 18->30, H3 12->20. */
  --h1-size: clamp(2.3125rem, 25.4px + 2.95vw, 5.275rem);
  --h1-line: 1.071;  /* 75/70 */
  --body-size: clamp(1.125rem, 13.8px + 1.07vw, 2.2rem);
  --body-line: 1.167; /* 35/30 */
  --h3-size: clamp(0.75rem, 6.5px + 0.89vw, 1.525rem);
  --h3-line: 1.25;   /* 25/20 */
  /* Form fields follow H3 but never drop below 16px (iOS zooms into
     smaller inputs) */
  --field-size: max(1rem, var(--h3-size));
}

/* ---------- Reset ---------- */
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  font-family: var(--font-display);
  color: var(--ink);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  /* Figma opentype flags LNUM + TNUM on every text style */
  font-variant-numeric: lining-nums tabular-nums;
}
img { max-width: 100%; display: block; }
ul { margin: 0; padding: 0; list-style: none; }
p { margin: 0; }
a { color: inherit; text-decoration: none; }
h1, h2, h3, h4 { margin: 0; font-weight: 700; }

.container {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-pad);
}

/* ---------- Type helpers ---------- */
.display-heading {
  font-size: var(--h1-size);
  line-height: var(--h1-line);
  letter-spacing: 0.01em;
  font-weight: 500; /* Figma H1: 65 Medium */
  color: var(--ink);
}
.display-heading--orange { color: var(--orange); }
/* Figma stacks headings and their paragraphs with generous air (~160px
   at design scale) rather than butting them together. */
.display-heading + .body-text,
.display-heading + .body-list {
  margin-top: calc(clamp(2.5rem, 6vw, 6.5rem) + 8px);
}
/* Mobile type per Figma (H1-Mobile 37/40 medium 1%, note heading
   H2-Mobile 18/21 medium 2%, checkbox fine print 7px). */
/* (H1-Mobile 37px is the token's floor -- no override needed.) */

.underline-word {
  position: relative;
  display: inline-block;
}
/* Stretch edge-to-edge under the full word (the SVG path itself spans
   its whole viewBox, so no inset is needed). */
.underline-word::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.04em;
  height: 0.11em;
  min-height: 3px;
  background: url("assets/img/squiggle.svg?v=6") no-repeat center / 100% 100%;
}
/* Each title gets its own hand-drawn line, like the design (the
   default squiggle stays on the hero's "Oktober") */
.underline-word--a::after { background-image: url("assets/img/squiggle-a.svg?v=1"); }
.underline-word--b::after { background-image: url("assets/img/squiggle-b.svg?v=1"); }
.underline-word--c::after { background-image: url("assets/img/squiggle-c.svg?v=1"); }
.underline-word--d::after { background-image: url("assets/img/squiggle-d.svg?v=1"); }

/* Figma: paragraphs sit in a narrower, inset column (1152px) than the
   headings (1509px) -- indent them on both sides. */
.body-text {
  font-size: var(--body-size);
  line-height: var(--body-line);
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--ink);
  margin-inline: clamp(1.5rem, 8vw, 8.5rem);
}
.body-text--label {
  color: var(--orange);
  font-weight: 700;
  margin-top: 0.4em;
}
.body-list {
  font-size: var(--body-size);
  line-height: var(--body-line);
  font-weight: 500;
  letter-spacing: 0.01em;
  margin-inline: clamp(1.5rem, 8vw, 8.5rem);
}
.body-list li {
  position: relative;
  padding-left: 1.1em;
}
.body-list li::before {
  content: "•";
  position: absolute;
  left: 0;
}
.body-list-columns {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem 3rem;
  margin-inline: clamp(1.5rem, 8vw, 8.5rem);
}
.body-list-columns .body-list { margin-inline: 0; }
.highlight-pink { color: var(--pink); }
/* Class annotations like "(3. und 4. Klasse)" never break apart */
.no-wrap { white-space: nowrap; }

.text-link {
  color: var(--orange);
  text-decoration: underline;
}

/* ---------- Logo (reused in hero + footer) ---------- */
/* Official artwork (mark + wordmark, baseline alignment baked in).
   The mark is 48.2 of the 56.7 viewBox height; sizing the image so
   the mark stays at 2x the wordmark size, as before. */
.logo {
  display: flex;
}
.logo-img {
  height: calc(var(--body-size) * 2 * 56.7 / 48.2);
  width: auto;
}
.site-link {
  font-size: var(--h3-size);
  font-weight: 700;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
}
.site-link-arrow {
  color: var(--ink);
  width: 0.7em;
  height: 0.7em;
  flex-shrink: 0;
}

/* ---------- Hero ---------- */
.hero {
  padding-top: clamp(1.5rem, 3vw, 2.5rem);
  padding-bottom: clamp(2rem, 5vw, 4rem);
}
.hero-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 2rem;
  flex-wrap: wrap;
}
.hero-title {
  max-width: 20ch;
  font-size: var(--h1-size);
  line-height: var(--h1-line);
  letter-spacing: 0.01em;
  font-weight: 500;
}
/* Fixed to the viewport: the site link + date badge stay visible while
   scrolling. right aligns with the container's content edge. */
.hero-top-right {
  position: fixed;
  top: clamp(0.75rem, 2vw, 2rem);
  right: max(clamp(1.25rem, 4vw, 3rem), calc((100vw - 2000px) / 2 + 48px));
  z-index: 30;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: clamp(0.5rem, 1.5vw, 1rem);
}
/* Sits in the hero flow, but always stacks above anything it overlaps
   (title, images, arrows) -- nothing may cover the badge. */
.badge-circle {
  position: relative;
  z-index: 20;
  /* Figma: 246px at the 1512 frame; same linear ramp as the rest,
     growing until 2000px */
  width: clamp(150px, 116px + 8.6vw, 288px);
  aspect-ratio: 1;
  flex-shrink: 0;
  display: block;
}
/* The <picture> only swaps the ring source (thinner stroke on
   phones); layout-wise the img acts as a direct child. */
.badge-circle picture { display: contents; }
.badge-circle-svg {
  width: 100%;
  height: 100%;
  transition: transform 0.6s ease;
}
.badge-circle:hover .badge-circle-svg,
.badge-circle:focus-visible .badge-circle-svg {
  transform: rotate(20deg);
}
.badge-circle-text {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  text-align: left;
  /* No extra gap: line spacing matches the body text (--body-line) */
  padding-left: 10%;
  /* 5.83deg, falling to the right */
  transform: rotate(5.83deg);
}
.badge-date {
  color: var(--orange);
  font-weight: 500;
  font-size: var(--body-size);
  line-height: var(--body-line);
}
.badge-cta {
  color: var(--ink);
  font-weight: 500;
  font-size: var(--body-size);
  line-height: var(--body-line);
  white-space: nowrap;
}

.hero-visual {
  position: relative;
  display: flex;
  justify-content: center;
  margin-top: clamp(1rem, 4vw, 3rem);
}
/* Desktop per Figma: the globe rides up beside the headline (its top-
   left canvas corner is empty, so nothing visually collides). The
   badge column is fixed, so hero-top is only as tall as the title.
   The hero fills the whole first viewport on large screens. */
@media (min-width: 1141px) {
  .hero {
    /* Fixed (not min-) height: the section must not grow with the
       image, or the caption/logo y-position would depend on which
       hero variant loaded. A too-tall image overflows visually. */
    height: 100vh;
    display: flex;
    flex-direction: column;
  }
  .hero-title { position: relative; z-index: 1; }
  .hero-visual {
    margin-top: clamp(-48px, -2.5vw, -16px);
    flex: 1;
    align-items: center;
    /* Fixed slot: exactly the viewport space left under the title,
       never grown by the image. The caption and logo anchor to the
       slot's bottom, so their y-position is identical for both hero
       variants; a too-tall image just overflows the slot visually. */
    min-height: 0;
  }
}
/* The PNG canvas is trimmed symmetrically around the composition, so a
   centered element means a centered globe. Figma spec: the (untrimmed)
   image is 1118.66px in a 1512px frame = 53vw / 793px max in trimmed-
   canvas terms; its -5deg rotation is baked into the export. */
.hero-globe {
  /* One linear ramp across all widths: 322px at a 326px viewport,
     growing until 2000px (863px), clamped at both ends. */
  width: clamp(322px, 32.2vw + 217px, 863px);
  height: auto;
  /* Entrance: fade in while springing up -- a damped bounce (each
     rebound smaller than the last) that feathers out to rest */
  animation: hero-pop 0.6s ease-in-out both;
}
@keyframes hero-pop {
  0%   { opacity: 0; scale: 0.6; }
  45%  { opacity: 1; scale: 1.08; }
  70%  { opacity: 1; scale: 0.965; }
  88%  { opacity: 1; scale: 1.015; }
  100% { opacity: 1; scale: 1; }
}
/* Piano collage leans slightly left. Phones: the img box gets the
   globe's exact layout height (object-fit centers the landscape
   collage inside it), so the caption and logo below keep one
   y-position no matter which variant loads -- without letting the
   piano bleed off the viewport edges. */
.hero-globe--piano {
  rotate: -6deg;
  width: min(calc(1.25 * clamp(322px, 32.2vw + 217px, 863px)), 100vw - 12px);
  height: calc(clamp(322px, 32.2vw + 217px, 863px) * 1.3139);
  object-fit: contain;
  /* Fixed 70px below the top of the equal-height box at every width:
     no vertical movement while resizing. The remaining spare height
     sits below the collage, before the caption. */
  object-position: center 70px;
}
/* Desktop: a linear ramp in viewport width (max at the 2000px
   container, falling to the mobile breakpoint), plus a viewport-
   height cap so the hero still fits the first screen on short
   windows -- without it the image pushes the caption below the fold. */
@media (min-width: 1141px) {
  .hero-globe {
    width: max(420px, min(37.6vw + 256px, 87.5vh - 217px, 1007px));
  }
  /* Desktop: the caption/logo anchor to the fixed slot (not the
     image), so the piano doesn't need the mobile equal-height box;
     ~25% over the globe matches its visual presence without running
     under the caption text. */
  .hero-globe--piano {
    width: max(475px, min(45.1vw + 307px, 113.4vh - 282px, 1209px));
    height: auto;
    /* Nudge left so the keyboard's right end clears the caption,
       and up a touch from the slot center */
    translate: -1.8% -40px;
  }
}
/* The footnote star sits above-right of the ball, as in the design;
   the caption below carries the matching asterisk. */
.hero-star {
  position: absolute;
  top: 8%;
  right: 28%;
  font-size: clamp(2rem, 2rem + 2vw, 3.5rem);
  color: var(--ink);
  font-weight: 500;
}
/* Stacked layouts: the star hugs the collage's upper right instead
   of hiding (per client, it belongs to the collage on mobile too) */
@media (max-width: 1140px) {
  .hero-star {
    top: 22%;
    right: 5%;
  }
}
/* Same bottom as .hero-caption so the logo always lines up with the
   caption text's last line. */
.hero-logo {
  position: absolute;
  left: 0;
  /* Sits low in the slot, dipping into the hero's bottom padding */
  bottom: calc(4% - 70px);
}
/* Desktop: the logo scrolls with the hero until its top reaches the
   site-link's line, then sticks there (script.js toggles the class). */
.hero-logo--stuck {
  position: fixed;
  top: clamp(0.75rem, 2vw, 2rem);
  bottom: auto;
  left: max(clamp(1.25rem, 4vw, 3rem), calc((100vw - 2000px) / 2 + 48px));
  z-index: 30;
}
/* Same H2 token as body text; box width in em preserves the Figma
   408px-at-30px caption box proportion at every viewport. */
.hero-caption {
  position: absolute;
  right: 0;
  bottom: calc(4% - 70px); /* same drop as .hero-logo */
  /* Hanging asterisk: the * is absolutely placed in the padding, so
     every text line (including the first G) aligns exactly */
  padding-left: 0.85em;
  max-width: 13.6em;
  font-size: var(--body-size);
  font-weight: 500;
  letter-spacing: 0.01em;
  line-height: 1.167;
}
.hero-caption > span[aria-hidden] {
  position: absolute;
  left: 0;
}
/* On load the caption drifts 20px down into its resting position */
@keyframes caption-settle {
  from { translate: 0 -20px; }
  to { translate: 0 0; }
}
.hero-caption {
  animation: caption-settle 1s ease-out both;
}
/* Mobile hero (per Mobile-2 Figma frame): badge overlaps the title's
   top-right; below it the column stacks globe -> caption -> logo.
   Kicks in at 1140px already: below that, the absolutely positioned
   caption starts overlapping the globe in the desktop layout. */
@media (max-width: 1140px) {
  .hero-top { position: relative; }
  /* The fixed badge column sits top-right; keep the headline out from
     underneath it by reserving its width. */
  .hero-title { position: relative; z-index: 1; padding-right: clamp(7.5rem, 36vw, 10rem); }
}
/* Phones: the Figma Mobile-2 title falls on exactly two lines
   ("Ab Oktober wählst / du deinen Mix.") and may run under the
   badge ring -- drop the reserved badge width so words never wrap
   away from the designed line fall. */
@media (max-width: 620px) {
  .hero-title { padding-right: 0; }
  /* Drop the badge below the title's two lines so the ring no longer
     crosses the headline text, and push it toward the right edge */
  .badge-circle { margin-top: 3.25rem; margin-right: -1rem; }
}
/* From 848px down the caption no longer fits beside the globe --
   stack the column (image, then caption, then logo) for both
   variants so their y-positions stay identical. */
@media (max-width: 848px) {
  /* The hero fills exactly the visible viewport on phones: collage
     at the top, lead + logo pinned to the bottom edge -- adapting
     to the device height instead of ending early on tall phones. */
  .hero {
    display: flex;
    flex-direction: column;
    min-height: 100svh;
  }
  .hero-visual {
    flex-direction: column;
    align-items: center;
    flex: 1;
    /* Collage sits a touch lower under the title on phones */
    margin-top: calc(clamp(1rem, 4vw, 3rem) + 16px);
  }
  /* Phones with short visible viewports (iPhone Safari with its
     bars: ~660px svh): shrink the collage so title + image + lead +
     logo all fit the first screen. ~360px is the non-image budget;
     the 250px floor keeps the collage recognizable. Browsers
     without svh fall back to the base ramp. */
  .hero {
    --hero-img-w: min(clamp(322px, 32.2vw + 217px, 863px),
                      max(250px, (100svh - 360px) * 0.7611));
  }
  /* The base linear ramp applies at all widths; on small phones the
     300px floor may exceed the container -- let it bleed (body clips
     horizontal overflow). */
  .hero-globe { max-width: none; width: var(--hero-img-w); }
  .hero-globe--piano {
    width: min(calc(1.25 * var(--hero-img-w)), 100vw - 12px);
    height: calc(var(--hero-img-w) * 1.3139);
  }
  .hero-caption {
    position: relative;
    order: 1;
    /* auto margin soaks up the leftover viewport height, pushing
       lead + logo to the bottom edge; the padding keeps a minimum
       gap to the collage on short devices */
    margin-top: auto;
    padding-top: 1.75rem;
    max-width: none;
    align-self: flex-start;
    /* H2-Mobile: the body token */
    letter-spacing: 0.02em;
  }
  .hero-logo { position: static; order: 2; margin-top: 2.25rem; align-self: flex-start; }
}
/* Narrow screens show only the arrow icon, no "unterstrass.edu" label. */
@media (max-width: 620px) {
  .site-link-text { display: none; }
  .site-link-arrow { width: 1rem; height: 1rem; }
}

/* ---------- Section rhythm ---------- */
.section-block {
  display: flex;
  flex-direction: column;
  gap: var(--gap-lg);
  padding-block: clamp(4.5rem, 9vw, 10rem);
}
.section-block--wide-gap { gap: var(--gap-xl); }
/* Tighter section padding below the photo strip */
.section-block:has(.photo-strip) {
  padding-bottom: clamp(2.5rem, 5vw, 5.5rem);
}
.subsection {
  display: flex;
  flex-direction: column;
  gap: clamp(1.25rem, 2vw, 2rem);
}
.subsection > .body-text + .body-list,
.subsection > .body-text--label + .body-list {
  margin-top: -0.75rem;
}

/* ---------- Sticky notes (yellow paper) ---------- */
/* .sticky-note is the unclipped positioning wrapper (holds the tape);
   .note-paper is the clipped, rotated paper shape. Tape must live outside
   the clip-path or its overhang gets cut off. */
.sticky-note {
  position: relative;
}
.note-paper {
  position: relative;
  z-index: 1;
  background: var(--yellow);
  padding: clamp(1.75rem, 4vw, 3.75rem) clamp(1.75rem, 4vw, 4.5rem);
}

/* Rotation lives on the wrapper (not .note-paper) so the tape and the
   paper rotate together as one rigid unit -- rotating only the paper
   let the tape (its unrotated sibling) drift away from the paper's
   visual top edge as box height changed across viewports. */
.sticky-note--newsletter {
  margin-top: calc(clamp(3rem, 6vw, 5rem) + 30px);
  /* ~65% of the screen on desktop, never narrower than 920px */
  max-width: min(max(920px, 65vw), 1300px);
  width: 100%;
  align-self: center;
  transform: rotate(-0.6deg);
}
.sticky-note--newsletter .display-heading {
  max-width: 18ch;
  margin-bottom: clamp(1.5rem, 3vw, 2.5rem);
}
/* H2-Mobile: 18/21 medium, 2% tracking, no width cap */
@media (max-width: 720px) {
  .sticky-note--newsletter .display-heading {
    font-size: var(--body-size);
    line-height: var(--body-line);
    letter-spacing: 0.02em;
    max-width: none;
  }
}

.sticky-note--quote {
  /* ~65% of the screen on desktop, never narrower than 720px */
  max-width: min(max(720px, 65vw), 1300px);
  align-self: center;
  margin-top: calc(clamp(2.5rem, 6vw, 7rem) + 30px);
}
/* Quote papers get ~15px extra air above and below the text */
.sticky-note--quote .note-paper {
  padding-block: calc(clamp(1.75rem, 4vw, 3.75rem) + 15px);
}
/* Tighter around the closing section: less air above "Planst du
   einen Übertritt?" and towards the footer */
main > .section-block:last-child {
  padding-top: clamp(2rem, 4.5vw, 5rem);
  padding-bottom: calc(clamp(4.5rem, 9vw, 10rem) - 50px);
}
.sticky-note--tilt-left { transform: rotate(-1.4deg); }
.sticky-note--tilt-right { transform: rotate(1.4deg); }

.quote-text {
  font-size: var(--h1-size);
  line-height: var(--h1-line);
  letter-spacing: 0.01em;
  font-weight: 500; /* Figma H1: 65 Medium */
  color: var(--ink);
}

.tape {
  position: absolute;
  z-index: 2;
  /* ~1/3 of the paper, trimmed 10% per client feedback */
  width: 29%;
  height: auto;
  /* Figma: tapes are 85% opaque, letting the paper shimmer through */
  opacity: 0.85;
  pointer-events: none;
  user-select: none;
}
/* top: 0 anchors the tape to the paper's top edge (paper starts at the
   wrapper's top since tape is absolute); translateY(-50%) then centers
   it ON the edge -- half above, half on the paper -- at any size. */
.tape--newsletter {
  top: 0;
  left: 50%;
  transform: translate(-50%, -50%) rotate(-3deg);
}
.tape--quote {
  top: 0;
  left: 50%;
  transform: translate(-50%, -50%) rotate(-4deg);
  /* Chunky like the photo-card tapes */
  width: 27%;
}
.sticky-note--tilt-right .tape--quote {
  transform: translate(-50%, -50%) rotate(4deg);
}
/* On phones the vw-based sizes bottom out too small -- scale the tape
   up relative to the (much narrower) notes, like the mobile design. */
@media (max-width: 720px) {
}

/* Phones: stickers a touch larger relative to their papers */
@media (max-width: 720px) {
  .tape { width: 38%; }
  .tape--quote { width: 36%; }
  .photo-card::before { width: 56%; }
  .photo-card--3::before, .photo-card--6::before { width: 61%; }
}

/* The photos arrow renders at ~1/3 natural size on phones, which
   shrinks its head out of proportion -- scale the head path back up
   around its tip so all arrowheads render alike. */
@media (max-width: 720px) {
  .arrow--photos path:nth-of-type(2) {
    transform-box: fill-box;
    transform-origin: 61% 100%;
    scale: 1.9;
  }
}

/* ---------- Hand-drawn connector arrows ---------- */
/* Note arrows are drawn at runtime (script.js drawNoteArrows): a 1x1
   SVG anchored at the note's top-left with overflow visible, paths in
   note-local coordinates. Same 2.5px line as everything else. */
.sticky-note svg.connector {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  overflow: visible;
  pointer-events: none;
  z-index: 2;
}
.sticky-note svg.connector path {
  fill: none;
  stroke: var(--ink);
  /* 2.5px is the site-wide line weight (underline, badge ring, arrows) */
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.arrow-anchor { position: relative; }
/* Fixed-shape arrows from the design that replace the runtime-drawn
   connector on specific notes (data-arrow="static"). */
.arrow-static {
  position: absolute;
  right: 4%;
  top: 0;
  height: clamp(110px, 12vw, 150px);
  width: auto;
  transform: translateY(-72%);
  pointer-events: none;
  user-select: none;
  z-index: 2;
}
/* The gap above the note shrinks to ~50px on phones -- keep the tail
   inside it (below the text) and let the head dip only into the note's
   top padding (24px), never onto the quote text. */
@media (max-width: 720px) {
  .arrow-static {
    height: 80px;
    transform: translateY(-72%);
    right: 8%;
  }
}
/* Tall zigzag left of the Wahlbereich note, its horizontal base
   pointing right into the note's top-left corner (per design). */
.arrow-static--zigzag {
  height: clamp(176px, 27.5vw + 33px, 583px);
  right: calc(100% - 24px);
  transform: translateY(calc(-100% + 44px));
}
/* The design gives this note a much taller gap so the zigzag fits
   into the whitespace instead of crossing the text (desktop only). */
@media (min-width: 721px) {
  .sticky-note--quote:has(.arrow-static--zigzag) {
    margin-top: calc(clamp(165px, 27.5vw, 418px) + 30px);
  }
}
/* Mobile uses the compact zigzag on the note's right, per the design */
.arrow-static--zigzag-m { display: none; }
@media (max-width: 720px) {
  .arrow-static--zigzag { display: none; }
  .arrow-static--zigzag-m {
    display: block;
    height: 132px;
    right: 2%;
    transform: translateY(-64%);
  }
}

/* Big arc arrow onto the newsletter note (tail at the intro text,
   head diving onto the paper). */
.arrow-static--curve {
  height: clamp(165px, 19.8vw, 220px);
  right: 6%;
  transform: translateY(-70%);
}
/* Tall S-snake beside the sun's right, head landing on the closing
   note's top-right corner (per design; it may reach up to the header). */
.arrow-static--sun {
  height: clamp(396px, 52.8vw, 803px);
  /* Push right just far enough that the S-bow clears the sun disc
     (0.377*height - 54px), but never past the viewport edge. */
  right: clamp(calc(376px - 50vw), calc(54px - 19.9vw), 0px);
  /* Head lands inside the paper, within its top padding */
  transform: translateY(calc(-100% + clamp(40px, 4.6vw, 68px)));
}
/* Phones use the design's small arc below the sun's left side instead
   of the tall snake -- it cannot touch the sun there. */
.arrow-static--sun-curl { display: none; }
@media (max-width: 720px) {
  .arrow-static--sun { display: none; }
  .arrow-static--sun-curl {
    display: block;
    height: clamp(143px, 46vw, 187px);
    right: 4%;
    transform: translateY(calc(-100% + 28px));
  }
}

/* Static in-flow arrow before the photo strip (tail top-right, head
   bottom-left, pointing down toward the photos). */
.arrow--photos {
  display: block;
  width: clamp(242px, 33vw, 440px);
  height: auto;
  margin: clamp(1rem, 2vw, 2rem) 0 0 clamp(2rem, 26vw, 24rem);
  /* Shift down (visually only) so the head lands in the upper part of
     the first photo; z-index draws it over the card. */
  position: relative;
  z-index: 2;
  transform: translateY(clamp(3.5rem, 6vw, 5.5rem));
  pointer-events: none;
  user-select: none;
}
@media (max-width: 720px) {
  .arrow--photos {
    width: clamp(176px, 53vw, 286px);
    margin-left: clamp(2rem, 30vw, 10rem);
  }
}

/* ---------- Newsletter form ---------- */
.newsletter-form {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.form-row {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
}
.field { flex: 1 1 200px; }
.field--email { flex: 1 1 260px; }
.field input {
  width: 100%;
  border: none;
  border-radius: 5px;
  background: var(--white);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--field-size);
  font-weight: 700;
  padding: 0.9em 1.1em;
}
.field input::placeholder { color: var(--gray); font-weight: 700; }
.field input:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }

.btn-classic {
  border: none;
  border-radius: 5px;
  background: var(--orange);
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--field-size);
  padding: 0.9em 2.4em;
  cursor: pointer;
  white-space: nowrap;
  transition: filter 0.15s ease;
}
.btn-classic:hover { filter: brightness(1.08); }
.btn-classic:active { filter: brightness(0.95); }

.checkbox-row {
  display: flex;
  align-items: center;
  gap: 0.6em;
  font-size: clamp(0.8rem, 0.7rem + 0.3vw, 1rem);
  font-weight: 700;
  margin-top: 0.4rem;
  cursor: pointer;
}
.form-status {
  margin-top: 0.75rem;
  font-size: var(--h3-size);
  font-weight: 700;
  min-height: 1.2em;
}
.form-status--error { color: var(--pink); }
@media (max-width: 720px) {
  .checkbox-row {
    /* Figma says 7px, but keep a readable floor */
    font-size: 11px;
    line-height: 1.25;
    font-weight: 500;
    letter-spacing: 0.02em;
  }
}
.checkbox-row a { text-decoration: underline; }
.checkbox-row input {
  width: 1.1em;
  height: 1.1em;
  accent-color: var(--ink);
  cursor: pointer;
}

/* ---------- Photo strip ---------- */
.photo-strip {
  overflow-x: auto;
  overflow-y: hidden;
  cursor: grab;
  /* Headroom for the full tape overhang + card tilt (the strip clips
     vertically, so the tapes were cut off with less) */
  padding-block: clamp(2.5rem, 4.8vw, 6rem);
  /* Pull the row up against the section gap, closer to the intro
     text; the growth over the old 1.75rem headroom is pulled back
     out of the flow so photo positions and rhythm stay unchanged */
  margin-top: calc(clamp(-9rem, -8.5vw, -3rem) - (clamp(2.5rem, 4.8vw, 6rem) - 1.75rem));
  margin-bottom: calc(-1 * (clamp(2.5rem, 4.8vw, 6rem) - 1.75rem));
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.photo-strip::-webkit-scrollbar { display: none; }
.photo-strip:active { cursor: grabbing; }
.photo-strip-track {
  display: flex;
  gap: clamp(1.5rem, 3vw, 3rem);
  padding-inline: var(--container-pad);
  width: max-content;
}
.photo-card {
  flex: 0 0 auto;
  /* Figma: bare photos, ~730px at the 1512 frame (48vw), growing
     until 2000px. No frame, no shadow. */
  width: clamp(280px, 48vw, 960px);
  position: relative;
}
/* No extra rotation: the tape is a child of the card, so it inherits
   the card's tilt and stays square to the photo edge, like the design. */
.photo-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  width: 47%;
  aspect-ratio: 2.9;
  transform: translate(-50%, -50%);
  background: url("assets/img/tape-a.webp") no-repeat center / contain;
  /* Same 85% tape opacity as .tape (Figma) */
  opacity: 0.85;
  pointer-events: none;
}
.photo-card--2::before, .photo-card--5::before {
  background-image: url("assets/img/tape-c.webp");
}
.photo-card--3::before, .photo-card--6::before {
  background-image: url("assets/img/tape-d.webp");
  aspect-ratio: 3.5;
  width: 52%;
}
.photo-card img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  -webkit-user-drag: none;
}
.photo-card--1 { transform: rotate(-3deg); }
.photo-card--2 { transform: rotate(2deg); }
.photo-card--3 { transform: rotate(-2deg); }
.photo-card--4 { transform: rotate(3deg); }
.photo-card--5 { transform: rotate(-2.5deg); }
.photo-card--6 { transform: rotate(2.5deg); }

/* ---------- Sun illustration ---------- */
/* Mobile: square crop at the design's 347px. Desktop (>=721px): the
   wide 1254x671 crop from the desktop frame, near container width. */
.sun-picture { display: block; }
.sun-illustration {
  display: block;
  width: min(347px, 100%);
  margin-inline: auto;
}
@media (min-width: 721px) {
  .sun-illustration { width: min(1254px, 100%); }
}

/* ---------- Footer ---------- */
.site-footer {
  background: var(--yellow);
  margin-top: clamp(3rem, 6vw, 5rem);
  padding-block: clamp(3rem, 6vw, 5.5rem);
  /* Bleed the yellow below the document end so iOS rubber-banding
     past the footer stays yellow -- without touching the page
     background (a gradient there tiled and made pull-to-refresh at
     the TOP yellow). Spread is clipped horizontally by the body's
     overflow-x: hidden. */
  box-shadow: 0 25vh 0 25vh var(--yellow);
}
/* Desktop: tighter below the bottom-aligned copyright line */
@media (min-width: 861px) {
  .site-footer { padding-bottom: clamp(1.5rem, 3vw, 2.75rem); }
}
.footer-grid {
  display: grid;
  /* Wide logo column pushes the contact/disclaimer columns right */
  grid-template-columns: 2.1fr 1fr 1fr;
  gap: 1.25rem clamp(2rem, 5vw, 4rem);
  align-items: start;
}
.logo--footer { align-self: start; }
.footer-heading {
  color: var(--orange);
  /* Figma: the footer stays at the full 20px H3 even on phones */
  font-size: max(20px, var(--h3-size));
  font-weight: 700;
  margin-bottom: 0.15em;
}
.footer-heading--disclaimer { margin-top: 2.2em; }
.footer-text {
  font-size: max(20px, var(--h3-size));
  line-height: var(--h3-line);
  font-weight: 700;
}
.footer-text a { text-decoration: underline; }

.footer-copyright {
  font-size: 15px; /* Figma utility size */
  font-weight: 700;
  line-height: var(--h3-line); /* same box ratio as the footer text */
}
/* Desktop: the copyright shares the Gymnasium column (row 1),
   bottom-aligned so its line sits on the same bottom line as the
   AGBs link in the Disclaimer column. Everything is placed
   explicitly -- an overlapping explicit item would otherwise push
   the auto-placed columns out of row 1. */
@media (min-width: 861px) {
  .logo--footer { grid-column: 1; grid-row: 1; }
  .footer-col { grid-row: 1; }
  .footer-col:nth-of-type(1) { grid-column: 2; }
  .footer-col:nth-of-type(2) { grid-column: 3; }
  .footer-copyright { grid-column: 2; grid-row: 1; align-self: end; }
}

@media (max-width: 860px) {
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .logo--footer { grid-column: 1 / -1; grid-row: 1; }
  /* Everything placed explicitly: the overlapping copyright would
     otherwise push the auto-placed columns into an implicit third
     column off the grid */
  .footer-col { grid-row: 2; }
  .footer-col:nth-of-type(1) { grid-column: 1; }
  .footer-col:nth-of-type(2) { grid-column: 2; }
  /* Copyright shares the first column, bottom-aligned: its line ends
     on the same bottom line as the AGBs link in the second column */
  .footer-copyright { grid-column: 1; grid-row: 2; align-self: end; }
}
@media (max-width: 520px) {
  .footer-grid { grid-template-columns: 1fr; }
  .footer-heading--disclaimer { margin-top: 1.5em; }
  /* Single column: everything stacks in source order again (the
     nth-of-type selectors must match the two-column rules'
     specificity, or those would still win here) */
  .footer-col:nth-of-type(1),
  .footer-col:nth-of-type(2) { grid-row: auto; grid-column: 1; }
  .footer-copyright { grid-column: 1; grid-row: auto; align-self: auto; }
}

@media (max-width: 640px) {
  .body-list-columns { grid-template-columns: 1fr; gap: 0; }
  .note-paper { padding: 1.5rem 1.4rem; }
}
/* Quote notes use H2-Mobile on phones: 18/21 medium, 2% tracking */
@media (max-width: 720px) {
  .quote-text {
    font-size: var(--body-size);
    line-height: var(--body-line);
    font-weight: 500;
    letter-spacing: 0.02em;
  }
}

/* Mobile-2 Figma frame: text flush with the heading margin (no inset)
   and round bullets instead of dashes. */
@media (max-width: 720px) {
  .body-text,
  .body-list,
  .body-list-columns {
    margin-inline: 0;
  }
  .body-list li::before { content: "\2022"; }
}

/* ---------- Micro-interactions ---------- */
/* Yellow papers wobble softly under the cursor: a damped sway (each
   swing smaller than the last) with a hint of lift, like a pinned
   paper settling after a nudge */
@keyframes note-shiver {
  0%   { rotate: 0deg;     translate: 0 0; }
  18%  { rotate: 0.6deg;   translate: 0 -2px; }
  45%  { rotate: -0.4deg;  translate: 0 1px; }
  70%  { rotate: 0.18deg;  translate: 0 -0.5px; }
  88%  { rotate: -0.07deg; translate: 0 0; }
  100% { rotate: 0deg;     translate: 0 0; }
}
/* The whole note wobbles -- paper AND tape move as one rigid unit
   (the animated rotate/translate compose with the wrapper's static
   transform tilt) */
.sticky-note:hover {
  animation: note-shiver 1.1s cubic-bezier(0.37, 0, 0.63, 1);
}
/* Photos get the same nudge; the animated rotate/translate properties
   compose with each card's static transform: rotate(...) tilt */
.photo-card:hover {
  animation: note-shiver 1.1s cubic-bezier(0.37, 0, 0.63, 1);
}

/* Arrows draw in along their line when scrolled into view, the head
   snaps on at the end together with a little blop. */
/* dash lengths are set per-arrow in script.js (screen-space) */
.arrow-draw path:nth-of-type(1) {
  /* starts slow, accelerates towards the end */
  transition: stroke-dashoffset 0.55s cubic-bezier(0.55, 0, 0.85, 0.55);
}
.arrow-draw path:nth-of-type(2) {
  transition: stroke-dashoffset 0.1s ease-out 0.55s;
}
.arrow-draw.is-drawn path:nth-of-type(2) {
  /* only the head does a little blop */
  transform-box: fill-box;
  transform-origin: center;
  animation: head-blop 0.28s ease-out 0.55s;
}
@keyframes head-blop {
  0% { scale: 1; }
  40% { scale: 1.35; }
  100% { scale: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .sticky-note:hover { animation: none; }
  .photo-card:hover { animation: none; }
  .hero-globe { animation: none; }
  .hero-caption { animation: none; }
  .arrow-draw path { stroke-dasharray: none !important; stroke-dashoffset: 0 !important; transition: none; animation: none; }
}

/* Phones: 2.5px lines look heavier against the smaller layout --
   thin all lines to 2px to visually match desktop. The badge ring
   and the squiggle underline are not inline SVGs, so they swap to
   -m variants with the thinner stroke baked in. */
@media (max-width: 720px) {
  svg.arrow-draw path,
  .sticky-note svg.connector path {
    stroke-width: 2;
  }
  .underline-word::after {
    background-image: url("assets/img/squiggle-m.svg?v=1");
    min-height: 2px;
  }
  .underline-word--a::after { background-image: url("assets/img/squiggle-a-m.svg?v=1"); }
  .underline-word--b::after { background-image: url("assets/img/squiggle-b-m.svg?v=1"); }
  .underline-word--c::after { background-image: url("assets/img/squiggle-c-m.svg?v=1"); }
  .underline-word--d::after { background-image: url("assets/img/squiggle-d-m.svg?v=1"); }
}
