/* ==========================================================================
   Conservatives for Osborn — master stylesheet
   All site styles live in this file.
   ==========================================================================

   1. Palette / tokens        <- change colors HERE only
   2. Reset & base
   3. Layout helpers
   4. Header / nav
   5. Hero (scrolling background image)
   6. Sections
   7. Issues accordion
   8. Footer / paid-for
   9. Responsive
   ========================================================================== */

/* 1. PALETTE / TOKENS
   --------------------------------------------------------------------------
   Osborn for Senate's own brand colors, ported from the campaign site's theme
   tokens (see nebraska-map.css in the websiteMap project, which reads them off
   osbornforsenate.com's published theme):

     accent red  #b9202f   frames, rules, links, buttons (site value; O4S publishes #b81f2e)
     maroon      #6a030f   hover / pressed
     light gray  #e2e2e2   light accent surface
     ink         #1a1a1a   body text on white
     white       #ffffff

   Swap the six --c-* values below and the whole site re-skins; the only colors
   outside this block are the five translucent black/white values tied to the
   hero photography (§5) and the footer (§8).
   -------------------------------------------------------------------------- */
:root {
  /* core palette — brand */
  --c-ink:        #1a1a1a;   /* primary text / dark surfaces (brand ink) */
  --c-ink-soft:   #5a5a5a;   /* secondary text — derived; O4S names no such token */
  --c-paper:      #ffffff;   /* page background, header, issue cards */
  --c-paper-alt:  #e2e2e2;   /* alternating section background (brand light gray) */
  --c-accent:     #b9202f;   /* links, buttons, rules (accent red; O4S theme reads #b81f2e) */
  --c-accent-dk:  #6a030f;   /* accent hover / pressed (brand maroon) */

  /* derived */
  --c-line:       rgba(0, 0, 0, .12);      /* hairline; must read on paper AND paper-alt */
  --c-overlay:    rgba(0, 0, 0, 0.55);     /* hero image scrim */
  --c-on-dark:    #ffffff;

  /* how strongly the flag reads behind the issues — raise to taste */
  --flag-opacity: .07;

  /* assets — the only place an image path is written.
     The hero cycles through --hero-image-1..N; to add a photo, add the next
     token here, a matching .hero__slide--N rule in section 5, and a matching
     <div> in the hero markup. Nothing else needs to change. */
  --hero-image-1: url("../media/front_splash/DSC06632.jpeg");
  --hero-image-2: url("../media/front_splash/DSC01328.jpg");
  --hero-image-3: url("../media/front_splash/America.jpg");
  --hero-image-4: url("../media/front_splash/Work.jpg");
  --flag-image:   url("../images/flag-billow.svg");

  /* how long one photo takes to dissolve into the next */
  --hero-fade: 1400ms;

  /* type */
  --font-head: "Georgia", "Times New Roman", serif;
  --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
               "Helvetica Neue", Arial, sans-serif;

  /* metrics */
  --wrap:        1120px;
  --wrap-narrow: 780px;
  --pad:         1.5rem;
  --radius:      3px;
  --shadow:      0 1px 3px rgba(0, 0, 0, .10), 0 8px 24px rgba(0, 0, 0, .06);
  --ease:        cubic-bezier(.4, 0, .2, 1);
}

/* 2. RESET & BASE
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--c-paper);
  color: var(--c-ink);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.65;
}

h1, h2, h3, h4 {
  font-family: var(--font-head);
  font-weight: 700;
  line-height: 1.15;
  margin: 0 0 .5em;
  letter-spacing: -0.01em;
}

h1 { font-size: clamp(2.5rem, 6vw, 4.25rem); }
h2 { font-size: clamp(1.9rem, 3.5vw, 2.6rem); }
h3 { font-size: 1.25rem; }

p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }

a { color: var(--c-accent); text-decoration: none; }
a:hover, a:focus-visible { color: var(--c-accent-dk); text-decoration: underline; }

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

:focus-visible {
  outline: 2px solid var(--c-accent);
  outline-offset: 3px;
}

/* 3. LAYOUT HELPERS
   -------------------------------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--pad);
}

.wrap--narrow { max-width: var(--wrap-narrow); margin-inline: auto; }

.section { padding: clamp(3.5rem, 8vw, 6rem) 0; }
.section--alt { background: var(--c-paper-alt); }

/* Runs its content edge-to-edge: the wrap drops its side padding and the
   heading takes its own back, so only the issue cards go flush. */
