/*
 * ACAD1 Review Center — components
 * child-theme-guide.md §4 "Buttons" / "Cards" / "Tags" / "Tables" / "Forms",
 * verbatim, with token substitutions for the guide's inline literals (see
 * 00-tokens.css pre-flight block):
 *
 *   guide's dark-active literal    -> var(--a1-accent-dk)   (.a1-btn--primary:active)
 *   guide's invalid-bg literal     -> var(--a1-invalid-bg)  (.a1-input[aria-invalid="true"])
 *
 * Plus two additions the guide describes but does not fence in code:
 *   - .a1-table--schedule th:nth-child(n) column widths, expressed on the
 *     <th> rather than a <colgroup> per the task's ambiguity resolution.
 *   - .a1-choice, the radio/checkbox card wrapper described in prose at the
 *     end of §4. Its 15px padding has no exact token match; the nearest
 *     token, --a1-s-4 (16px), is used instead (see task-2-report.md).
 */

/* ── Buttons ─────────────────────────────────────────────────────────── */
.a1-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font: inherit; font-weight: 700; font-size: var(--a1-body-sm);
  padding: 13px 22px; min-height: var(--a1-target-min);
  border: 1px solid transparent; border-radius: var(--a1-r-btn);
  text-decoration: none; cursor: pointer; transition: background .15s, color .15s;
}
.a1-btn--primary { background: var(--a1-accent); color: var(--a1-contrast); }
.a1-btn--primary:hover  { background: var(--a1-accent-lt); color: var(--a1-contrast); }
.a1-btn--primary:active { background: var(--a1-accent-dk); }

.a1-btn--secondary { border-color: var(--a1-primary); color: var(--a1-primary); background: transparent; }
.a1-btn--secondary:hover { background: var(--a1-surface); }

.a1-btn--onaccent { background: var(--a1-contrast); color: var(--a1-accent); }
.a1-btn--ondark   { border-color: var(--a1-on-accent-border); color: var(--a1-contrast); }

.a1-btn--lg    { font-size: 15.5px; padding: 15px 30px; }
.a1-btn--block { width: 100%; }
.a1-btn:disabled, .a1-btn[aria-disabled="true"] {
  background: var(--a1-disabled-bg); color: var(--a1-disabled-fg); cursor: not-allowed; border-color: transparent;
}

/* ── Cards ───────────────────────────────────────────────────────────── */
/* Cards never get a shadow at rest. Elevation (--a1-sh-*) is reserved for
   the mobile nav panel, the sticky bar and dialogs. */
.a1-card {
  background: var(--a1-bg); border: 1px solid var(--a1-border);
  border-radius: var(--a1-r-card); padding: var(--a1-s-6);
  display: flex; flex-direction: column; gap: var(--a1-s-3);
}
.a1-card--surface { background: var(--a1-surface); }
.a1-card--dark    { background: var(--a1-primary); color: var(--a1-on-dark); border-color: var(--a1-primary); }
/* Online Review Program, recommended tier. The accent sits on the TOP edge:
   a thick rule down one side collides with the card radius at both corners it
   touches, and this system uses that treatment nowhere else. */
.a1-card--feature { border-top: 3px solid var(--a1-accent); }
.a1-card__kicker  { font-size: var(--a1-kicker); font-weight: 700; letter-spacing: var(--a1-ls-kicker); text-transform: uppercase; color: var(--a1-accent); }
.a1-card__cta     { margin-top: auto; padding-top: var(--a1-s-4); font-size: var(--a1-meta); font-weight: 700; }

/* ── Tags ────────────────────────────────────────────────────────────── */
.a1-tag {
  display: inline-flex; align-items: center;
  font-size: 11.5px; font-weight: 600; padding: 5px 11px;
  border-radius: var(--a1-r-tag); background: var(--a1-surface); color: var(--a1-secondary);
}
.a1-tag--accent  { color: var(--a1-accent); font-weight: 700; }
.a1-tag--outline { background: transparent; border: 1px solid var(--a1-border-strong); }

/* ── Tables — the core component of this site ───────────────────────── */
.a1-table { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: 14px; }
.a1-table thead tr { background: var(--a1-primary); }
.a1-table th {
  text-align: left; padding: 13px 16px;
  font-size: var(--a1-kicker); font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--a1-contrast);
}
.a1-table td { padding: 14px 16px; border-bottom: 1px solid var(--a1-rule); }
.a1-table tbody { font-variant-numeric: tabular-nums; }
.a1-table tbody tr:nth-child(even) { background: var(--a1-surface); }
.a1-table tbody tr:last-child td { border-bottom: 0; }

.a1-table .is-num { text-align: right; font-weight: 700; white-space: nowrap; }
.a1-table .is-nowrap { white-space: nowrap; }
/* Featured row. Was a 3px accent rule on the first cell, which the rounded,
   overflow-hidden table wrapper clips on the first and last rows — so the
   marker appeared and disappeared depending on where the row fell. A tint
   reads the same in every position. */
.a1-table tbody tr.is-featured td { background: var(--a1-selection); }
.a1-table__wrap { background: var(--a1-bg); border: 1px solid var(--a1-border); border-radius: var(--a1-r-card); overflow: hidden; }

/* two-line schedule cell — day pattern over time range, uniform row heights */
/* `nowrap` here was protecting a day pattern ("Mon - Fri") from breaking
   mid-range. It also stopped anything LONGER from breaking, so a self-paced
   row — whose day field carries a delivery descriptor rather than a pattern —
   ran straight out of its column and over the fee beside it. The label wraps;
   only the time range, which must never break mid-range, still does not. */
.a1-sched__days { font-weight: 600; color: var(--a1-text); white-space: normal; overflow-wrap: anywhere; }
.a1-sched__time { font-size: 13px; color: var(--a1-secondary); white-space: normal; overflow-wrap: anywhere; text-wrap: pretty; }
.a1-sched__time > time, .a1-table .is-nowrap { white-space: nowrap; }

/* Six-column schedule table widths (§4 table). table-layout: fixed above
   plus explicit <th> widths — no <colgroup>, some block renderers strip it. */
