/* ==========================================================================
   Base element styles.
   Loaded after tokens.css, which defines everything referenced here.
   ========================================================================== */

/* --- Focus ---------------------------------------------------------------
   Kadence suppresses the focus ring via a body class; inc/accessibility.php
   removes that class, so these need no !important and stay overridable.

   :focus-visible rather than :focus, so the ring appears for keyboard and
   assistive-tech users without firing on every mouse click.

   The ring is drawn twice: a coloured outline plus a contrasting halo, so it
   stays visible over photography and over the Aubergine and Umber sections
   where a single dark ring would disappear. Measured against WCAG 2.4.11's
   3:1 minimum for focus indicators:
       Aubergine ring on white   10.92:1
       Ochre ring on Umber        9.91:1
       Ochre ring on Aubergine    5.59:1
   -------------------------------------------------------------------------- */
:root {
  --gsjc-focus-ring: var(--gsjc-aubergine);
  --gsjc-focus-halo: var(--gsjc-white);
}

:focus-visible {
  outline: 2px solid var(--gsjc-focus-ring);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px var(--gsjc-focus-halo);
  border-radius: 1px;
}

/* The bare :focus-visible above is specificity (0,1,0) — low enough that almost
   any plugin rule outranks it, and an accessibility guarantee should not be
   that easy to lose. Repeating it per interactive element raises it to (0,1,1),
   which holds against ordinary theme and plugin styling. Verified against
   Kadence 1.5.2, whose only competing focus rule is .screen-reader-text:focus
   on the skip link. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[role="button"]:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--gsjc-focus-ring);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px var(--gsjc-focus-halo);
  border-radius: 1px;
}

/* Dark grounds flip the ring rather than losing it. Any section that sets a
   dark background should carry one of these classes. */
.gsjc-on-dark,
.has-gsjc-aubergine-background-color,
.has-gsjc-umber-background-color {
  --gsjc-focus-ring: var(--gsjc-ochre);
  --gsjc-focus-halo: var(--gsjc-umber);
}

/* Never remove the ring — only restyle it. Kept as a standing reminder next to
   the rule most likely to tempt someone into `outline: none`. */

/* --- Typography defaults -------------------------------------------------- */
body {
  font-family: var(--gsjc-font-body);
  font-size: var(--gsjc-fs-body);
  line-height: var(--gsjc-lh-body);
  letter-spacing: var(--gsjc-track-body);
  color: var(--gsjc-ink);
}

h1, h2, h3, h4, h5, h6,
.entry-title {
  font-family: var(--gsjc-font-head);
  font-weight: var(--gsjc-weight-head);
  line-height: var(--gsjc-lh-head);
  letter-spacing: var(--gsjc-track-head);
}

h1 { font-size: var(--gsjc-fs-h1); }
h2 { font-size: var(--gsjc-fs-h2); }
h3 { font-size: var(--gsjc-fs-h3); }
h4 { font-size: var(--gsjc-fs-h4); }

/* The guide's Highlight face: Besley Italic, for emphasising key words
   alongside Besley Medium. Used sparingly and never for a whole paragraph. */
.gsjc-highlight {
  font-family: var(--gsjc-font-head);
  font-style: italic;
  font-weight: var(--gsjc-weight-head);
  letter-spacing: var(--gsjc-track-head);
}

/* Menu labels are stored sentence case so screen readers and editors both get
   readable text; the uppercase is presentational only. */
