/* BMDL PTSA brand overrides.
   The theme defines its palette as CSS custom properties on :root
   (themes/dot-org-hugo-theme/assets/scss/_variables.scss); overriding them
   here avoids forking the theme's SCSS.

   Brand colors, from brand/phoenix-mark.svg and brand/logo-wordmark-dark.svg:
     phoenix red  #cd2d2f  (primary)
     orange       #fcb527  (accent, from the wordmark flourish)

   The theme's --primary-* steps are NOT a lightness ramp -- it assigns them by
   role, and primary buttons (700) are deliberately brighter than body links
   (600). Values below are chosen per role, each meeting WCAG AA. Contrast
   ratios in comments are against white unless noted. */
:root {
  /* H2 headings; secondary + tertiary button backgrounds. 4.64:1 -- passes AA
     for white button text and comfortably for large heading text. */
  --primary-400: #d63a3c;

  /* Secondary/tertiary button hover. Must be darker than 400. 5.82:1 */
  --primary-500: #c02a2c;

  /* Body links. 6.22:1 -- deliberately darker than the brand red, since link
     text runs at body size where extra contrast matters. */
  --primary-600: #b8282a;

  /* PRIMARY button background -- the true brand red, on the most visible
     surface (the Join / Become a member CTAs). 5.23:1 with white text. */
  --primary-700: #cd2d2f;

  /* Primary button hover. 7.13:1 */
  --primary-800: #a82426;
}

/* The theme ties --footer-link-color-hover to --primary-400, but the footer
   background is --black. Brand red on black is only 4.01:1, which fails AA for
   normal text, and no single value satisfies both white-button and
   black-footer use (the luminance window is roughly [0.175, 0.183]).
   Decoupling it is the fix -- a light tint of the brand red, 9.80:1 on black. */
:root {
  --footer-link-color-hover: #f2999a;
}

/* Accent orange is for graphic elements only -- it is 1.78:1 on white, far
   below AA, so it must never carry text on a light background. It is 11.78:1
   on black, so it is safe in the footer. */
:root {
  --accent-orange: #fcb527;
}

/* Logo sizing.
   The theme caps the logo at 100x40px (mobile) / 130x50px (desktop) via
   object-fit: contain. Those boxes are ~2.6:1, but the BMDL lockup is 8.48:1
   (121.06 x 14.27mm), so width binds and the logo renders just 15.3px tall in
   the 50px slot -- 31% of the available height, which is why it reads small
   next to the nav. Widening the width cap lets it use more of the header.
   Height caps are left alone so this can never overflow the 60/80px header. */
.header .logo {
  max-width: 190px;
}
@media (min-width: 1000px) {
  .header .logo {
    max-width: 240px; /* -> ~28px tall */
  }
}

/* Homepage hero.
   The theme splits a 2-column block 6/6 on a 12-column grid and sets H1 to 80px
   uppercase condensed on desktop, which stacked the headline about one word per
   line.

   Note the hero is NOT limited to --content-width: `.content > *` caps children
   at 895px, but `.content div` (higher specificity, both in _content.scss)
   resets it, so the columns block spans the full 1200px container.

   At 1200px an 8/4 split gives 788px of text and a 376px image column. 376px is
   just under the photo's natural 400px, so it fills the column exactly -- at
   7/5 the column was 479px and the 400px photo sat left with ~79px of dead
   space beside it. Filling via a slight downscale also looks sharper than
   upscaling a low-resolution source to fit.

   Scoped to body.page-home so other pages keep the theme's H1 scale. */
@media (min-width: 800px) {
  .page-home .columns-2 > :first-child {
    grid-column: span 8;
  }
  .page-home .columns-2 > :last-child {
    grid-column: span 4;
  }
  /* Center the photo against the text block rather than letting it sit at the
     top; the content column is taller. */
  .page-home .columns-2 {
    align-items: center;
  }
}

/* Tighten the hero-to-cards gap. The theme stacks .columns margin-bottom (40px),
   an author-inserted spacer, and .cards margin-top (40px). The spacer is gone
   from the markup; this trims the remaining 80px.

   The CTA band further down now supplies most of that separation with its own
   padding, and drops .cards margin-top to 8px to compensate -- so the gap this
   sets is measured from the hero to the *band edge*, not to the cards. */
.page-home .columns-2 {
  margin-bottom: 8px;
}
.page-home .columns-2 h1 {
  /* The middle term has to scale with the cap: at 3.8vw the 48px ceiling only
     engaged above a ~1260px viewport, so raising the cap alone would have
     changed nothing at a typical desktop width. 5vw hits 60px at 1200px. */
  font-size: clamp(36px, 5vw, 60px);
  line-height: 1.06;
}