.a1-table--schedule th:nth-child(1) { width: 30%; } /* Programme & section */
.a1-table--schedule th:nth-child(2) { width: 12%; } /* Tier */
.a1-table--schedule th:nth-child(3) { width: 13%; } /* Dates */
.a1-table--schedule th:nth-child(4) { width: 21%; } /* Days & time */
.a1-table--schedule th:nth-child(5) { width: 12%; } /* Fee */
.a1-table--schedule th:nth-child(6) { width: 12%; } /* Action */

/* ── Forms ───────────────────────────────────────────────────────────── */
.a1-field { display: flex; flex-direction: column; gap: 7px; }
.a1-label {
  font-size: var(--a1-kicker); font-weight: 700; letter-spacing: var(--a1-ls-kicker);
  text-transform: uppercase; color: var(--a1-secondary);
}
.a1-input, .a1-select, .a1-textarea {
  width: 100%; font: inherit; font-size: var(--a1-body-sm);
  min-height: var(--a1-target-min); padding: 12px 13px;
  color: var(--a1-text); background: var(--a1-contrast);
  border: 1px solid var(--a1-border-strong); border-radius: var(--a1-r-input);
}
.a1-input:hover { border-color: var(--a1-secondary); }
.a1-input:focus-visible { border-color: var(--a1-accent); outline: 2px solid var(--a1-accent); outline-offset: 1px; }
.a1-textarea { min-height: 120px; resize: vertical; }
.a1-input[aria-invalid="true"] { border-color: var(--a1-accent); background: var(--a1-invalid-bg); }

input[type="radio"], input[type="checkbox"] { accent-color: var(--a1-accent); width: 17px; height: 17px; }

/* Radio/checkbox row wrapper: the whole row is the tap target (registration
   page). Described in prose at the end of §4, not fenced as code there. */
.a1-choice {
  display: flex; align-items: center; gap: var(--a1-s-3);
  min-height: var(--a1-target-min);
  background: var(--a1-bg); border: 1px solid var(--a1-border);
  border-radius: var(--a1-r-card); padding: var(--a1-s-4); /* nearest token to the guide's 15px */
  cursor: pointer;
}

/* ══════════════════════════════════════════════════════════════════════
 * Site chrome — Task 4 addition
 *
 * child-theme-guide.md §4's "Header / footer behaviour" subsection is
 * prose only (never fenced as a code block the way Buttons/Cards/Tags/
 * Tables/Forms were), so Tasks 1–2 never built these desktop base styles.
 * 50-responsive.css (Task 3) already ships the breakpoint overrides for
 * all of them, plus a purely structural (no colour/type) stopgap
 * declaration for several classes at the top of that file so the
 * responsive rules were never fully dead. This section is the real
 * desktop base those overrides depart from — colour, type and elevation
 * included, per §1's colour-usage rules and §4's prose. Any property
 * duplicated from 50-responsive.css's stopgap is intentional and
 * harmless: identical values, later file wins the cascade either way.
 *
 * Interactive elements below carry an explicit --a1-target-min min-height
 * per §7 ("48px minimum hit target site-wide, not just mobile"). Dark-ground
 * elements (.a1-header__utility, .a1-footer) use only the --a1-on-dark-*
 * alpha tokens per §1, and extend :focus-visible the same way 10-base.css's
 * dark/accent flip does, since neither is guaranteed to sit inside a
 * literal `.a1-dark` wrapper element. Both now flip to --a1-contrast, not
 * --a1-accent-lt: read the measured ratios in 10-base.css before changing
 * either back.
 * ══════════════════════════════════════════════════════════════════════ */

/* ── Header ──────────────────────────────────────────────────────────── */
/* §4: "utility bar (--a1-primary) over a white nav bar. Grid 200px 1fr auto." */
.a1-header {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr) auto;
  align-items: center;
  column-gap: var(--a1-s-4);
  background: var(--a1-contrast);
  padding-inline: var(--a1-gutter);
  min-height: var(--a1-s-11); /* 80px — reuses the existing space token, no new value */
  border-bottom: 1px solid var(--a1-border);
  /* anchors the ≤920px open mobile-nav panel (position: absolute) — see
     50-responsive.css's ≤920px block. No visible effect at desktop. */
  position: relative;
}

.a1-header__utility {
  display: flex; align-items: center; justify-content: flex-end;
  gap: var(--a1-s-5);
  padding-inline: var(--a1-gutter);
  font-size: var(--a1-meta);
  background: var(--a1-primary); color: var(--a1-on-dark);
}
.a1-header__utility a {
  display: inline-flex; align-items: center; min-height: var(--a1-target-min);
  color: var(--a1-on-dark-80); text-decoration: none;
}
.a1-header__utility a:hover { color: var(--a1-on-dark); }
.a1-header__utility :focus-visible { outline-color: var(--a1-contrast); } /* --a1-primary ground: --a1-accent-lt measures 2.96:1, below SC 1.4.11's 3:1 — see 10-base.css */

.a1-header__nav ul {
  display: flex; align-items: center; gap: var(--a1-s-6);
  list-style: none; margin: 0; padding: 0;
}
.a1-header__nav a {
  display: inline-flex; align-items: center; min-height: var(--a1-target-min);
  font-weight: 600; color: var(--a1-text); text-decoration: none;
}
.a1-header__nav a:hover { color: var(--a1-accent); }

.a1-header__cta { display: flex; align-items: center; }

/* Mobile nav: native <details>/<summary> per §4 — no JavaScript. Marker
   removal and the closed-by-default display are unconditional (not a
   responsive concern); 50-responsive.css's ≤920px block is the only place
   the toggle is ever made visible or opened. */
.a1-nav-toggle summary {
  display: none;
  list-style: none;
  cursor: pointer;
}
.a1-nav-toggle summary::-webkit-details-marker { display: none; }
.a1-nav-toggle summary::marker { content: ""; }

