/* Ciudad de Ángeles — the blend, carried onto the seven remaining pages.
   Loads after site.css and blend.css. Additive, like blend.css: it redefines no brand
   colour, no font, no spacing scale.

   Ben, 2026-09-22: "just build them, I trust you and your design aesthetic."

   The home page's warmth comes from three things, and this file brings all three to the
   pages that were already written: photographs shown as physical prints, a paper ground
   with a hand in it, and type that behaves like a magazine rather than a brochure. What it
   deliberately does NOT do is rewrite a single sentence — these pages' words are the
   client's, they are already on the site, and the copy gate holds them. This is dressing.

   The one structural gap it closes: the old pages have no photographs at all. Their
   image slots are `.frame` — a duotone gradient with an icon in it, a placeholder that was
   honest when there were no pictures and is now just a coloured box. Where a real
   photograph exists, `.frame.has-photo` becomes a print; where one does not, the frame is
   quietened so it reads as paper rather than as a poster.

   What moves: nothing that was not already moving. blend.css's reveal choreography runs on
   `.reveal` elements these pages already carry, once, on load. No scroll-driven section
   here — the relay on the home page is meant to be the only one. */

/* ---------- the ground ---------- */
/* The home page alternates paper and a dotted noticeboard. These pages alternate paper and
   --paper-2 through the existing `.soft` tone, so the rhythm arrives without a content edit. */
.section.soft {
  background-color: var(--paper-2);
  background-image: radial-gradient(var(--board-dot) .8px, transparent .8px);
  background-size: 17px 17px;
}

/* ---------- section labels: the same hand as the home page's kickers ---------- */
.sec-label { align-items: center; }
.sec-label .idx {
  font-variant-numeric: tabular-nums;
  color: var(--coral-text);           /* the contrast fix from blend.css, applied here too */
}
.sec-label .meta { color: var(--ink-2); }
.sec-label .rule { background: var(--line-2); }

/* Display type on these pages was set a notch tighter than the home page's. Match it, so a
   visitor moving from the home page to Make an Impact does not feel the font change. */
h2.big { letter-spacing: -.04em; line-height: .98; text-wrap: balance; }
h2.mid { text-wrap: balance; }
.lede { text-wrap: pretty; }
.prose p { text-wrap: pretty; }
.pull { text-wrap: balance; }
.pull .hl { color: var(--coral-text); }

/* ---------- a photograph, as a print ---------- */
/* Same object as blend.css's `.snap`, reached through the markup these pages already have.
   `.frame` keeps its aspect-ratio classes; the gradient, the hatching and the icon go. */
.frame.has-photo {
  background: var(--print-bg);
  color: var(--ink);
  padding: var(--print-pad) var(--print-pad) calc(var(--print-pad) * 1.5);
  border-radius: var(--print-radius);
  box-shadow: var(--print-shadow);
  rotate: var(--tilt, 0deg);
  display: block;
  overflow: visible;
}
.frame.has-photo::after { content: none; }          /* no hatching on a real photograph */
.frame.has-photo > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 1px;
  background: var(--paper-2);
  display: block;
}
/* The aspect ratio belongs to the picture, not to the paper around it. */
.frame.has-photo { aspect-ratio: auto; }
.frame.has-photo.a43 > img { aspect-ratio: 4 / 3; }
.frame.has-photo.a34 > img { aspect-ratio: 3 / 4; }
.frame.has-photo.a11 > img { aspect-ratio: 1; }
.frame.has-photo.a169 > img { aspect-ratio: 16 / 9; }
.frame.has-photo .cap {
  font-family: var(--font-script);
  font-weight: 700;
  font-size: clamp(20px, 1.9vw, 26px);
  letter-spacing: 0;
  text-transform: none;
  line-height: 1.15;
  color: var(--brand-deep);
  margin: calc(var(--print-pad) * .9) 2px 0;
  opacity: 1;
  text-align: left;
  text-wrap: pretty;
}
.frame.has-photo .cap .where {
  display: block;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: .62rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin-top: 6px;
}
/* One piece of tape per page, on the first print only — the same restraint as the board. */
.frame.has-photo.taped { position: relative; }
.frame.has-photo.taped::before {
  content: "";
  position: absolute;
  top: -13px;
  left: 50%;
  width: 92px;
  height: 26px;
  translate: -50% 0;
  rotate: 2.5deg;
  background: color-mix(in srgb, var(--gold) 72%, transparent);
  box-shadow: 0 1px 2px rgba(23, 19, 16, .14);
}