/* The theme bundles Nunito and Oswald as latin-only woff2 subsets, so Chinese
   glyphs fall back to whatever the browser picks. Append system CJK faces to
   the stack for the zh-cn pages. */
:root:lang(zh-cn),
[lang="zh-cn"] {
  --rounded-font-family:
    "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial,
    "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC",
    "Source Han Sans SC", sans-serif;
  --condensed-font-family:
    "Oswald", "Impact", "Arial Black", "PingFang SC", "Hiragino Sans GB",
    "Microsoft YaHei", "Noto Sans CJK SC", "Source Han Sans SC", sans-serif;
}

/* ---------- Events ---------------------------------------------------------
   Used by /events/ and the home page summary. The theme has no list-with-
   metadata pattern to borrow, so these are local classes; colors come from the
   theme's palette variables rather than literals. */

.events + .events {
  margin-top: 48px;
}
.events__list {
  display: grid;
  gap: 12px;
}
/* A tinted block per event, so a stack of them reads as distinct rows.

   No left rule: in grey it read as a blockquote, and in accent orange it
   clashed with the orange ornament rule in the section heading right above it.
   The tint alone does the separating.

   It is a lighter mix of the CTA band's wash rather than a neutral grey, so the
   two tinted areas on the home page belong to the same palette, and light
   enough that the copy on it keeps its normal contrast. */
:root {
  --event-background: #faf6f5;
}
.event {
  background: var(--event-background);
  border-radius: 8px;
  padding: 14px 16px;
}
.event__title {
  margin: 0 0 4px;
}
.event__meta {
  margin: 0;
  color: var(--gray-800);
  font-size: 0.9rem;
}
/* Location sits after the date on one line at desktop width, its own line when
   there is not room. The separator is a pseudo-element so it disappears with
   the wrap. */
.event__location::before {
  content: "·";
  margin: 0 0.5em;
}
@media (max-width: 600px) {
  .event__location {
    display: block;
  }
  .event__location::before {
    content: none;
  }
}
.event__summary {
  margin: 8px 0 0;
}
.events__empty {
  color: var(--gray-800);
}
.events__all {
  margin-top: 24px;
}

/* Event detail page */
.event-detail {
  margin: 0 0 32px;
}
.event-detail dt {
  color: var(--gray-800);
  font-size: 0.9rem;
  margin-top: 8px;
}
.event-detail dd {
  margin: 0;
}

/* Section separator: a centered label with a rule running out to both margins,
   after the pattern CNCF uses on cncf.io. The lines are pseudo-elements that
   flex to fill whatever the label leaves, so the label can be any length or
   language and stays centered. */
.section-rule {
  display: flex;
  align-items: center;
  gap: 24px;
  margin-bottom: 32px;
  font-family: var(--condensed-font-family);
  font-size: 1.05rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.section-rule::before,
.section-rule::after {
  content: "";
  flex: 1 1 0;
  height: 1px;
  /* Accent orange, echoing the ornament rule on the old site. Safe here where
     grey would not be a brand cue: the rule is decoration, and the 1.78:1
     contrast that bars orange from carrying text does not apply to it. The
     label itself stays dark. */
  background: var(--accent-orange);
}
.section-rule__mark {
  flex: 0 0 auto;
  width: 20px;
  height: auto;
}
/* The mark and the label are one unit, so they keep a tighter gap than the
   rules do. */
.section-rule__mark + span {
  margin-left: -14px;
}
/* Chinese has no letter case and letterspacing hurts CJK legibility, so the
   rules stay and the type treatment does not. */
[lang="zh-cn"] .section-rule {
  text-transform: none;
  letter-spacing: normal;
}

/* Event art. Committees hand over whatever they have -- a wide photo one month,
   a tall flyer the next -- and the two contexts want opposite things from that.
   Listings crop to a fixed landscape tile so a row of events reads as a row
   rather than a ragged stack. The event's own page never crops: a flyer is
   usually the only place some details appear, so it is shown whole. */
:root {
  --event-thumb-width: 200px;
  --event-thumb-ratio: 3 / 2;
}
.event__image,
.event-body__image {
  margin: 0;
}
.event--illustrated {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--event-thumb-width);
  gap: 20px;
  align-items: start;
}
.event__image img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: var(--event-thumb-ratio);
  object-fit: cover;
  /* Posters put the title at the top, so a tall image crops from the bottom
     rather than through the middle. On a landscape photo this is close enough
     to centered to not matter. */
  object-position: center top;
}
.event-body__image img {
  display: block;
  width: auto;
  height: auto;
  object-fit: contain;
}
.event-body--illustrated {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 32px;
  align-items: start;
}
.event-body__image img {
  max-width: 320px;
  max-height: 440px;
}
.event-body__text > :first-child {
  margin-top: 0;
}
@media (max-width: 700px) {
  .event--illustrated,
  .event-body--illustrated {
    grid-template-columns: minmax(0, 1fr);
  }
  /* Stacked, the art reads as an illustration of the text above it rather than
     a header, so it keeps its source order and just widens. */
  .event-body__image img {
    max-width: 100%;
    max-height: none;
  }
}