/* ── Sticky bottom bar ───────────────────────────────────────────────── */
/* §4: "Call + Enroll Now, 48px tall". Hidden by default — 50-responsive.css's
   ≤700px block is the only place it is shown (`display: flex`). One of the
   few components allowed elevation (§4: "Elevation is reserved for the
   mobile nav panel, the sticky bar and dialogs"). */
.a1-stickybar {
  display: none;
  align-items: stretch;
  position: fixed;
  inset-block-end: 0;
  inset-inline: 0;
  height: var(--a1-target-min);
  z-index: var(--a1-z-sticky-bar);
  background: var(--a1-contrast);
  border-top: 1px solid var(--a1-border);
  box-shadow: var(--a1-sh-lg);
}
.a1-stickybar > a,
.a1-stickybar > .a1-btn {
  flex: 1;
  min-height: var(--a1-target-min);
  border-radius: 0;
}

/* ── CTA band ────────────────────────────────────────────────────────── */
/* §6: "1fr auto CTA bands stack" at ≤900px. Structural only — used inside
   several different section backgrounds, so it carries no colour of its
   own (matches 50-responsive.css's existing unqueried declaration). */
.a1-cta-band {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--a1-s-5);
  align-items: center;
}

/* ── Footer ──────────────────────────────────────────────────────────── */
/* §4: "4 columns" at desktop; §1: dark panels (--a1-primary ground) carry
   the footer. 50-responsive.css owns the 4→2→1 column collapse (2 at
   1024px, 1 at 620px). */
.a1-footer {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--a1-s-8);
  background: var(--a1-primary);
  color: var(--a1-on-dark);
  padding-block: var(--a1-section-y);
}
.a1-footer a {
  display: inline-flex; align-items: center; min-height: var(--a1-target-min);
  color: var(--a1-on-dark-80); text-decoration: none;
}
.a1-footer a:hover { color: var(--a1-on-dark); }
.a1-footer :focus-visible { outline-color: var(--a1-contrast); } /* same --a1-primary ground as the utility bar — see 10-base.css */

.a1-footer__legal {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--a1-s-4);
  margin-top: var(--a1-s-8);
  padding-top: var(--a1-s-5);
  border-top: 1px solid var(--a1-on-dark-rule);
  font-size: var(--a1-meta);
  color: var(--a1-on-dark-70);
}

/* ── Horizontal chip / tab scrollers ─────────────────────────────────── */
/* §6: "Horizontal chip and tab rows (venue tabs, filter chips) get
   overflow-x: auto ... they scroll, they never squash." No venue-tab
   active-state spec exists in the guide beyond this, so kept minimal. */