.section--flush > .wrap { padding-inline: 0; }
.section--flush .section-head { padding-inline: var(--pad); }

.section-head { text-align: center; margin-bottom: 3rem; }

.section-head::after {
  content: "";
  display: block;
  width: 64px;
  height: 3px;
  margin: 1.25rem auto 0;
  background: var(--c-accent);
}

.lede {
  font-size: 1.15rem;
  color: var(--c-ink-soft);
  max-width: 60ch;
  margin-inline: auto;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--c-ink);
  color: var(--c-on-dark);
  padding: .75rem 1.25rem;
  z-index: 200;
}
.skip-link:focus { left: 0; }

/* 4. HEADER / NAV
   -------------------------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--c-paper);
  border-bottom: 1px solid var(--c-line);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  min-height: 72px;
  padding-block: .75rem;
}

.brand {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.1rem;
  line-height: 1.2;
  color: var(--c-ink);
  text-transform: uppercase;
  letter-spacing: .06em;
}
.brand:hover { color: var(--c-ink); text-decoration: none; }

.nav {
  display: flex;
  align-items: center;
  gap: 1.75rem;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav__link {
  color: var(--c-ink);
  font-weight: 600;
  font-size: .95rem;
  letter-spacing: .02em;
}
.nav__link:hover { color: var(--c-accent); text-decoration: none; }
.nav__link.is-current { color: var(--c-accent); }

/* the two action links, top right */
.nav__actions {
  display: flex;
  align-items: center;
  gap: .625rem;
}

.btn {
  display: inline-block;
  padding: .6rem 1.35rem;
  border: 2px solid var(--c-accent);
  border-radius: var(--radius);
  font-weight: 700;
  font-size: .9rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color .18s var(--ease), color .18s var(--ease);
}

.btn--solid { background: var(--c-accent); color: var(--c-on-dark); }
.btn--solid:hover, .btn--solid:focus-visible {
  background: var(--c-accent-dk); border-color: var(--c-accent-dk);
  color: var(--c-on-dark); text-decoration: none;
}

.btn--ghost { background: transparent; color: var(--c-accent); }
.btn--ghost:hover, .btn--ghost:focus-visible {
  background: var(--c-accent); color: var(--c-on-dark); text-decoration: none;
}

/* 5. HERO — title over a background image that scrolls behind the content
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  display: flex;
  align-items: center;
  min-height: calc(100vh - 72px);
  padding: clamp(4rem, 12vh, 8rem) 0;
  overflow: hidden;
  color: var(--c-on-dark);
  text-align: center;
}

/* Separate layer so the images can be fixed (parallax) without the overlay
   or text inheriting it. This element only holds the scrim and the fallback
   colour; the photos themselves are the .hero__slide children. */
.hero__bg {
  position: absolute;
  inset: 0;
  background-color: var(--c-ink); /* fallback before/without an image */
  z-index: 0;
}

/* One stacked layer per photo. main.js crossfades .is-active from one to the
   next; every slide is identically positioned so the dissolve stays registered.
   The first slide ships with .is-active in the markup, so with JS off the hero
   is simply the single static photo it was before. */
.hero__slide {
  position: absolute;
  inset: 0;
  z-index: 0;
  opacity: 0;
  background-size: cover;
  background-position: center 30%;
  background-repeat: no-repeat;
  background-attachment: fixed;   /* the scroll effect */
  transition: opacity var(--hero-fade) var(--ease);
}