/* The theme caps every direct child of .content at --content-width (895px)
   while the container itself is 1200px. It exempts div and iframe but not
   section, so the events block -- and with it the rule flanking the heading --
   stopped short of the hero and cards stacked above it. */
.content > .events,
.content > .announcements {
  max-width: 100%;
}
/* Full-width is right for the rule, not for prose: a summary set across 1200px
   is a punishing line length. Cap the text, not the block. */
.event__summary {
  max-width: 68ch;
}

/* Full-bleed band behind the home page CTA row, to break the page into
   sections rather than one continuous column.

   The band is a box-shadow rather than a 100vw pseudo-element: 100vw includes
   the scrollbar, so that approach overflows by ~15px and adds a horizontal
   scrollbar on any desktop browser showing one. A spread shadow paints outside
   the box without affecting layout, and clip-path trims it vertically so it
   does not bleed into the hero above or the events below.

   Nothing sits directly on the tint -- the cards are white and carry all the
   text -- so it has no contrast obligations of its own. It is a wash of the
   brand red, warm enough not to read as gray next to the orange accent. */
:root {
  --band-background: #fbf4f2;
}
.page-home .cards {
  background: var(--band-background);
  box-shadow: 0 0 0 100vmax var(--band-background);
  clip-path: inset(0 -100vmax);
  /* Padding replaces most of the old margin: the band edge now does the
     separating, so the gap from hero to cards stays near the 48px this file
     tuned it to further up, measured through the band instead of empty page. */
  padding: 40px 0;
  margin-top: 8px;
  margin-bottom: 48px;
}

/* The theme sets `cursor: default` on menu parents at desktop widths, which was
   honest when they were href="#" toggles. The header.html override gives them
   their real URLs, so the cursor has to agree that they are links. Scoped to
   the theme's own $min-desktop breakpoint (1000px), which is where it applies
   the rule; below that the submenu opens on tap and nothing navigates. */
@media (min-width: 1000px) {
  /* Must carry .main-menu: the theme's rule is
     `.main-menu .menu-item-has-children > a`, so the bare descendant selector
     loses on specificity no matter how late it loads. */
  .main-menu .menu-item-has-children > a {
    cursor: pointer;
  }
}

/* Footer menu parents are links now (see the footer.html override). The theme
   styles every footer menu anchor at 13px/400, which would render a parent
   identically to its own children and erase the column heading. Restoring
   inherit keeps .top-menu-item's 15px/800 while the anchor stays an anchor. */
.footer__menu .top-menu-item a {
  font-size: inherit;
  font-weight: inherit;
}

/* Home page cards, rebuilt from the old site's four-icon row: title, then icon,
   then a line of copy, all centred, with the whole card as the click target.

   Icons ran about 250px on the old site and outweighed the calls to action they
   were labelling; at 48 they orient without competing.

   They stay the artwork's own grey. The band is a red tint already -- a second
   red element would compete with it rather than sit on it. If they ever should
   be branded, the PNGs are transparent, so `mask-image` plus `background-color`
   recolours them without new artwork. */
.page-home .card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
/* The theme pads cards 40px/24px, which is generous for a heading, an icon and
   one line. Trimmed so the row reads as a band of choices rather than three
   tall panels -- the old site's real problem was height, not content. */
.page-home .card {
  padding: 22px 20px;
  /* Clips the title bar's corners to the card's 10px radius. */
  overflow: hidden;
}

/* One variable so the title bar's colour is a one-line experiment. Brand red
   is the current answer; --gray-800 (#5f6367, 6.37:1 with white) is the calmer
   one, and reserves red for things you actually click. */
:root {
  --card-header-background: var(--primary-700);
}