/* ---------- a filled placeholder ---------- */
/* The written briefs inside the old placeholder boxes are now real photographs. These sit in
   the page's own columns rather than on the noticeboard, so they are photographs with a
   caption under them, not pinned prints: no tilt, no tape, nothing to mistake for a scrapbook.
   `:has(img)` is the switch — a frame whose optional photograph is absent keeps every rule
   below it untouched, because the generator removes the <img> element entirely. */
.frame:has(img.fill) {
  background: var(--print-bg);
  color: var(--ink);
  box-shadow: var(--print-shadow);
  border: 0;
  overflow: hidden;
}
.frame:has(img.fill)::after { content: none; }
.frame img.fill { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
/* the caption rides over the foot of the picture, where a photograph's own caption belongs */
.frame:has(img.fill) .fi {
  position: absolute;
  inset: auto 0 0;
  padding: 34px 16px 12px;
  background: linear-gradient(to top, rgba(18, 58, 92, .82), rgba(18, 58, 92, 0));
  text-align: left;
}
.frame:has(img.fill) .fi .ic { display: none; }
.frame:has(img.fill) .cap {
  color: #fff !important;
  margin: 0;
  font-family: var(--font-mono);
  font-size: .68rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  opacity: 1;
}
.frame:has(img.fill) .play { position: relative; z-index: 2; }
/* a highlight card's picture is small; its caption would cover the child's face */
.hl .frame:has(img.fill) .fi { display: none; }

/* A frame with no photograph behind it should not shout. Flatten the gradient to a tint of
   the brand and drop the hatch; it becomes a quiet card instead of a poster. */
.frame:not(.has-photo) {
  background: var(--brand-tint);
  color: var(--brand-deep);
  box-shadow: none;
  border: 1px solid color-mix(in srgb, var(--brand) 22%, transparent);
}
.frame:not(.has-photo).gold { background: var(--gold-tint); color: var(--ink); }
.frame:not(.has-photo).coral { background: var(--coral-tint); color: var(--coral-hover); }
.frame:not(.has-photo)::after { content: none; }
.frame:not(.has-photo) .ic { opacity: .5; }
.frame:not(.has-photo) .cap { color: currentColor; opacity: .75; }

/* ---------- the prints strip: the noticeboard, in a page's own rhythm ---------- */
.prints {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: clamp(20px, 2.6vw, 40px);
  align-items: start;
}
.prints > * { min-width: 0; }
.prints > :nth-child(1) { grid-column: span 5; --tilt: var(--tilt-1); }
.prints > :nth-child(2) { grid-column: span 4; --tilt: var(--tilt-2); margin-top: clamp(20px, 3.4vw, 54px); }
.prints > :nth-child(3) { grid-column: span 3; --tilt: var(--tilt-3); margin-top: clamp(6px, 1.4vw, 18px); }
.prints > :nth-child(4) { grid-column: span 4; --tilt: var(--tilt-4); }
.prints > :nth-child(5) { grid-column: span 5; --tilt: var(--tilt-3); }
.prints-head { max-width: 46ch; margin-bottom: clamp(10px, 1.8vw, 24px); }
/* A strip of one is a picture, not a grid: centre it and give it real size, rather than
   leaving two thirds of the row empty. Two prints share the row evenly. */
.prints:has(> :only-child) { grid-template-columns: minmax(0, 1fr); justify-items: center; }
.prints > :only-child { grid-column: 1; width: min(100%, 720px); }
.prints > :first-child:nth-last-child(2), .prints > :first-child:nth-last-child(2) ~ * { grid-column: span 6; }

/* one large print, centred, when a page wants a single picture to carry a section */
.print-solo { max-width: 760px; margin-inline: auto; --tilt: var(--tilt-1); }

/* ---------- the numbered paths: the tear-off strip's manners ---------- */
.path { transition: padding-left .25s, background .18s; }
.path:hover { background: var(--paper-2); padding-left: 12px; }
.path .pn { color: var(--coral-text); font-variant-numeric: tabular-nums; }
.path h3 { text-wrap: balance; }
/* The whole row is the target, not the small link inside it. */
.path a { position: relative; }
.path a::after { content: ""; position: absolute; inset: -18px -12px; }

/* ---------- the smallest phone ---------- */
/* Pre-existing, measured before this slice and left alone by it: the four-up stat band and
   the four-up tier row keep two columns at 320px and their contents cannot shrink, so
   Our Story scrolled sideways by 54px and Support a Home by 11px. One column below 520,
   and every grid child allowed to shrink. */
.statline > *, .tiers > *, .eg > *, .path > *, .prints > * { min-width: 0; }
@media (max-width: 519px) {
  .statline, .tiers { grid-template-columns: minmax(0, 1fr); }
  /* The "90¢ of every dollar" figure sits beside its sentence in a flex row; at 320 the
     number alone is wider than the space left for the words, so the row stacks. */
  .trust90 { flex-wrap: wrap; gap: 8px 20px; }
  .trust90 .t { flex: 1 1 100%; }
}

/* ---------- tiers read as a ledger ---------- */
.tier { border-top-color: var(--brand-deep); }
.tier .amt { font-variant-numeric: tabular-nums; }
.tier .amt span { color: var(--ink-2); }
.tiers > .tier:hover { background: var(--surface); }

/* ---------- stats: the home page's gold numbers, on the brand ground ---------- */
.statline .s .n { font-variant-numeric: tabular-nums; }

/* ---------- forms: the quiz's choices, not a brochure's boxes ---------- */
/* Every field on these pages is `.input`; the quiz taught the house that a form control is
   a large, calm, single-column thing with a visible focus ring. */
.input {
  background: var(--surface);
  border-color: var(--line-2);
  padding: 15px 16px;
  min-height: 52px;
}
.input:hover { border-color: var(--brand); }
.input:focus { border-color: var(--brand); box-shadow: 0 0 0 3px rgba(40, 96, 144, .14); }
select.input { appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--ink-2) 50%), linear-gradient(135deg, var(--ink-2) 50%, transparent 50%); background-position: calc(100% - 20px) 55%, calc(100% - 14px) 55%; background-size: 6px 6px, 6px 6px; background-repeat: no-repeat; padding-right: 44px; }
textarea.input { min-height: 132px; }
label { display: inline-block; }