.hero__slide.is-active { opacity: 1; }

/* the only per-photo rules in the file — the paths live in section 1 */
.hero__slide--1 { background-image: var(--hero-image-1); }
.hero__slide--2 { background-image: var(--hero-image-2); }
.hero__slide--3 { background-image: var(--hero-image-3); }
.hero__slide--4 { background-image: var(--hero-image-4); }

.hero__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;                     /* scrim rides above every slide */
  background: linear-gradient(
    to bottom,
    var(--c-overlay) 0%,
    rgba(0, 0, 0, .35) 45%,
    var(--c-overlay) 100%
  );
}

.hero .wrap { position: relative; z-index: 1; }

.hero__eyebrow {
  display: inline-block;
  margin-bottom: 1.25rem;
  padding: .4rem 1rem;
  border: 1px solid rgba(255, 255, 255, .45);
  border-radius: var(--radius);
  font-size: .8rem;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
}

.hero__title {
  margin: 0;
  text-shadow: 0 2px 24px rgba(0, 0, 0, .45);
}

.hero__sub {
  max-width: 46ch;
  margin: 1.25rem auto 0;
  font-size: clamp(1.05rem, 2vw, 1.35rem);
  text-shadow: 0 1px 12px rgba(0, 0, 0, .5);
}

/* 6. SECTIONS — page shell for interior pages
   -------------------------------------------------------------------------- */
.page-header {
  padding: clamp(3rem, 8vw, 5rem) 0 clamp(2rem, 5vw, 3rem);
  background: var(--c-paper-alt);
  border-bottom: 1px solid var(--c-line);
  text-align: center;
}

.placeholder {
  padding: clamp(3rem, 10vw, 6rem) 0;
  text-align: center;
  color: var(--c-ink-soft);
}

/* Three-up photo row (meet-dan.html). Each cell is a <figure>: the dashed
   .photo__frame is the stand-in, and dropping a real photo in means swapping
   that one div for <img class="photo__img" src alt> — the figure, the caption
   and the grid all stay put. Collapses to a single column in section 9. */
.photo-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1rem, 3vw, 1.75rem);
}

/* The row sits under the bio on meet-dan.html; the gap is the row's own so the
   section keeps its normal padding. */
.photo-row--below { margin-top: clamp(2.5rem, 6vw, 4rem); }

.photo { margin: 0; }

/* frame and photo share the ratio so swapping one for the other doesn't
   reflow the page around it */
.photo__frame,
.photo__img {
  aspect-ratio: 4 / 3;
  border-radius: var(--radius);
}

.photo__frame {
  display: grid;
  place-items: center;
  padding: var(--pad);
  background: var(--c-paper-alt);
  border: 2px dashed var(--c-line);
  text-align: center;
}

.photo__img { width: 100%; object-fit: cover; }

.photo__note {
  font-size: .8rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--c-ink-soft);
}

.photo__caption {
  margin-top: .75rem;
  font-size: .9rem;
  line-height: 1.5;
  color: var(--c-ink-soft);
}

/* Life-story chapters. UNUSED since meet-dan.html became a single bio blurb
   plus a photo row — kept as a ready-made slot, like .placeholder/.textbox, for
   a page that wants copy and a photo side by side. One chapter is a heading, its
   copy and one photo, side by side; the chapters run in chronological order and alternate
   which side the photo sits on. The copy always comes FIRST in the markup and
   .story--flip moves the figure with `order`, so the reading order stays
   heading-then-photo however the chapter is arranged. Photos reuse
   .photo/.photo__frame above, so the stand-in swaps to an <img> the same way
   here as in a photo row. Collapses to one column in section 9. */
.story {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1.5rem, 5vw, 3.5rem);
  align-items: center;
}

.story--flip .story__figure { order: -1; }

.story__copy > :first-child { margin-top: 0; }