/* The title is a filled bar across the top of the card rather than text inside
   it. Negative margins cancel the card's padding so it runs edge to edge, and
   align-self overrides the flex centring that would otherwise shrink it to the
   width of its own text.

   Brand red carries white text at 5.23:1 -- the same pairing this file already
   documents for primary buttons, which is where that value was checked. */
.page-home .card h4 {
  align-self: stretch;
  margin: -22px -20px 14px;
  padding: 11px 16px;
  background: var(--card-header-background);
}
.page-home .card h4 {
  color: var(--white);
}
.page-home .card__icon {
  display: block;
  margin: 2px 0 8px;
}
.page-home .card p:last-child {
  margin-bottom: 0;
}

/* The card CTA and "see all events" are the same kind of thing -- the link out
   of a block to the page behind it -- so they share a treatment rather than
   drifting into two similar-but-different sizes.

   The link is just the link: the card around it is not a click target. */
.page-home .card__cta a,
.events__all a {
  text-decoration: none;
  font-weight: 700;
  /* A step above the copy, not a heading -- enough that the eye lands on it
     after the sentence rather than treating it as another line of body text. */
  font-size: 1.05rem;
}
/* Underline on hover and on keyboard focus -- the arrow marks it as a link at
   rest, the underline confirms it is the thing under the cursor. */
.page-home .card__cta a:hover,
.page-home .card__cta a:focus-visible,
.events__all a:hover,
.events__all a:focus-visible {
  text-decoration: underline;
  text-underline-offset: 3px;
}
/* An arrow rather than a persistent underline: the link is already the only
   coloured text in the block, and the arrow suggests movement without adding a
   second underlined thing to a card that has none.

   inline-block keeps the hover underline off the arrow. text-decoration draws
   through descendants and cannot be switched off from inside, but it does not
   propagate into an atomic inline box, which is what inline-block makes this. */
.page-home .card__cta a::before,
.events__all a::before {
  content: "\2192";
  display: inline-block;
  margin-right: 6px;
}

/* Icon beside the copy once there is width for it, stacked and centred below.
   600px is the theme's own breakpoint for cards going 2-up (_columns.scss), so
   the switch lands where the cards change shape anyway rather than at a width
   picked here.

   Grid rather than flex: the title bar has to span both columns, which is one
   declaration in grid and a wrapper element in flex -- and a wrapper would mean
   a shortcode, since this content is authored as markdown. */
@media (min-width: 600px) {
  .page-home .card {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    /* Every card in a row is as tall as the tallest. The slack goes to the
       bottom rather than being centred: centring made each card's copy start at
       a different height, since only the middle one runs to three lines, and
       the icons drifted with it. Top-aligned, the icons line up across the row
       and the ragged edge is the one place it does not show -- inside a white
       card with nothing under it. */
    /* Bar, then body, then the CTA pinned to the bottom: the middle row takes
       the slack so icon and copy stay at the top of the body while the CTAs
       line up across the row regardless of how long each card's copy runs. */
    grid-template-rows: auto 1fr auto;
    align-items: start;
    column-gap: 14px;
    text-align: left;
  }
  .page-home .card h4 {
    grid-column: 1 / -1;
    /* The bar stays centred even though the body below it is not; it reads as a
       label for the whole card rather than the first line of the text. */
    text-align: center;
  }
  /* The copy keeps the theme's paragraph top margin, which in a side-by-side
     row reads as the text hanging below the icon rather than starting level
     with it. Both cells start at the top of the row. */
  .page-home .card p {
    margin-top: 0;
  }
  /* Sits under the copy rather than under the icon, which is where grid
     auto-placement would otherwise drop it. */
  .page-home .card__cta {
    grid-column: 2;
    margin: 14px 0 0;
  }
  /* The icon is wrapped in a <p> by markdownify, so the grid child is that
     paragraph, not the image. */
  .page-home .card p:has(> .card__icon) {
    /* 3px of optical correction: the icon's box starts at its very top edge
       while the text's starts above the cap height, so a strict top alignment
       reads as the icon sitting high. */
    margin: 3px 0 0;
  }
}

/* ---------- Announcements --------------------------------------------------
   A strip between the hero and the CTA cards: short, promotional, short-lived.

   Styled as a promotion, not an alert. These say "spirit wear is here", not
   "school is closed" -- so it borrows the accent bar (free now that the events
   no longer use one) rather than the red-and-loud treatment an emergency
   notice would want. If a real alert is ever needed, it should look different
   from this, not louder than it. */