.a1-chips,
.a1-tabs-scroll {
  display: flex;
  gap: var(--a1-s-2);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
/* Children carry --a1-target-min because they are the tap targets, not the
   scroller: a chip or venue tab is usually an .a1-tag, whose own padding
   lands it at roughly 28px — under §7's 48px floor and §12's
   definition-of-done. inline-flex + centring is what lets the extra height
   go around the label instead of above it. */
.a1-chips > *,
.a1-tabs-scroll > * {
  flex: none; white-space: nowrap;
  display: inline-flex; align-items: center;
  min-height: var(--a1-target-min);
}

/* ── Sticky rail utility ─────────────────────────────────────────────── */
/* §6 row 1: "Every position: sticky becomes static" at ≤1080px — the
   base sticky state those rails depart from. Matches the existing
   unqueried declaration in 50-responsive.css. */
.a1-sticky {
  position: sticky;
  top: var(--a1-s-5);
}

/* ── Partner-logo marquee ────────────────────────────────────────────── */
/* §7: must honour prefers-reduced-motion — 50-responsive.css already
   stops `.a1-marquee` and all its descendants under that query, so it is
   not duplicated here. This is the base scrolling behaviour it stops. */
.a1-marquee { overflow: hidden; }
.a1-marquee__track {
  display: flex;
  align-items: center;
  gap: var(--a1-s-8);
  width: max-content;
  animation: a1-marquee-scroll 30s linear infinite;
}
@keyframes a1-marquee-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* ---------------------------------------------------------------------------
 * Button colour, hardened against the parent theme
 * ---------------------------------------------------------------------------
 * GeneratePress emits `.entry-content a { color: … }` from its Customizer link
 * colour — specificity (0,1,1). A single-class `.a1-btn--primary` is (0,1,0)
 * and loses, so every primary button inside page content inherited GP's dark
 * link colour on the oxblood fill and became unreadable.
 *
 * Repeating the class raises these to (0,2,0), which beats (0,1,1) on class
 * count alone — no !important, which this layer forbids. `:visited` is listed
 * because browsers style visited links independently of the base rule.
 *
 * The real fix is also to align GP's Customizer palette to the token set; this
 * rule makes the buttons correct regardless of whether that happens.
 */
.a1-btn.a1-btn--primary,
.a1-btn.a1-btn--primary:visited { background: var(--a1-accent); color: var(--a1-contrast); }
.a1-btn.a1-btn--primary:hover,
.a1-btn.a1-btn--primary:focus  { background: var(--a1-accent-lt); color: var(--a1-contrast); }
.a1-btn.a1-btn--primary:active { background: var(--a1-accent-dk); color: var(--a1-contrast); }

.a1-btn.a1-btn--secondary,
.a1-btn.a1-btn--secondary:visited { color: var(--a1-primary); border-color: var(--a1-primary); }
.a1-btn.a1-btn--secondary:hover   { color: var(--a1-primary); background: var(--a1-surface); }

.a1-btn.a1-btn--onaccent,
.a1-btn.a1-btn--onaccent:visited { background: var(--a1-contrast); color: var(--a1-accent); }
.a1-btn.a1-btn--onaccent:hover   { background: var(--a1-contrast); color: var(--a1-accent-dk); }

.a1-btn.a1-btn--ondark,
.a1-btn.a1-btn--ondark:visited { color: var(--a1-contrast); border-color: var(--a1-on-accent-border); }
.a1-btn.a1-btn--ondark:hover   { color: var(--a1-contrast); background: rgba(0,0,0,0.12); } /* csscheck-allow: neutral scrim over an arbitrary ground, no token applies */

/* Any anchor sitting on an accent or dark band must never inherit GP's dark
 * link colour either. */
.a1-section--accent a:not(.a1-btn),
.a1-card--dark a:not(.a1-btn) { color: var(--a1-contrast); }
.a1-section--dark a:not(.a1-btn) { color: var(--a1-on-dark); }

/* ---------------------------------------------------------------------------
 * Header layout contract (authored against real markup)
 * ---------------------------------------------------------------------------
 * `.a1-header` IS the three-column nav row — not an outer wrapper. The utility
 * bar is a sibling above it, never a grid child, or it collapses into the
 * 200px logo track (observed: utility bar rendered 200px wide inside a 1440px
 * viewport before this was corrected).
 *
 * The desktop nav is a direct child of `.a1-header`, NOT inside <details>:
 * Chrome does not render a closed <details>'s children at all, so a nav placed
 * inside one cannot be revealed with CSS on desktop.
 */
.a1-header { align-items: center; gap: var(--a1-s-5); position: relative; }
.a1-header__utility { justify-content: space-between; }
.a1-header > .a1-header__nav { display: flex; gap: var(--a1-s-6); justify-content: center; flex-wrap: wrap; }
.a1-nav-toggle { display: none; }
.a1-header__nav-panel { display: flex; flex-direction: column; gap: var(--a1-s-4); }

/* Footer layout contract: `.a1-footer` IS the four-column row (spec §0), not
 * the outer wrapper. Column 1 is wider per the spec's 1.4fr. */
.a1-footer { grid-template-columns: 1.4fr minmax(0,1fr) minmax(0,1fr) minmax(0,1fr); gap: 40px; }
.a1-footer__legal { display: flex; }

/* ---------------------------------------------------------------------------
 * Sticky enrolment bar — hardened for real phones
 * ---------------------------------------------------------------------------
 * Fixes found by measuring the bar on a device rather than in a mockup:
 *
 * - `height` was fixed at the token value, so a 48px hit target plus padding
 *   overflowed its own container. `min-height` lets the bar grow instead.
 * - The elevation shadow pointed downward, i.e. off-screen, on an element
 *   pinned to the viewport floor. --a1-sh-up casts it upward where it reads.
 * - No safe-area inset, so on notched iPhones the home indicator sat on top
 *   of the buttons.
 * - `touch-action: manipulation` removes the 300ms tap delay; the tap
 *   highlight is cleared because the buttons already have their own :active.
 * - Border and shadow together read as two separate edges, so the border goes.
 */
.a1-stickybar {
  height: auto;
  min-height: var(--a1-stickybar-h);
  gap: var(--a1-s-2);
  padding: var(--a1-s-2);
  padding-bottom: calc(var(--a1-s-2) + env(safe-area-inset-bottom, 0px));
  background: var(--a1-contrast);
  border-top: 0;
  box-shadow: var(--a1-sh-up);
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.a1-stickybar > .a1-btn {
  flex: 1;
  min-height: var(--a1-target-min);
  border-radius: var(--a1-r-btn);
}

/* ---------------------------------------------------------------------------
 * Step indicator
 * ---------------------------------------------------------------------------
 * A grid rather than flex, so the three steps stay equal width and the 2px
 * gap can show the dark ground through as hairline rules — one border-radius
 * on the container with overflow:hidden clips all three cells, which avoids
 * per-cell corner rounding that never quite lines up.
 */
.a1-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 2px;
  background: var(--a1-on-dark-rule);
  border-radius: var(--a1-r-card);
  overflow: hidden;
}
.a1-steps > li {
  display: flex;
  align-items: center;
  gap: var(--a1-s-3);
  padding: var(--a1-s-4) var(--a1-s-5);
  min-height: var(--a1-target-min);
  color: var(--a1-on-dark-80);
  font-size: var(--a1-body-sm);
  font-weight: 600;
}
.a1-steps > li[aria-current] { background: var(--a1-bg); color: var(--a1-text); }
.a1-steps__n {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  flex: none;
  border: 1px solid var(--a1-on-dark-50);
  font-weight: 700;
  font-size: var(--a1-caption);
  font-variant-numeric: tabular-nums;
}
.a1-steps > li[aria-current] .a1-steps__n {
  background: var(--a1-accent);
  color: var(--a1-contrast);
  border-color: transparent;
}

/* Child selector to match the specificity of `.a1-stickybar > .a1-btn`
 * above, which otherwise wins and splits the bar 50/50 — flattening the
 * primary action to the same weight as its companion. */
.a1-stickybar > .a1-stickybar__call {
  flex: 0 0 auto;
  min-width: 52px;
  padding-inline: var(--a1-s-4);
}

/* Links on the footer's charcoal ground. `.a1-site-footer` is not
 * `.a1-section--dark`, so the on-dark link rule in 10-base.css never matched
 * here and links inherited the global accent — oxblood on charcoal is 1.92:1.
 * The footer ground is charcoal, so links take the on-dark ramp. */
.a1-site-footer a:not(.a1-btn),
.a1-footer a:not(.a1-btn),
.a1-footer__legal a:not(.a1-btn) { color: var(--a1-on-dark-80); }
.a1-site-footer a:not(.a1-btn):hover,
.a1-footer a:not(.a1-btn):hover,
.a1-footer__legal a:not(.a1-btn):hover { color: var(--a1-contrast); }
.a1-site-footer :focus-visible { outline-color: var(--a1-contrast); }

/* ---------------------------------------------------------------------------
 * Form controls, hardened against the parent theme
 * ---------------------------------------------------------------------------
 * GeneratePress styles fields with attribute selectors —
 * `input[type="text"], input[type="email"] { … }` — which is (0,1,1). The
 * `.a1-input` rule above is (0,1,0), so it lost on specificity rather than on
 * order, and every text field on the registration form was painted with GP's
 * Customizer form colours instead: #323F4B ground under #939393 text, which
 * measures 3.51:1 and fails AA for body text. `select` was not covered by those
 * selectors and stayed correct at 18.08:1 — so the same form showed a white
 * dropdown directly above a dark-on-dark text box.
 *
 * Repeating the class raises these to (0,2,0), which beats GP's attribute
 * selectors and its inline dynamic CSS alike. Same technique, and same reason,
 * as the .a1-btn--primary hardening below.
 */
.a1-input.a1-input,
.a1-select.a1-select,
.a1-textarea.a1-textarea {
  color: var(--a1-text);
  background: var(--a1-contrast);
  border: 1px solid var(--a1-border-strong);
}

/* opacity:1 because Firefox dims placeholders by default, which would undo the
   contrast this token was chosen for. */
.a1-input.a1-input::placeholder,
.a1-textarea.a1-textarea::placeholder { color: var(--a1-secondary); opacity: 1; }

.a1-input.a1-input:hover { border-color: var(--a1-secondary); }
.a1-input.a1-input:focus,
.a1-input.a1-input:focus-visible { border-color: var(--a1-accent); }
.a1-input.a1-input[aria-invalid="true"] { border-color: var(--a1-accent); background: var(--a1-invalid-bg); }

/* Programme badge in the schedule table's first cell. Three programmes share
   one table now, so the exam has to be readable at a glance before the venue
   and section code, which look alike across programmes. */
.a1-sched__exam {
  display: inline-block;
  margin-right: var(--a1-s-2);
  padding: 1px 7px;
  border-radius: var(--a1-r-tag);
  background: var(--a1-primary);
  color: var(--a1-on-dark);
  font-size: var(--a1-caption);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  vertical-align: 1px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   2026 refinement layer
   ═══════════════════════════════════════════════════════════════════════════
   A refinement, not a redesign: the oxblood-on-paper identity, the type scale
   and every piece of copy are untouched. What changes is the edge treatment,
   which is what made the site read as boxy — a page of hard rectangles at
   every scale, from the 52px logo to the full-width dark bands.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── The logo was a square because the artwork is a circle ─────────────────
   acad1-logo.jpg is a circular gold-ring emblem rendered onto a solid black
   square canvas. A JPEG cannot carry transparency, so that black canvas was
   painted onto the header as a hard tile — the "square box" itself, not a
   styling oversight. Clipping the image to a circle discards the corners and
   leaves exactly the mark the designer drew. Applied wherever the logo
   appears so header, sticky bar and footer agree. */
.a1-header img[src*="acad1-logo"],
.a1-footer img[src*="acad1-logo"],
.a1-stickybar img[src*="acad1-logo"],
.custom-logo,
img.custom-logo { border-radius: 50%; }

/* ── Sections become slabs ─────────────────────────────────────────────────
   The toned sections already sat inside the content column rather than
   bleeding to the viewport edge, so their square corners read as a rectangle
   that had simply been cut off. A slab radius makes the same band read as a
   panel that was placed. Light sections stay square: they share the page
   ground, so rounding them would outline a shape nobody can see the edge of. */
.a1-section--dark,
.a1-section--accent,
.a1-section--primary { border-radius: var(--a1-r-slab); }

/* ── Card media shares the card's corner ───────────────────────────────────
   A square photograph inside a rounded card is the single most common tell of
   a radius applied to the container and forgotten on its contents. Slightly
   tighter than the card so the two curves nest instead of fighting. */
.a1-card img { border-radius: calc(var(--a1-r-card) - 4px); }

/* Hero and feature imagery carries the larger media radius. */
.a1-section > .a1-container > img,
.a1-media img { border-radius: var(--a1-r-media); }

/* ── Feature card ─────────────────────────────────────────────────────────
   Was a 3px accent border-left. A thick coloured rule down one side is a
   pattern this design system does not otherwise use anywhere, and it fights
   the card's own radius at both corners it touches. Moved to the top edge,
   which is the treatment the spec already specifies for the recommended tier
   card, so the two emphasised cards on the site now match each other. */
/* (The feature card's accent now lives on its base rule above.) */

/* ── Interaction ──────────────────────────────────────────────────────────
   One authored moment rather than motion scattered over the page: a card that
   carries a link lifts fractionally toward the pointer. Everything else keeps
   its existing states. The transition is declared on the element, not on
   :hover, so it eases out as well as in. */
.a1-card {
  transition: transform 220ms cubic-bezier(0.16, 1, 0.3, 1),
              box-shadow 220ms cubic-bezier(0.16, 1, 0.3, 1),
              border-color 220ms cubic-bezier(0.16, 1, 0.3, 1);
}
.a1-card:has(a):hover {
  transform: translateY(-3px);
  box-shadow: var(--a1-sh-md);
  border-color: var(--a1-border-strong);
}
.a1-card--dark:has(a):hover { border-color: var(--a1-on-dark-rule); }

.a1-btn { transition: background-color 160ms ease-out, color 160ms ease-out, border-color 160ms ease-out; }

@media (prefers-reduced-motion: reduce) {
  .a1-card, .a1-btn { transition: none; }
  .a1-card:has(a):hover { transform: none; }
}

/* ── Surfaces the browser draws ───────────────────────────────────────────
   Scrollbar, numerals and underline offset ship with defaults that belong to
   no design system. ::selection and :focus-visible are already themed in
   10-base.css; these are the rest. */
* { scrollbar-color: var(--a1-border-strong) transparent; scrollbar-width: thin; }
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--a1-border-strong);
  border-radius: var(--a1-r-tag);
  border: 3px solid var(--a1-bg);
}
::-webkit-scrollbar-thumb:hover { background: var(--a1-secondary); }