.gsjc-uppercase,
.main-navigation .menu > li > a,
.secondary-navigation .menu > li > a {
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* --- Full-bleed sections --------------------------------------------------
   Breaks a section out of the content container to both viewport edges.

   --gsjc-vw is the LAYOUT width: the viewport minus the classic scrollbar.
   It is set from JS in inc/enqueue.php because CSS cannot express it — 100vw
   includes the scrollbar, and there is no unit that excludes it. Getting this
   wrong is not a scrollbar of its own; it is a 7px LEFT SHIFT. A section
   15px too wide is centred on the window rather than on the layout box, so it
   starts half a scrollbar left of the content column, and every heading inside
   it lands 7px left of the headings above and below. Measured on this site at
   768px: bleeding sections at left:-7 with their text at x=17, against x=24
   for the season grid.

   This was invisible for a long time because the earlier rule keyed on
   --global-vw, which Kadence does NOT publish here (verified: unset on the
   root element), so the 100vw fallback was always what ran — and every check
   was made in a pane using overlay scrollbars, where the scrollbar is 0px wide
   and the bug cannot appear. It is visible to any visitor with classic
   scrollbars, which is most of Windows.

   100vw remains the fallback, so with JS off the layout is what it was before
   rather than broken.

   The two rules below close the gap Kadence leaves above and below the content
   area, but ONLY when a bleeding section is genuinely first or last — every
   other page keeps its spacing, and a browser without :has() simply keeps the
   margin, which is a safe way to fail. The mockup has these bands meeting the
   header and the footer with a single pixel between them. */
.gsjc-bleed {
  width: var(--gsjc-vw, 100vw);
  margin-left: calc(50% - (var(--gsjc-vw, 100vw) / 2));
}

.content-area:has(.entry-content > .gsjc-bleed:first-child),
.content-area:has(.gsjc-concert > .gsjc-bleed:first-child),
.content-area:has(.gsjc-person > .gsjc-bleed:first-child)    { margin-top: 0; }
.content-area:has(.entry-content > .gsjc-bleed:last-child)  { margin-bottom: 0; }

/* --- Narrow pages, left-aligned ---------------------------------------------
   A page whose Content Width is set to Narrow in the editor sidebar (Kadence
   panel → Content Width) gets a reading-width column. That is Kadence's own
   setting and its own per-page control: an editor can see it, flip it, and
   the canvas edits narrow. The width is one Customizer number, published as
   --global-content-narrow-width (760px, about 75 characters at 18px).

   Two things Kadence does with it are changed here, and only these two:

   1. Kadence narrows the whole container and centres it, so a narrow column
      sits a third of the way across the page while the logo, the nav and
      every band title start at the left edge. The designer asked for the
      column left-aligned. So the container keeps its normal width and each
      block inside is capped instead — same left edge as everything else.

   2. A full-bleed band computes its position from its parent's centre, so it
      is left out of the cap and keeps working on a narrow page (Sing With Us
      and Buy Tickets both carry one). Wide and full blocks are left out for
      the same reason; Kadence's -80px alignwide margins are reset, because
      an alignwide block on a full-width container already has its width.

   The editor canvas shows the narrow column centred (Kadence's own editor
   styles); the front end shows it left. That is the one mismatch, and it is
   position, not content. docs/kadence-settings.md records it. */
.content-width-narrow .content-container.site-container {
  max-width: var(--global-content-width);
}

.content-width-narrow .entry-content > :not(.gsjc-bleed):not(.alignfull):not(.alignwide):not(.gsjc-with-form) {
  max-width: var(--global-content-narrow-width);
}

.content-width-narrow .entry-content .alignwide,
.content-width-narrow .content-area .alignwide {
  margin-left: 0;
  margin-right: 0;
}

/* --- Content beside a Zeffy form --------------------------------------------
   Used by a concert that sells through Zeffy and by any Page with a form set
   in its sidebar box: the content at reading width on the left, the form on
   the content's right edge. One definition, so the two cannot drift.

   The form column is 26rem: Zeffy lays a form out at about 400px and a wider
   frame only adds white either side. 1242 - 64 - 416 leaves 762 for the
   content, which the reading-width cap trims to 760. Top-aligned, not
   stretched: the frame has its own height. On a Narrow page the wrapper is
   exempt from the page's cap (above) and the body column carries it instead,
   so the form still reaches the right edge. */
.gsjc-with-form {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(20rem, 26rem);
  column-gap: var(--gsjc-space-2xl);
  align-items: start;
}

.gsjc-with-form__body {
  max-width: var(--global-content-narrow-width, 47.5rem);
}

/* The page-wide frame's 46rem cap (support.css) is for a form with a page
   to itself; here the grid track is the width. */
.gsjc-with-form__aside {
  max-width: none;
}

/* Under 900px the pair stacks — the theme's two-up threshold — with the
   form after the content. */
@media (max-width: 900px) {
  .gsjc-with-form {
    grid-template-columns: 1fr;
    row-gap: var(--gsjc-space-xl);
  }
}

/* --- The name list ----------------------------------------------------------
   Names, not prose: trustees on About Us, sponsors and donors on Support Us,
   soloists on a concert. One treatment, one class on the List block (or on
   the Columns block that holds several lists). The designer's note on the
   concert page was "style these like we do the board", which is the moment
   the two copies of this rule became one.

   No bullets: they imply that enumeration matters, and the indent fights the
   page's left edge. Two selector parts, because Kadence styles lists inside
   content with `.single-content ul` at (0,1,1) and a single class loses to
   it silently — dev/audit-specificity.py enforces this.

   Two forms: the class on a wrapper that holds several lists (the trustees'
   Columns block, the sponsors' Groups), or on the List block itself (a
   concert's soloists). The first deploy covered only the wrapper form and
   the soloists kept their bullets. */
.gsjc-namelist ul.wp-block-list,
ul.wp-block-list.gsjc-namelist {
  margin: 0;
  padding-left: 0;
  list-style: none;
  line-height: var(--gsjc-lh-body);
}

.gsjc-namelist li {
  margin: 0 0 var(--gsjc-space-2xs);
}

/* A name set in <strong> is Besley bold Aubergine with the role in body text
   beside it, as the About Us mockup sets the artistic team's captions.
   10.93:1 on white. The comma belongs to the name: it is inside the bold in
   the mockup, and splitting it off leaves it floating. A list whose names are
   not bolded — the sponsors — simply reads as plain lines. */
.gsjc-namelist li strong {
  font-family: var(--gsjc-font-head);
  font-weight: var(--gsjc-weight-bold);
  color: var(--gsjc-primary);
}

/* A linked name — a soloist's site or Instagram — keeps the name's own colour
   and shows it is a link by its underline, in the hairline ink so the bold
   name stays the thing you read. Hover and focus bring the line up to full
   ink. The editor's "open in new tab" toggle handles the target. */
.gsjc-namelist li strong a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--gsjc-line);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.14em;
  transition: text-decoration-color 0.18s var(--gsjc-ease);
}