:root {
  --announcement-background: #fdf6ec;
  --announcement-accent: var(--accent-orange);
}
.announcements {
  display: grid;
  gap: 12px;
  margin: 32px 0;
}
.announcement {
  background: var(--announcement-background);
  border-left: 4px solid var(--announcement-accent);
  border-radius: 0 8px 8px 0;
  padding: 16px 20px;
}
.announcement__title {
  margin: 0 0 4px;
  font-size: 1.25rem;
}
.announcement__text p {
  margin: 0;
  /* The strip spans the full container, but the sentence inside it should not:
     a line of prose set across 1200px is a punishing measure. Same split the
     events use -- full-width block, capped text. */
  max-width: 72ch;
}
.announcement__cta {
  margin: 8px 0 0;
}
/* The strip's link gets the same treatment as the card CTAs and "see all
   events" -- same job, same look. */
.announcement__cta a {
  text-decoration: none;
  font-weight: 700;
}
.announcement__cta a::before {
  content: "\2192";
  display: inline-block;
  margin-right: 6px;
}
.announcement__cta a:hover,
.announcement__cta a:focus-visible {
  text-decoration: underline;
  text-underline-offset: 3px;
}
/* Text and link side by side once there is room, so a one-line announcement
   stays one line tall. */
@media (min-width: 700px) {
  .announcement {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    column-gap: 24px;
  }
  .announcement__cta {
    margin: 0;
    white-space: nowrap;
  }
}

/* ---------- Footer affiliations --------------------------------------------
   Who the PTSA belongs to, plus the partner marks, above the copyright rule. */
.affiliations {
  display: grid;
  gap: 24px;
  margin-top: 48px;
}
.affiliations__text p {
  margin: 0 0 8px;
  /* Two dense factual sentences; the footer's body size is generous for them
     and the copyright line below already runs at this size. */
  font-size: 0.9rem;
  max-width: 70ch;
}
.affiliations__logos {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 24px;
}
.affiliations__logos img {
  display: block;
  height: auto;
}
/* The Bellevue council lockup ships with an opaque white panel baked into the
   artwork, so on the dark footer it reads as a white card rather than a logo.
   Padding turns that into a deliberate-looking plate instead of a raw edge. */
.affiliations__logos li:nth-child(2) img {
  background: var(--white);
  border-radius: 4px;
  padding: 6px 8px;
}
@media (min-width: 900px) {
  .affiliations {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 40px;
  }
}

/* ---------- Environment banner ---------------------------------------------
   Names the build on every page of a preview or local site. Never renders in
   production (params.show_env_banner, false by default).

   Deliberately unlovely: accent orange with near-black text reads as a system
   notice rather than site furniture, so nobody mistakes it for a design
   element or, worse, stops seeing it. It scrolls away with the page rather
   than sticking -- it needs to be noticed once, not to cost vertical space on
   every screen. 10.6:1 on the orange, comfortably past AA. */
.env-banner {
  background: var(--accent-orange);
  color: #1a1a1a;
  padding: 8px 16px;
  text-align: center;
  font-size: 0.85rem;
  letter-spacing: 0.02em;
}
.env-banner__env {
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-right: 4px;
}
/* The link inherits the banner's near-black rather than the brand red, which
   would be 3.4:1 on orange and fails AA. Underlined so it still reads as a
   link without relying on colour alone. */
.env-banner__live {
  margin-left: 4px;
}
.env-banner__live a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
  font-weight: 700;
}

/* ---------- 404 -------------------------------------------------------------
   Someone here wanted something specific, so the search field is the primary
   affordance rather than the list of links. */
.notfound__search {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 24px 0;
}
.notfound__search label {
  flex: 0 0 100%;
  font-weight: 700;
}
.notfound__search input {
  flex: 1 1 260px;
  padding: 10px 12px;
  border: 2px solid var(--gray-300);
  border-radius: 8px;
  font: inherit;
}
.notfound__search input:focus-visible {
  outline: 2px solid var(--primary-600);
  outline-offset: 1px;
}
.notfound__elsewhere {
  margin-bottom: 8px;
}
.notfound__links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 24px;
}
.notfound__other-language {
  margin-top: 32px;
  padding-top: 16px;
  border-top: 1px solid var(--gray-300);
}
/* Hugo titles the 404 page "404 Page not found" and the theme prints it as the
   h1 in English on every language. The template renders a translated heading
   instead; this hides the untranslatable one. */
.page-404 .title {
  display: none;
}
.notfound__title {
  margin-top: 0;
}