/* Figures that are read in a column — fees, dates, counts — line up only with
   lining tabular numerals. Proportional digits make a price column ragged. */
.a1-table .is-num,
.a1-stats > * > :first-child,
.woocommerce .amount,
.a1-sched__time { font-variant-numeric: tabular-nums lining-nums; }

/* Underlines that clear the descenders instead of striking through them. */
.entry-content a:not(.a1-btn):not(.a1-card__cta a) { text-underline-offset: 0.18em; text-decoration-thickness: 1px; }

/* ── GeneratePress back-to-top ────────────────────────────────────────────
   Ships as a grey rounded square in the parent theme's own colours, which is
   the one control on the page that belongs to no palette here. */
.generate-back-to-top {
  background: var(--a1-primary);
  color: var(--a1-on-dark);
  border-radius: 50%;
  box-shadow: var(--a1-sh-md);
}
.generate-back-to-top:hover,
.generate-back-to-top:focus { background: var(--a1-accent); color: var(--a1-contrast); }

/* ── Web Interface Guidelines pass ─────────────────────────────────────────
   Items the guidelines call for that this theme had not yet declared. */

/* An in-page jump landed the target heading hard against the viewport edge,
   with no room above it to show it had arrived. The programme pages jump to
   #fees and #schedules from their own hero buttons, so this fires often. */