.gsjc-namelist li strong a:hover,
.gsjc-namelist li strong a:focus-visible {
  text-decoration-color: currentColor;
}

/* Several lists in a Columns block: the block's 34px column gap becomes the
   ROW gap once the columns stack, punching an arbitrary hole between the
   names that happened to end one column and start the next. Only the row gap
   is reset; side by side the columns keep their gutter. */
@media (max-width: 767px) {
  .gsjc-namelist.wp-block-columns {
    row-gap: var(--gsjc-space-2xs);
  }
}

/* --- The button ----------------------------------------------------------
   ONE definition, three consumers. This treatment previously existed three
   times — the hero call to action, the concert ticket link, and core Button
   blocks — written out separately in three stylesheets. They had already
   drifted: the concert button used 0.7rem/1.5rem padding where the others used
   0.8rem/1.8rem, and only it declared a 44px minimum.

   CSS has no mixins, so "shared" means one rule with a selector list rather
   than a class every consumer must wear. That is what keeps the hero's and the
   concert page's own markup unchanged while still having a single source.

   Ochre with Umber text: 9.91:1. NEVER white on Ochre, which is 1.95:1 and the
   mistake this pairing exists to prevent.

   min-height is now on all three, not just the concert link. WCAG 2.5.5 asks
   44px of a touch target; these compute to 48. */
.gsjc-button,
.entry-content .wp-block-button__link,
.gsjc-hero .gsjc-hero__cta,
.gsjc-concert .gsjc-concert__tickets {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0.8rem 1.8rem;
  background: var(--gsjc-accent);
  color: var(--gsjc-umber);
  font-family: var(--gsjc-font-body);
  font-size: var(--gsjc-fs-small);
  font-weight: var(--gsjc-weight-caption);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  border-radius: var(--gsjc-radius-sm);
  transition: background-color 0.18s var(--gsjc-ease), color 0.18s var(--gsjc-ease);
}

/* One hover, where there were two. The hero previously inverted to white-on-
   Aubergine while the other two went Aubergine-on-white; both are legible, but
   a site should not have two answers to what a button does when you point at
   it. Aubergine with white text is 10.93:1. */
.gsjc-button:hover,
.gsjc-button:focus-visible,
.entry-content .wp-block-button__link:hover,
.entry-content .wp-block-button__link:focus-visible,
.gsjc-hero .gsjc-hero__cta:hover,
.gsjc-hero .gsjc-hero__cta:focus-visible,
.gsjc-concert .gsjc-concert__tickets:hover,
.gsjc-concert .gsjc-concert__tickets:focus-visible {
  background: var(--gsjc-primary);
  color: var(--gsjc-white);
}

/* --- Embedded third-party frames ------------------------------------------
   A Zeffy form and a Google Calendar are both someone else's page in an
   iframe, and both want the same treatment: the site's hairline so a white
   embed on a white page has an edge, the site's 2px corner, and no baseline
   gap. Shared here rather than written twice, for the same reason the button
   above is shared once — this is the second consumer, which is where a pattern
   either gets a home or starts drifting.

   Height and width stay local: they are the only things these two genuinely
   disagree about. */
.gsjc-zeffy-frame,
.gsjc-calendar {
  margin-block: var(--gsjc-space-lg);
  border: 1px solid var(--gsjc-line);
  border-radius: var(--gsjc-radius-sm);
  background: var(--gsjc-white);
  overflow: hidden;
}

.gsjc-zeffy-frame iframe,
.gsjc-calendar iframe {
  display: block;               /* an inline iframe adds a baseline descender gap */
  width: 100%;
  border: 0;
}

/* The calendar is the Member Portal's only styling, so it lives here rather
   than earning a stylesheet of its own for one rule. Google's Schedule view
   scrolls its own list, so the frame just needs a sensible height: a floor for
   short windows, scaling with the viewport, capped before it runs off a
   desktop screen. Replaces a hardcoded width="800" height="600". */
.gsjc-calendar iframe {
  height: clamp(28rem, 70vh, 44rem);
}