/* Prose box for body copy. Deliberately the same card treatment as .issue
   (paper face, hairline, shadow) so the two pages read as one site; it sits
   on a .section--alt ground, which is what makes the card face visible. */
.textbox {
  padding: clamp(1.5rem, 4vw, 2.5rem);
  background: var(--c-paper);
  border: 1px solid var(--c-line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.textbox > :first-child { margin-top: 0; }

/* 7a. ISSUES SECTION BACKDROP — faint billowing flag
   -------------------------------------------------------------------------- */
#issues { position: relative; overflow: hidden; }

/* The flag spans the section at its FULLY-EXPANDED height, measured once by
   main.js into --flag-h. Fixing the box to that height is what keeps the
   stutter away: a panel opening changes the section's height, but the flag's
   own box never moves, so the vector is rasterized once instead of every
   frame. #issues has overflow:hidden, so the excess is clipped while panels
   are closed and the flag stays confined to this section.
   Falls back to 100% if JS never runs — with no JS there's no accordion, so
   the section height is static anyway. */
.issues-flag {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 0;
  width: 100%;
  height: var(--flag-h, 100%);
  background: var(--flag-image) center center / 100% 100% no-repeat;
  opacity: var(--flag-opacity);
  pointer-events: none;
  transform: translateZ(0);   /* own compositor layer: composited, not repainted */
}

/* transitions off while main.js measures the expanded height */
#issues.is-measuring,
#issues.is-measuring * { transition: none !important; }

#issues > .wrap { position: relative; z-index: 1; }


/* 7. ISSUES ACCORDION
   --------------------------------------------------------------------------
   Closed: header + short summary visible.
   Open:   summary fades/collapses out, full blurb expands in its place.
   Height animation uses the grid 0fr -> 1fr trick so no max-height guessing.
   -------------------------------------------------------------------------- */
.issues { display: grid; gap: 1rem; }

.issue {
  background: var(--c-paper);
  border: 1px solid var(--c-line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease);
}

.issue.is-open { border-color: var(--c-accent); }

.issue__toggle {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.5rem;
  width: 100%;
  margin: 0;
  padding: 1.5rem clamp(1.25rem, 3vw, 2rem);
  background: none;
  border: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  transition: padding-bottom .3s var(--ease);
}

/* Open: the summary has collapsed away, so the toggle's bottom padding is the
   only thing left between the title and the blurb. Pull it in tight. */
.issue.is-open .issue__toggle { padding-bottom: .5rem; }

.issue__toggle:hover .issue__title { color: var(--c-accent); }

.issue__heading { flex: 1 1 auto; min-width: 0; }

.issue__title {
  display: block;
  margin: 0;
  font-family: var(--font-head);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.01em;
  font-size: clamp(1.15rem, 2.2vw, 1.45rem);
  transition: color .18s var(--ease);
}

/* short summary — visible only when closed */
.issue__summary {
  display: block;
  margin: .5rem 0 0;
  color: var(--c-ink-soft);
  opacity: 1;
  max-height: 6rem;
  transition: opacity .22s var(--ease),
              max-height .3s var(--ease),
              margin .3s var(--ease);
}

.issue.is-open .issue__summary {
  opacity: 0;
  max-height: 0;
  margin-top: 0;
  overflow: hidden;
  pointer-events: none;
}

/* +/- indicator */
.issue__icon {
  position: relative;
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  margin-top: .25rem;
  border: 2px solid var(--c-accent);
  border-radius: 50%;
  transition: background-color .2s var(--ease), transform .3s var(--ease);
}

.issue__icon::before,
.issue__icon::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 12px;
  height: 2px;
  background: var(--c-accent);
  transform: translate(-50%, -50%);
  transition: transform .3s var(--ease), background-color .2s var(--ease);
}
.issue__icon::after { transform: translate(-50%, -50%) rotate(90deg); }

.issue.is-open .issue__icon { background: var(--c-accent); transform: rotate(180deg); }
.issue.is-open .issue__icon::before,
.issue.is-open .issue__icon::after { background: var(--c-on-dark); }
.issue.is-open .issue__icon::after { transform: translate(-50%, -50%) rotate(0deg); }

/* full blurb — collapsed to zero height when closed */
.issue__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .34s var(--ease);
}