:where(h1, h2, h3, [id]) { scroll-margin-top: var(--a1-s-8); }

/* Headings set their own line breaks rather than filling the measure and
   orphaning a word onto the last line. Confined to headings — `balance` is
   capped at a handful of lines and is wrong for body copy. */
h1, h2, h3, .a1-card h3 { text-wrap: balance; }

/* Long-form paragraphs avoid a single-word last line. */
p, li { text-wrap: pretty; }

/* Tell the browser which scheme its own widgets should render in — form
   controls, scrollbars and the caret pick their defaults from this. The site
   is light throughout, so this is a statement rather than a switch. */
:root { color-scheme: light; }

/* The mobile navigation is a full-height panel. Without this, scrolling to its
   end hands the gesture to the page underneath and the page moves behind the
   open menu. */
.a1-header__nav-panel,
.a1-nav-panel { overscroll-behavior: contain; }

/* Long single-token content — an email address, a venue name with no spaces —
   must wrap rather than push its container wider than the viewport. */
.a1-card, .a1-table td, .a1-table th, address { overflow-wrap: anywhere; }

/* Tags that are links. The exam chips on the home page name the exact page a
   visitor wants, so they navigate rather than decorate — which means they need
   the states a link has. Underline is withheld at rest because a row of
   underlined pills reads as noise; it returns on hover and focus, and the
   colour shift alone never has to carry the affordance. */