/* A form section sits on paper with a hairline, the way a printed application does. */
.section [id$="-form"], .panel-form {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--coral);
  padding: clamp(22px, 3vw, 38px);
}

/* ---------- the closing band ---------- */
/* blend.css already darkens `.section.coral` for contrast; keep its buttons honest here. */
.section.coral .btn-outline.on-blue:hover { background: #fff; color: var(--coral-hover); border-color: #fff; }

/* ---------- motion ---------- */
/* Ben, 2026-09-22, choosing from five candidates: "definitely do one, two, and let's do three on
   one page." One is sections arriving as you scroll; two is a fade between pages; three is the
   sticky section label, on Our Story only until he has seen it.

   The floor stays what it was: a page with no scroll-timeline support, or with motion paused, or
   with reduced motion asked for, does the load choreography once and nothing else. */
@keyframes page-rise {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}
body.motion-on .section .reveal { animation: page-rise .6s var(--ease-out) both; }
body.motion-on .section .reveal:nth-child(2) { animation-delay: .06s; }
body.motion-on .section .reveal:nth-child(3) { animation-delay: .12s; }

/* 1. Sections arrive as you reach them. Before this, everything below the first screen had
   finished animating before a visitor ever got there. `view()` is the same mechanism the home
   page already uses for its hero print, so nothing new runs and no JavaScript is involved.
   `animation-range` ends at 34% so a block is settled well before it reaches the middle of the
   screen — a reader should never watch a paragraph finish arriving. */
@supports (animation-timeline: view()) {
  body.motion-on .section .reveal {
    animation: page-rise .5s linear both;
    animation-timeline: view();
    animation-range: entry 4% entry 34%;
    animation-delay: 0s;
  }
  /* the first screenful has no scroll to animate against, so it keeps the load choreography */
  body.motion-on .section:first-of-type .reveal,
  body.motion-on .section:nth-of-type(2) .reveal {
    animation: page-rise .6s var(--ease-out) both;
    animation-timeline: auto;
  }
  body.motion-on .section:nth-of-type(2) .reveal:nth-child(2) { animation-delay: .06s; }
}

/* 3. The section's own label stays with the section while it scrolls past, then the next one takes
   its place. No animation: it is a position. Tried on Our Story first; Ben, 2026-09-22: "yes, I
   like that. Do that on the rest." — so it now applies to every page that loads this stylesheet. */
.section .sec-label {
  position: sticky;
  top: 69px;                       /* the site header is 69px tall and sticky above it */
  z-index: 3;
  background: var(--paper);        /* solid: a headline scrolling under it must not read through */
  padding-block: 14px 10px;
  margin-bottom: clamp(16px, 3vw, 30px);
}
/* and a short fade below, so the section does not look cut off at a hard line */
.section .sec-label::after {
  content: "";
  position: absolute;
  inset: 100% 0 auto;
  height: 18px;
  background: linear-gradient(to bottom, var(--paper), transparent);
  pointer-events: none;
}
.section.soft .sec-label { background: var(--paper-2); }
.section.soft .sec-label::after { background: linear-gradient(to bottom, var(--paper-2), transparent); }
.section.blue .sec-label { background: var(--brand-deep); }
.section.blue .sec-label::after { background: linear-gradient(to bottom, var(--brand-deep), transparent); }
/* the closing coral band is one statement, not a section to navigate */
.section.coral .sec-label { background: none; position: static; }
.section.coral .sec-label::after { content: none; }
@media (max-width: 767px) {
  /* on a phone the header already takes a band off the top; a second sticky line costs too much */
  .section .sec-label { position: static; background: none; padding-block: 0; }
}

@media (prefers-reduced-motion: reduce) {
  body.motion-on .section .reveal { animation: none; }
}

/* ---------- responsive ---------- */
@media (max-width: 1023px) {
  .prints > :nth-child(1), .prints > :nth-child(5) { grid-column: span 7; }
  .prints > :nth-child(2), .prints > :nth-child(4) { grid-column: span 5; }
  .prints > :nth-child(3) { grid-column: span 5; }
}
@media (max-width: 767px) {
  .prints { gap: 22px 14px; }
  .prints > * { grid-column: span 12 !important; margin-top: 0; }
  .frame.has-photo.taped::before { width: 70px; height: 22px; top: -11px; }
}

/* 2. A fade between pages. Chrome and Safari cross-fade one document into the next; every other
   browser ignores the rule and navigates as it always did. The same two lines are in blend.css so
   the home page, the quiz and the Casa form are part of the same crossing. */
@view-transition { navigation: auto; }
@media (prefers-reduced-motion: reduce) { @view-transition { navigation: none; } }