.issue.is-open .issue__panel { grid-template-rows: 1fr; }

.issue__panel-inner { overflow: hidden; }

.issue__body {
  padding: 0 clamp(1.25rem, 3vw, 2rem) 1.75rem;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity .28s var(--ease) .06s, transform .28s var(--ease) .06s;
}

.issue.is-open .issue__body { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .issue, .issue *, .btn { transition: none !important; }
  /* main.js also stops advancing the hero, so this only kills the first fade */
  .hero__slide { transition: none !important; }
}

/* 8. FOOTER / PAID-FOR
   -------------------------------------------------------------------------- */
.site-footer {
  background: var(--c-ink);
  color: var(--c-on-dark);
  padding: 2.25rem 0;
}

.site-footer a { color: var(--c-on-dark); }
.site-footer a:hover { color: var(--c-on-dark); text-decoration: underline; }

/* The footer disclosure block: paid-for line first, then the lines carried over
   from osbornforsenate.com's own footer. The container only centers and bounds
   the measure — the box is on .paid-for alone. */
.disclosure {
  max-width: 34rem;
  margin: 0 auto;
  text-align: center;
}

/* Only the legally required line is boxed, in white so the frame reads as a
   deliberate notice against the ink footer. --c-on-dark, not a new literal. */
.paid-for {
  display: inline-block;
  margin: 0 0 1.25rem;
  padding: .6rem 1.15rem;
  border: 2px solid var(--c-on-dark);
  border-radius: var(--radius);
  text-align: center;
  font-size: .8rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--c-on-dark);
}

/* Committee name and mailing address. <address> is the right element here;
   kill the UA italic. */
.disclosure__address {
  margin: 0 0 1rem;
  font-style: normal;
  font-size: .78rem;
  line-height: 1.6;
  letter-spacing: .03em;
}

/* The Navy rank disclaimer. Uppercased in CSS, not in the markup, so the source
   stays readable — the same split .paid-for already uses. */
.disclosure__note {
  margin: 0 0 1rem;
  font-size: .68rem;
  line-height: 1.5;
  letter-spacing: .05em;
  text-transform: uppercase;
}

.disclosure__copyright {
  margin: 0;
  font-size: .72rem;
  letter-spacing: .03em;
}

.disclosure__address,
.disclosure__note,
.disclosure__copyright { color: rgba(255, 255, 255, .7); }

/* 9. RESPONSIVE
   -------------------------------------------------------------------------- */
@media (max-width: 860px) {
  /* Two columns leave the prose at an unreadable measure well before the photo
     row needs to collapse, so the chapters stack earlier — and `order` is reset
     with them, so every chapter stacks the same way round: heading, copy, photo. */
  .story { grid-template-columns: 1fr; }
  .story--flip .story__figure { order: 0; }
  .site-header__inner { flex-wrap: wrap; row-gap: .75rem; }
  .nav { width: 100%; justify-content: space-between; gap: 1rem; }
  .nav__links { gap: 1.1rem; }
  .btn { padding: .5rem 1rem; font-size: .8rem; }
}

@media (max-width: 640px) {
  /* stacked, the column gap would leave a caption sitting as close to the
     NEXT frame as to its own — open the row gap so the pairing stays obvious */
  .photo-row { grid-template-columns: 1fr; row-gap: 2.5rem; }
  .hero { min-height: 78vh; text-align: center; }
  /* iOS ignores fixed attachment; scroll keeps the image from zooming oddly */
  .hero__slide { background-attachment: scroll; }
  .nav__links { font-size: .9rem; }
}