a.a1-tag {
  text-decoration: none;
  color: var(--a1-text);
  transition: background-color 160ms ease-out, color 160ms ease-out, border-color 160ms ease-out;
}
a.a1-tag:hover,
a.a1-tag:focus-visible {
  background: var(--a1-primary);
  color: var(--a1-on-dark);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
a.a1-tag--accent:hover,
a.a1-tag--accent:focus-visible { background: var(--a1-accent); color: var(--a1-contrast); }

@media (prefers-reduced-motion: reduce) { a.a1-tag { transition: none; } }

/* ── Air around the page body ──────────────────────────────────────────────
   The first section sat 1px below the header on every inner page. That was
   survivable while sections were square — the band simply continued the
   header's edge — but a rounded slab whose top corners are cut off by the
   chrome above it reads as a rectangle again, which undoes the slab entirely.
   The landing page is excluded: its first section is the hero, and it is
   meant to meet the header.

   Applied to GeneratePress' own content wrapper rather than to the first
   section, so it holds on templates whose content is not a bare list of
   sections — the branch layout and the WooCommerce pages among them. */
body:not(.home) .site-content { padding-top: var(--a1-page-gap-top); }

/* The same argument at the other end: the last slab needs to clear the footer
   rather than tuck under it. This one applies to the landing page too — its
   final section is a rounded CTA band with the same corners to protect. */
.site-content { padding-bottom: var(--a1-page-gap-bottom); }

/* ═══════════════════════════════════════════════════════════════════════════
   Block-native layer
   ═══════════════════════════════════════════════════════════════════════════
   The pages are being rebuilt from wp:html slabs into native core blocks. Raw
   HTML could carry inline styles; a core block cannot (and should not). These
   rules move every colour and measure the slabs set inline into the cascade,
   keyed off the section classes the blocks carry — so a block page needs no
   inline style anywhere, and an editor adding a heading inside a dark section
   gets readable text without knowing the token system exists. */

/* Section-scoped text colour: the ground decides, the content inherits. */
.a1-section--dark :is(h1, h2, h3, h4) { color: var(--a1-on-dark); }
.a1-section--dark p                   { color: var(--a1-on-dark-80); }
.a1-section--dark li                  { color: var(--a1-on-dark-80); }
.a1-section--dark .a1-card__kicker    { color: var(--a1-accent-on-dark); }
.a1-section--accent :is(h1, h2, h3, h4, p) { color: var(--a1-contrast); }

/* Breadcrumb line above a hero heading. */
.a1-breadcrumb,
.a1-breadcrumb a { color: var(--a1-on-dark-70); font-size: var(--a1-meta); }
.a1-breadcrumb a:hover { color: var(--a1-on-dark); }

/* Measures. Blocks reference these instead of inline max-widths. */
.a1-lead       { max-width: 62ch; }
.a1-measure    { max-width: 62ch; }
.a1-measure-sm { max-width: 56ch; }
.a1-measure-lg { max-width: 70ch; }

/* Secondary small print (fee footnotes, table notes). */
.a1-note { color: var(--a1-secondary); font-size: var(--a1-body-sm); }
.a1-section--dark .a1-note { color: var(--a1-on-dark-70); }

/* Stat figures (2003 / 200+ / 9) and tier prices. */
.a1-stat-number,
.a1-price {
  font-size: var(--a1-h3); font-weight: 800; margin: 0;
  font-variant-numeric: tabular-nums lining-nums;
}
.a1-price small { font-size: var(--a1-meta); font-weight: 400; color: var(--a1-secondary); }

/* Hero media slot: full-bleed within its column, capped height. */
.a1-media--hero img {
  width: 100%; height: clamp(320px, 44vw, 520px);
  object-fit: cover; border-radius: var(--a1-r-media);
}

/* A section that hands off directly into the next (schedule table under its
   own heading section). */
.a1-section--flush-top { padding-top: 0; }

/* ── core/button bridge ────────────────────────────────────────────────────
   core/button places custom classes on its wrapper div and hard-codes
   .wp-block-button__link on the anchor, so the .a1-btn selectors can never
   reach it. The link takes the .a1-btn base; the variant is read off the
   wrapper. Same visual system, one extra hop. */
.wp-block-buttons { display: flex; flex-wrap: wrap; gap: var(--a1-s-3); }
.wp-block-button__link {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font: inherit; font-weight: 700; font-size: var(--a1-body-sm);
  padding: 13px 22px; min-height: var(--a1-target-min);
  border: 1px solid transparent; border-radius: var(--a1-r-btn);
  text-decoration: none; cursor: pointer; transition: background .15s, color .15s;
}
.wp-block-button.a1-btn--primary .wp-block-button__link { background: var(--a1-accent); color: var(--a1-contrast); }
.wp-block-button.a1-btn--primary .wp-block-button__link:hover { background: var(--a1-accent-lt); color: var(--a1-contrast); }
.wp-block-button.a1-btn--primary .wp-block-button__link:active { background: var(--a1-accent-dk); }
.wp-block-button.a1-btn--secondary .wp-block-button__link { border-color: var(--a1-primary); color: var(--a1-primary); background: transparent; }
.wp-block-button.a1-btn--secondary .wp-block-button__link:hover { background: var(--a1-surface); }
.wp-block-button.a1-btn--onaccent .wp-block-button__link { background: var(--a1-contrast); color: var(--a1-accent); }
.wp-block-button.a1-btn--onaccent .wp-block-button__link:hover { background: var(--a1-contrast); color: var(--a1-accent-dk); }
.wp-block-button.a1-btn--ondark .wp-block-button__link { border-color: var(--a1-on-accent-border); color: var(--a1-contrast); background: transparent; }
.wp-block-button.a1-btn--ondark .wp-block-button__link:hover { background: rgba(0,0,0,0.12); color: var(--a1-contrast); } /* csscheck-allow: neutral scrim over an arbitrary ground, no token applies */

/* Core image blocks inside the token world. */
.a1-section .wp-block-image { margin: 0; }
.a1-section .wp-block-image img { max-width: 100%; height: auto; border-radius: var(--a1-r-media); }
.a1-card .wp-block-image img { border-radius: calc(var(--a1-r-card) - 4px); }

/* The Woo products-header on the shop page renders empty once its title is
   suppressed; an empty second <header> landmark is noise to a screen reader. */
.woocommerce-products-header:empty { display: none; }

/* Utilities backing the block conversion: patterns the wp:html slabs set
   inline, now expressible as a class a block can carry. */
.a1-accent-word { color: var(--a1-accent); }
.a1-row-between {
  display: flex; justify-content: space-between; align-items: flex-end;
  gap: var(--a1-s-5); flex-wrap: wrap;
}
.a1-stats .a1-card__kicker { margin-top: var(--a1-s-1); }
.a1-copy-col { max-width: 760px; }
.a1-hairline-top { border-top: 1px solid var(--a1-border); padding-top: var(--a1-s-6); }
.a1-section--dark .a1-hairline-top { border-top-color: var(--a1-on-dark-rule); }
.a1-card--tight { padding: var(--a1-s-3); }
.a1-clip { overflow: hidden; }

/* Utilities completing the slab-to-block translation (each replaces one
   recurring inline-style pattern from the old raw HTML). */
.a1-meta { font-size: var(--a1-meta); }
.a1-section--dark .a1-meta,
.a1-section--dark .a1-meta a { color: var(--a1-on-dark-70); }
.a1-medium { font-weight: 500; }
.a1-h-sm { font-size: 22px; }
.a1-sticky-offset { top: 96px; }
.a1-measure-title { max-width: 24ch; }
.a1-card--white { background: var(--a1-contrast); }
.a1-card--roomy { padding: var(--a1-s-7); }
.a1-card--flush { padding: 0; }
.a1-card--ghost { background: var(--a1-ghost-bg); border-color: var(--a1-ghost-border); }
.a1-vstack { display: flex; flex-direction: column; gap: var(--a1-s-5); }
.a1-phone-lg { font-size: 26px; font-weight: 800; line-height: 1.3; }
.a1-link-underline { text-decoration: none; border-bottom: 1px solid var(--a1-accent-lt); padding-bottom: 2px; }
.a1-media--card img, img.a1-media--card { width: 100%; height: 168px; object-fit: cover; }
img.a1-logo-mark { max-height: 72px; width: auto; object-fit: contain; filter: grayscale(1); }
.a1-h4 { font-size: var(--a1-h4); }
.a1-pad-5 { padding: var(--a1-s-5); }
.a1-center-y { align-items: center; }
.a1-grid--autofit { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
.a1-copy-col-lg { max-width: 860px; margin-inline: auto; }
.a1-row-split { display: flex; justify-content: space-between; padding: 4px 0; }
hr.a1-rule-mark { border: 0; border-top: 2px solid var(--a1-primary); width: 48px; margin: var(--a1-s-4) 0; background: none; }
hr.a1-rule-ondark { border: 0; border-top: 1px solid var(--a1-on-dark-rule); margin: var(--a1-s-4) 0; background: none; }

/* Dark and ghost CARDS need the same content cascade as dark sections: a
   charcoal card in a light section otherwise renders base ink on charcoal
   (1.11:1) because conversion moved colour off the elements and into the
   ground's responsibility. */
.a1-card--dark :is(h1, h2, h3, h4),
.a1-card--ghost :is(h1, h2, h3, h4) { color: var(--a1-on-dark); }
.a1-card--dark p,
.a1-card--dark li,
.a1-card--ghost p,
.a1-card--ghost li { color: var(--a1-on-dark-80); }
.a1-card--dark .a1-card__kicker,
.a1-card--ghost .a1-card__kicker { color: var(--a1-accent-on-dark); }
.a1-card--dark .a1-note,
.a1-card--ghost .a1-note { color: var(--a1-on-dark-70); }

/* And the inverse: a light-grounded card inside a dark section must not
   inherit the section's on-dark palette. */
.a1-section--dark :is(.a1-card--white, .a1-card--surface) :is(h1, h2, h3, h4),
.a1-section--dark :is(.a1-card--white, .a1-card--surface) p,
.a1-section--dark :is(.a1-card--white, .a1-card--surface) li { color: var(--a1-text); }
.a1-section--dark :is(.a1-card--white, .a1-card--surface) .a1-card__kicker { color: var(--a1-accent); }
.a1-section--dark :is(.a1-card--white, .a1-card--surface) .a1-note { color: var(--a1-secondary); }

/* ═══════════════════════════════════════════════════════════════════════════
   Rhythm layer — padding, margins and container spacing for the block pages
   ═══════════════════════════════════════════════════════════════════════════
   WordPress's flow layout stacks every block a uniform gap apart, which reads
   as a list, not a composition. The design's rhythm is: tight within a group
   (kicker to heading, heading to lead), generous between groups, and more
   space above a heading than below it. Grids and flex rows own their spacing
   through gap, so their children carry no margins at all. Density dial 0.4:
   the mid band — neither airy-editorial nor packed. */

/* Base beat inside any content group in a section. */
.a1-section .wp-block-group > * + * { margin-block-start: var(--a1-s-4); }

/* Layout containers space through gap — children carry nothing. */
.a1-section :is(.a1-grid, .a1-split, .a1-split--rail, .a1-split--filter,
  .a1-stats, .a1-vstack, .a1-row-between, .a1-row-split, .a1-chips,
  .wp-block-buttons, .a1-marquee__track) > * { margin-block: 0; }

/* Generous air above a new thought: headings and hairline-topped groups
   arriving mid-flow. */
.a1-container > * + :is(h2, h3),
.a1-container > * + .a1-hairline-top,
.a1-section .wp-block-group > * + :is(h2, h3) { margin-block-start: var(--a1-s-8); }

/* Tight after the heading it introduces. */
.a1-container > :is(h1, h2, h3) + *,
.a1-section .wp-block-group > :is(h1, h2, h3) + * { margin-block-start: var(--a1-s-3); }

/* Hero cadence: breadcrumb, kicker, headline, lead, actions. */
.a1-container > .a1-meta + p { margin-block-start: var(--a1-s-6); }
.a1-container > .a1-card__kicker + :is(h1, h2) { margin-block-start: var(--a1-s-2); }
.a1-container > h1 + p { margin-block-start: var(--a1-s-4); }
.a1-container > * + .wp-block-buttons { margin-block-start: var(--a1-s-6); }

/* Cards beat tighter than the page. */
.a1-card > * + * { margin-block-start: var(--a1-s-3); }
.a1-card > .a1-card__kicker + * { margin-block-start: var(--a1-s-2); }
.a1-card > .a1-card__cta { margin-top: auto; padding-top: var(--a1-s-4); }

/* Stat cells: figure sits right on its label. */
.a1-stats .a1-stat-number + .a1-card__kicker { margin-block-start: var(--a1-s-1); }

/* Shortcode output and islands keep their own internal spacing; give the
   blocks around them clear separation. */
.a1-container > * + :is(.a1-table__wrap, .wp-block-shortcode) { margin-block-start: var(--a1-s-6); }

/* ═══════════════════════════════════════════════════════════════════════════
   Button state integrity
   ═══════════════════════════════════════════════════════════════════════════
   Two leaks made hover text illegible in places:
   1. A core/button with no variant class fell to WordPress's own
      .wp-element-button default — dark grey #32373c — and on hover the global
      `a:hover { color: var(--a1-accent-lt) }` painted oxblood-on-grey at
      2.5:1. An unclassed button now IS a primary.
   2. Variants whose hover declared only a background let that same a:hover
      rule supply the text colour. Every state of every variant now declares
      BOTH colour and ground; nothing is left for the link default to fill. */

.wp-block-button__link,
.wp-block-button__link.wp-element-button {
  background: var(--a1-accent); color: var(--a1-contrast);
}
.wp-block-button__link:hover,
.wp-block-button__link:focus { background: var(--a1-accent-lt); color: var(--a1-contrast); }
.wp-block-button__link:active { background: var(--a1-accent-dk); color: var(--a1-contrast); }

.wp-block-button.a1-btn--secondary .wp-block-button__link:hover,
.wp-block-button.a1-btn--secondary .wp-block-button__link:focus { background: var(--a1-surface); color: var(--a1-primary); }
.wp-block-button.a1-btn--secondary .wp-block-button__link:active { background: var(--a1-border); color: var(--a1-primary); }
.wp-block-button.a1-btn--onaccent .wp-block-button__link:active { background: var(--a1-contrast); color: var(--a1-accent-dk); }
.wp-block-button.a1-btn--ondark .wp-block-button__link:active { background: rgba(0,0,0,0.2); color: var(--a1-contrast); } /* csscheck-allow: neutral scrim, no token applies */

/* The legacy anchors get the same completeness: focus mirrors hover, and the
   two inverted variants keep their text colour through every state. */
.a1-btn.a1-btn--primary:focus { background: var(--a1-accent-lt); color: var(--a1-contrast); }
.a1-btn.a1-btn--secondary:hover,
.a1-btn.a1-btn--secondary:focus { background: var(--a1-surface); color: var(--a1-primary); }
.a1-btn.a1-btn--secondary:active { background: var(--a1-border); color: var(--a1-primary); }
.a1-btn.a1-btn--onaccent:focus { background: var(--a1-contrast); color: var(--a1-accent-dk); }
.a1-btn.a1-btn--onaccent:active { background: var(--a1-contrast); color: var(--a1-accent-dk); }
.a1-btn.a1-btn--ondark:focus { background: rgba(0,0,0,0.12); color: var(--a1-contrast); } /* csscheck-allow: neutral scrim, no token applies */
.a1-btn.a1-btn--ondark:active { background: rgba(0,0,0,0.2); color: var(--a1-contrast); } /* csscheck-allow: neutral scrim, no token applies */
.a1-btn:hover, .wp-block-button__link:hover { text-decoration: none; }
