/* ASPIRE Paddling Co — shared stylesheet */

:root {
  --brand: #004c6d;
  --brand-dark: #00354d;
  --brand-light: #e6f0f5;
  --accent: #f2a541;
  --ink: #23282d;
  --ink-soft: #55616b;
  --line: #dde5ea;
  --bg: #ffffff;
  --bg-alt: #f6f9fb;
  --radius: 10px;
  --shadow: 0 2px 14px rgba(0, 41, 60, .08);
  --shadow-lg: 0 12px 34px rgba(0, 41, 60, .14);
  --maxw: 1180px;
  --font: "Roboto", "Segoe UI", system-ui, -apple-system, Arial, sans-serif;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.65;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

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

a { color: var(--brand); }

h1, h2, h3, h4 {
  font-weight: 700;
  line-height: 1.15;
  margin: 0 0 .6em;
  letter-spacing: -.01em;
}

h1 { font-size: clamp(2.1rem, 5vw, 3.4rem); }
h2 { font-size: clamp(1.6rem, 3.2vw, 2.3rem); }
h3 { font-size: 1.2rem; }

p { margin: 0 0 1.1em; }

.wrap {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 24px;
}

.skip {
  position: absolute;
  left: -9999px;
}
.skip:focus {
  left: 12px; top: 12px;
  z-index: 200;
  background: #fff;
  padding: 10px 16px;
  border-radius: 6px;
}

/* ---------- header ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(255, 255, 255, .96);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}

.header-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 12px 24px;
  display: flex;
  align-items: center;
  gap: 24px;
}

.logo img { height: 46px; width: auto; }

.nav-toggle {
  margin-left: auto;
  display: none;
  background: none;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 8px 12px;
  font-size: 1.1rem;
  cursor: pointer;
  color: var(--brand);
}

.nav {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
}

.nav a {
  display: block;
  padding: 10px 14px;
  font-size: .82rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  border-radius: 6px;
}

.nav a:hover { background: var(--brand-light); color: var(--brand); }

/* The current page is marked by colour and a tint, not by a rule under the
   link. The kayak parks on the current item and its wake settles in exactly
   that strip, so an underline there was a second marker fighting the first —
   and it cut across the boat. */
.nav a[aria-current="page"] { color: var(--brand); background: var(--brand-light); }

.nav .btn { margin-left: 8px; }

/* ---------- buttons ---------- */

.btn {
  display: inline-block;
  padding: 13px 26px;
  border: 2px solid var(--brand);
  border-radius: 999px;
  background: var(--brand);
  color: #fff;
  font-size: .82rem;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: background .15s ease, color .15s ease, transform .15s ease;
}
.btn:hover { background: var(--brand-dark); border-color: var(--brand-dark); transform: translateY(-1px); }

.btn-outline { background: transparent; color: var(--brand); }
.btn-outline:hover { background: var(--brand); color: #fff; }

.btn-light { background: #fff; border-color: #fff; color: var(--brand); }
.btn-light:hover { background: var(--brand-light); border-color: var(--brand-light); color: var(--brand-dark); }

/* ---------- hero ---------- */

.hero {
  position: relative;
  min-height: 62vh;
  display: flex;
  align-items: center;
  color: #fff;
  background: var(--brand-dark) center/cover no-repeat;
}
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(0, 53, 77, .82) 0%, rgba(0, 53, 77, .45) 65%, rgba(0, 53, 77, .25) 100%);
}
.hero .wrap { position: relative; z-index: 1; padding: 80px 24px; }
.hero p { max-width: 58ch; font-size: 1.1rem; color: rgba(255, 255, 255, .92); }
.hero .eyebrow {
  font-size: .8rem;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 14px;
}

.hero-sm { min-height: 40vh; }

/* ---------- sections ---------- */

.section { padding: 76px 0; }
.section-alt { background: var(--bg-alt); }

.section-head { max-width: 62ch; margin-bottom: 44px; }
.section-head.center { margin-left: auto; margin-right: auto; text-align: center; }
.section-head p { color: var(--ink-soft); font-size: 1.05rem; margin-bottom: 0; }

.eyebrow {
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--brand);
  margin: 0 0 10px;
}

/* ---------- cards ---------- */

.grid {
  display: grid;
  gap: 28px;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
}

.card {
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
  transition: transform .18s ease, box-shadow .18s ease;
}
.card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); }

.card img { aspect-ratio: 16 / 10; object-fit: cover; width: 100%; }
.card-body { padding: 24px; display: flex; flex-direction: column; flex: 1; }
.card-body p { color: var(--ink-soft); font-size: .97rem; }
.card-body .btn { align-self: flex-start; margin-top: auto; }

/* ---------- split ---------- */

.split {
  display: grid;
  gap: 48px;
  align-items: center;
  grid-template-columns: 1fr 1fr;
}
.split img { border-radius: var(--radius); box-shadow: var(--shadow); }

/* ---------- values ---------- */

.values { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.value {
  padding: 26px;
  background: #fff;
  border: 1px solid var(--line);
  border-left: 4px solid var(--brand);
  border-radius: var(--radius);
}
.value h3 { margin-bottom: .35em; color: var(--brand); }
.value p { margin: 0; font-size: .95rem; color: var(--ink-soft); }

/* ---------- testimonials ---------- */

.quotes { display: grid; gap: 28px; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.quote {
  padding: 30px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.quote blockquote { margin: 0 0 18px; font-size: 1.02rem; color: var(--ink); }
.quote blockquote::before { content: "\201C"; color: var(--accent); font-size: 2.4rem; line-height: 0; vertical-align: -.35em; margin-right: 4px; }
.quote cite { font-style: normal; font-size: .88rem; color: var(--ink-soft); }
.quote cite strong { display: block; color: var(--ink); font-size: .96rem; }

/* ---------- cta band ---------- */

.cta {
  padding: 66px 0;
  background: var(--brand);
  color: #fff;
  text-align: center;
}
.cta h2 { color: #fff; }
.cta p { max-width: 54ch; margin: 0 auto 26px; color: rgba(255, 255, 255, .9); }

/* ---------- form ---------- */

.form-layout { display: grid; gap: 48px; grid-template-columns: 1.1fr .9fr; align-items: start; }

.form {
  padding: 32px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.field { margin-bottom: 20px; }
.field label {
  display: block;
  margin-bottom: 7px;
  font-size: .84rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.field input[type="text"],
.field input[type="email"],
.field input[type="tel"],
.field textarea,
.field select {
  width: 100%;
  padding: 12px 14px;
  font: inherit;
  font-size: 1rem;
  color: var(--ink);
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 8px;
}
.field input:focus, .field textarea:focus, .field select:focus {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
  border-color: var(--brand);
}
.field textarea { min-height: 140px; resize: vertical; }

.radios { display: flex; flex-wrap: wrap; gap: 18px; }
.radios label {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: .95rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink);
  font-weight: 400;
}

.contact-details { font-size: 1rem; }
.contact-details dt {
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-top: 20px;
}
.contact-details dd { margin: 4px 0 0; }
.contact-details a { text-decoration: none; }
.contact-details a:hover { text-decoration: underline; }

/* ---------- footer ---------- */

.site-footer {
  padding: 56px 0 28px;
  background: var(--brand-dark);
  color: rgba(255, 255, 255, .84);
  font-size: .95rem;
}
.site-footer h3 { color: #fff; font-size: 1rem; letter-spacing: .06em; text-transform: uppercase; }
.site-footer a { color: #fff; text-decoration: none; }
.site-footer a:hover { text-decoration: underline; }
.footer-grid { display: grid; gap: 36px; grid-template-columns: 1.3fr 1fr 1fr; }
.footer-grid ul { list-style: none; margin: 0; padding: 0; }
.footer-grid li { margin-bottom: 8px; }
.footer-logo { height: 42px; width: auto; margin-bottom: 18px; filter: brightness(0) invert(1); }
.badge { max-width: 120px; margin-top: 18px; background: #fff; border-radius: 8px; padding: 8px; }
.footer-bottom {
  margin-top: 40px;
  padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, .16);
  font-size: .85rem;
  color: rgba(255, 255, 255, .6);
}

/* ---------- notes / placeholders ---------- */

.todo {
  padding: 14px 18px;
  border-left: 4px solid var(--accent);
  background: #fff8ec;
  border-radius: 6px;
  font-size: .92rem;
  color: #6b4d16;
}

/* ---------- responsive ---------- */

@media (max-width: 900px) {
  .split, .form-layout { grid-template-columns: 1fr; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 760px) {
  .nav-toggle { display: block; }
  .nav {
    display: none;
    position: absolute;
    left: 0; right: 0; top: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 10px 16px 18px;
    background: #fff;
    border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow);
  }
  .nav.open { display: flex; }
  .nav a { padding: 14px 8px; border-bottom: 1px solid var(--line); border-radius: 0; }
  .nav .btn { margin: 14px 8px 0; border-bottom: none; text-align: center; }
  .header-inner { position: relative; }
  .section { padding: 56px 0; }
  .footer-grid { grid-template-columns: 1fr; }
}

/* ---------- audience split (For Educators / For Corporate Clients) ---------- */

.audience { display: grid; gap: 28px; grid-template-columns: 1fr 1fr; }
.audience-card {
  padding: 34px;
  background: #fff;
  border: 1px solid var(--line);
  border-top: 4px solid var(--brand);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.audience-card h3 { color: var(--brand); font-size: 1.35rem; }
.audience-card p { color: var(--ink-soft); }

/* ---------- values table ---------- */

.table-values { width: 100%; border-collapse: collapse; background: #fff; }
.table-values th, .table-values td {
  padding: 16px 18px;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--line);
}
.table-values thead th {
  font-size: .78rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #fff;
  background: var(--brand);
  border-bottom: none;
}
.table-values tbody th { width: 230px; color: var(--brand); font-weight: 700; }
.table-values tbody td { color: var(--ink-soft); }
.table-values tbody tr:nth-child(even) { background: var(--bg-alt); }

/* ---------- jump list ---------- */

.jump { display: flex; flex-wrap: wrap; gap: 10px; list-style: none; margin: 0; padding: 0; }
.jump a {
  display: block;
  padding: 10px 18px;
  font-size: .82rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--brand);
  background: var(--brand-light);
  border-radius: 999px;
}
.jump a:hover { background: var(--brand); color: #fff; }

/* ---------- learning outcomes ---------- */

/* min(320px, 100%) rather than a bare 320px: below about 370 the viewport
   cannot give a 320px track the padding as well, and the row overflows to
   the right — silently, because html,body carry overflow-x:hidden, so it
   reads as text that has gone missing rather than as a page too wide.
   Measured at 320: the card ran to 344. */
.outcome-groups {
  display: grid;
  gap: 28px;
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  /* Grid items stretch to the row height by default, so one open group next
     to a short one drew the short one as a tall empty white box with its
     heading stranded at the top — which reads as a card that failed to load.
     Each one is now as tall as its own content. */
  align-items: start;
}
.outcome-group {
  padding: 28px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.outcome-group h3 { color: var(--brand); font-size: 1.05rem; }
.outcomes { margin: 0; padding-left: 1.15em; }
.outcomes li { margin-bottom: 12px; font-size: .96rem; color: var(--ink-soft); }
.outcomes li strong { color: var(--ink); }
.outcomes li::marker { color: var(--accent); }

.stage-num {
  margin: 0 0 6px;
  font-size: .74rem;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--accent);
}
.stage-years { font-size: .92rem; color: var(--ink-soft); }
.stage-meta {
  display: inline-block;
  margin: 0 0 28px;
  padding: 10px 18px;
  font-size: .92rem;
  color: var(--brand);
  background: var(--brand-light);
  border-radius: 8px;
}

/* ---------- misc ---------- */

.note { margin-top: 20px; font-size: .9rem; color: var(--ink-soft); }

.field-label {
  display: block;
  margin-bottom: 7px;
  font-size: .84rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.steps { margin: 0; padding-left: 1.2em; }
.steps li { margin-bottom: 10px; color: var(--ink-soft); }
.steps li::marker { color: var(--brand); font-weight: 700; }

@media (max-width: 900px) {
  .audience { grid-template-columns: 1fr; }
  .table-values tbody th { width: auto; }
}

/* ================================================================
   PADDLING CHARACTER LAYER
   Added after the base sheet so these rules win.

   Design rule for everything below: decoration is never positioned
   absolutely outside its parent. Every decorative element is either a
   full-width background on a clipped container, or a ::before/::after
   inside one. This is deliberate — absolutely-positioned decoration
   escaping its section is what broke the Coorong site's hero.
   ================================================================ */

:root {
  /* warmer coastal palette: brand blue stays, sand + sun join it */
  --sand: #f4ede1;
  --sand-deep: #e8dcc8;
  --sun: #f2a541;
  --reef: #1b8a9c;
  --accent: #f2a541;
  --bg-alt: var(--sand);
}

/* every section clips its own decoration — the single most important
   rule in this file */
.section, .hero, .cta, .site-footer { overflow: clip; overflow: hidden; position: relative; }

/* ---------- scroll progress ---------- */

.progress {
  position: fixed;
  top: 0; left: 0;
  height: 3px;
  width: 0;
  z-index: 200;
  background: linear-gradient(90deg, var(--reef), var(--sun));
  transition: width .1s linear;
  pointer-events: none;
}

/* ---------- header: shrinks on scroll ---------- */

.site-header { transition: box-shadow .2s ease, padding .2s ease; }
.site-header.scrolled { box-shadow: 0 2px 18px rgba(0, 41, 60, .12); }
.site-header.scrolled .logo img { height: 36px; transition: height .2s ease; }
.logo img { transition: height .2s ease; }

/* ---------- hero: drifting wave at the waterline ---------- */

.hero::before {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -2px;
  height: 90px;
  z-index: 1;
  background-repeat: repeat-x;
  background-position: 0 bottom;
  background-size: 1200px 90px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 90' preserveAspectRatio='none'%3E%3Cpath d='M0 46c120-26 220 18 340 12s190-38 310-30 210 44 330 36 180-30 220-38v64H0z' fill='%23ffffff' fill-opacity='.35'/%3E%3C/svg%3E");
  animation: drift 26s linear infinite;
}

.hero::after {
  /* keep the existing gradient scrim, and lay the solid wave over it */
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 80' preserveAspectRatio='none'%3E%3Cpath d='M0 40c150 34 280-22 430-16s250 40 400 34 250-34 370-42v70H0z' fill='%23ffffff'/%3E%3C/svg%3E") 0 bottom / 100% 80px no-repeat,
    linear-gradient(90deg, rgba(0, 53, 77, .86) 0%, rgba(0, 53, 77, .5) 60%, rgba(0, 53, 77, .28) 100%);
}

@keyframes drift {
  from { background-position: 0 bottom; }
  to   { background-position: 1200px bottom; }
}

.hero .wrap { padding-bottom: 130px; }
.hero-sm .wrap { padding-bottom: 110px; }

/* the eyebrow gets a small paddle rule instead of a bare line */
.hero .eyebrow { display: inline-flex; align-items: center; gap: 12px; }
.hero .eyebrow::before {
  content: "";
  width: 34px; height: 2px;
  background: var(--sun);
  border-radius: 2px;
}

/* ---------- sand sections get a wave lip ---------- */

.section-alt::before {
  content: "";
  position: absolute;
  top: -1px; left: 0; right: 0;
  height: 54px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 54' preserveAspectRatio='none'%3E%3Cpath d='M0 0c140 32 260 32 420 14S760-6 900 6s220 26 300 34V0z' fill='%23ffffff'/%3E%3C/svg%3E") 0 0 / 100% 54px no-repeat;
}
.section-alt { padding-top: 104px; }

/* ---------- cta + footer waterlines ---------- */

.cta::before, .site-footer::before {
  content: "";
  position: absolute;
  top: -1px; left: 0; right: 0;
  height: 48px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 48' preserveAspectRatio='none'%3E%3Cpath d='M0 0c130 30 250 26 400 10s300-22 440-8 250 22 360 30V0z' fill='%23ffffff'/%3E%3C/svg%3E") 0 0 / 100% 48px no-repeat;
}
.cta { padding-top: 96px; }
.site-footer { padding-top: 84px; }
.cta::before { filter: none; }

/* the cta band reads as open water */
.cta {
  background: linear-gradient(160deg, var(--brand) 0%, var(--reef) 100%);
}

/* ---------- scroll reveal ---------- */

.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .6s ease, transform .6s ease;
}
.reveal.in { opacity: 1; transform: none; }

/* ---------- cards: lift, and the photo breathes ---------- */

.card { position: relative; overflow: hidden; }
.card::after {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 4px;
  background: var(--brand);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .3s ease;
}
.card:hover::after { transform: scaleX(1); }
/* The card photo used to scale 1.04 on hover. Removed: the card already lifts
   and draws a rule across its top, and a third thing moving made the photo
   look like it was straining against the box it is cropped into. */

/* ================================================================
   EXPERIENCES — the five themes, told in colour
   ================================================================

   The theme colours have been in this file since the page was built and
   almost nothing showed them: an eyebrow, a rule that only appears on
   hover, an outline button. Five themes that look identical are one theme
   with five headings.

   The five ids still set --theme, because that is where the client's own
   slugs live. Everything that USES it hangs off `.xp-theme` — one rule
   each, instead of a five-way selector list that had to be edited in four
   places to add a sixth theme.
   ================================================================ */

/* The id is the client's own slug for the theme, from the content store,
   which is why the colour is keyed on it and nothing else. Add a theme in
   Pages and it needs a line here — that is the one place. */
#challenge  { --theme: #e4572e; }
#reset      { --theme: #1b8a9c; }
#culture    { --theme: #8a6a3d; }
#celebrate  { --theme: #d4a015; }
#skills     { --theme: #004c6d; }

/* The tint, named once. Everything that needs the section's own background
   colour — the section, and both of the waves it draws — reads this, so
   there is one place the 9% lives. */
.xp-theme { --tint: color-mix(in srgb, var(--theme) 9%, var(--sand)); }

/* --theme is the colour; --theme-ink is the colour you are allowed to put
   WORDS in.

   Four of the five failed WCAG AA as text and had done since the page was
   built. Measured against white: challenge 3.68:1, reset 4.07, culture
   4.99, celebrate 2.38 — and celebrate at 2.38 is not a contrast problem,
   it is an unreadable heading. Mixed 60% into black they come out at 8.17,
   8.67, 9.87 and 5.86, and they still read as rust, teal, earth and gold.

   Derived rather than five more constants in this file: change --theme and
   the ink follows it. The only rule to hold onto is which is which —
   **text and borders take --theme-ink, marks and fills take --theme.** */
.xp-theme, .xp-jump a { --theme-ink: color-mix(in srgb, var(--theme, var(--brand)) 60%, #000); }

.xp-theme .eyebrow { color: var(--theme-ink); }
.xp-theme .card::after { background: var(--theme); }
.xp-theme .btn-outline { color: var(--theme-ink); border-color: var(--theme-ink); }
.xp-theme .btn-outline:hover { background: var(--theme-ink); border-color: var(--theme-ink); color: #fff; }

/* The section head takes the theme down its left edge. Same idiom as the
   hero's eyebrow rule, turned on its side: a short bar of colour beside
   the words rather than a box around them. */
.xp-theme .section-head {
  padding-left: 22px;
  border-left: 4px solid var(--theme);
}

/* Every themed section is tinted with its own colour mixed into the sand,
   not laid over white — the page keeps one warm base and the five shift
   around it. */
.xp-theme { background: var(--tint); }

/* ---------- where one theme meets the next ----------

   THE MISTAKE THIS FIXES, because it is an easy one to make again: the wave
   lip is not a divider, it is **the colour of the section above hanging
   down into the section below**. `.section-alt::before` is filled white
   because on every other page the thing above it is white. Tint the
   sections and that stops being true, and every boundary becomes tint,
   white band, next tint — and at the foot of the page the grey-green of
   Skills, a white band, then the navy CTA. It looked like the page had come
   apart, and it was live for one round.

   The fix is the one this file already records for the scene bands: **a
   band owns its own edge.** Each themed section draws its own wave in its
   own colour, rising into whatever is above it — so a boundary needs one
   colour rather than two, and no section has to know what it follows.

   THE SHAPE IS A MASK, NOT A FILLED IMAGE, and that is the whole trick: a
   colour cannot be pushed into a data URI from a custom property, which is
   why the original lip had to be a fixed white and why it could only ever
   work under a white section. Masked, the shape is reusable and the colour
   comes from `background-color`, which can be `var(--tint)`.

   It is the same crest as every other boundary on the site — the path from
   `.section-alt::before` further down this file, inverted. If that one is
   ever redrawn, redraw this with it or the page grows two waves.

   SPECIFICITY, NOT ORDER. These are `.section-alt.xp-theme::before`, not
   `.xp-theme::before`. The first attempt lost silently: there are three
   more `.section-alt::before` rules LATER in this file, including the one
   that sets the real crest and its height, and at equal specificity the
   last one wins. The height came out 46px against a 54px mask and the wave
   had a white crescent through it.

   `overflow: visible` is safe HERE and nowhere else on the page: these
   sections carry no scene, and the only thing that escapes is the wave.
   Both waves sit in section padding — 76px below the last card, 96px above
   the CTA's own content — so neither can land on anything. */

.xp-theme { overflow: visible; }
.xp-theme > .wrap { position: relative; z-index: 1; }

.section-alt.xp-theme::before {
  --lip-h: 46px;
  content: "";
  position: absolute;
  top: calc(1px - var(--lip-h));
  left: 0; right: 0;
  height: var(--lip-h);
  z-index: 0;
  background: var(--tint);
  background-image: none;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 46' preserveAspectRatio='none'%3E%3Cpath d='M0 24c150-26 260-26 420-12s340 24 480 14 220-14 300-16V46H0z' fill='%23000'/%3E%3C/svg%3E") 0 0 / 100% 100% no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 46' preserveAspectRatio='none'%3E%3Cpath d='M0 24c150-26 260-26 420-12s340 24 480 14 220-14 300-16V46H0z' fill='%23000'/%3E%3C/svg%3E") 0 0 / 100% 100% no-repeat;
  pointer-events: none;
}

/* The foot of the page. The CTA draws its own white lip with the same
   problem, so the last themed section hangs its colour into the CTA
   instead and the CTA's lip is switched off.

   The z-index is load-bearing: `.cta` is positioned and comes later, so
   without it the CTA's background paints straight over this and the
   boundary goes back to a hard straight edge — which is exactly how the
   first attempt rendered.

   `:has()` rather than a class on the last section, because which theme is
   last is the client's business: reorder them in Pages and this follows. */
.xp-theme:has(+ .cta) { z-index: 1; }
.xp-theme:has(+ .cta)::after {
  --lip-h: 46px;
  content: "";
  position: absolute;
  bottom: calc(1px - var(--lip-h));
  left: 0; right: 0;
  height: var(--lip-h);
  z-index: 0;
  background: var(--tint);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 46' preserveAspectRatio='none'%3E%3Cpath d='M0 0v24c150-26 260-26 420-12s340 24 480 14 220-14 300-16V0z' fill='%23000'/%3E%3C/svg%3E") 0 0 / 100% 100% no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 46' preserveAspectRatio='none'%3E%3Cpath d='M0 0v24c150-26 260-26 420-12s340 24 480 14 220-14 300-16V0z' fill='%23000'/%3E%3C/svg%3E") 0 0 / 100% 100% no-repeat;
  pointer-events: none;
}
.xp-theme + .cta::before { display: none; }

/* Both waves track the heights the rest of the page uses at these widths.
   One variable each, so the offset cannot drift from the height. */
@media (max-width: 900px) {
  .section-alt.xp-theme::before { --lip-h: 30px; }
  .xp-theme:has(+ .cta)::after  { --lip-h: 28px; }
}
@media (max-width: 760px) {
  .section-alt.xp-theme::before,
  .xp-theme:has(+ .cta)::after { --lip-h: 26px; }
}

/* The chips carry the colour they jump to. A dot rather than a filled
   chip: celebrate is 2.4:1 against white and a chip filled with it could
   not be read at all, so the colour is a mark and the label stays navy
   until the chip is pointed at. */
/* Scoped to .xp-jump, not .jump. `.jump` is the site's chip list and other
   pages use it; a coloured dot appearing on every chip on the site is
   exactly the class collision this file has already paid for once. */
.xp-jump a { display: inline-flex; align-items: center; gap: 9px; }
.xp-jump a::before {
  content: "";
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--theme, var(--brand));
  flex: none;
}
.xp-jump a[href="#challenge"] { --theme: #e4572e; }
.xp-jump a[href="#reset"]     { --theme: #1b8a9c; }
.xp-jump a[href="#culture"]   { --theme: #8a6a3d; }
.xp-jump a[href="#celebrate"] { --theme: #d4a015; }
.xp-jump a[href="#skills"]    { --theme: #004c6d; }
.xp-jump a:hover { background: var(--theme-ink); color: #fff; }
.xp-jump a:hover::before { background: #fff; }

/* jump chips pick up a little life */
.jump a { transition: transform .15s ease, background .15s ease, color .15s ease; }
.jump a:hover { transform: translateY(-2px); }

/* ---------- school stages: numbered buoys ---------- */

.stage-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px; height: 30px;
  margin-bottom: 10px;
  font-size: .8rem;
  letter-spacing: 0;
  color: #fff;
  background: var(--sun);
  border-radius: 50%;
}

.outcome-group { position: relative; transition: transform .18s ease, box-shadow .18s ease; }
.outcome-group:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }

/* ---------- values / audience cards ---------- */

.value { transition: transform .18s ease, border-left-color .18s ease; }
.value:hover { transform: translateX(3px); border-left-color: var(--sun); }

.audience-card { position: relative; overflow: hidden; }
.audience-card::after {
  content: "";
  position: absolute;
  right: -30px; bottom: -30px;
  width: 120px; height: 120px;
  border-radius: 50%;
  background: var(--brand-light);
  opacity: .5;
  z-index: 0;
}
.audience-card > * { position: relative; z-index: 1; }

/* ---------- buttons ---------- */

.btn { position: relative; overflow: hidden; }
.btn::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, .16);
  transform: translateX(-101%);
  transition: transform .35s ease;
}
.btn:hover::after { transform: translateX(0); }
.btn > * { position: relative; }

/* ---------- quotes ---------- */

.quote { border-top: 3px solid var(--sun); }

/* ---------- table ---------- */

.table-values thead th { background: linear-gradient(90deg, var(--brand), var(--reef)); }

/* ---------- accessibility: honour the OS setting ---------- */

@media (prefers-reduced-motion: reduce) {
  .hero::before { animation: none; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .card img, .card::after, .btn::after, .jump a,
  .value, .outcome-group, .site-header, .logo img { transition: none; }
  .card:hover img { transform: none; }
  .progress { transition: none; }
  * { scroll-behavior: auto; }
}

/* ---------- narrow screens: decoration steps back ---------- */

@media (max-width: 760px) {
  .hero::before { height: 56px; background-size: 700px 56px; }
  .hero::after { background-size: 100% 52px, auto; }
  .hero .wrap { padding-bottom: 86px; }
  .hero-sm .wrap { padding-bottom: 76px; }
  .section-alt { padding-top: 76px; }
  .section-alt::before { height: 30px; background-size: 100% 30px; }
  .cta::before, .site-footer::before { height: 28px; background-size: 100% 28px; }
  .cta { padding-top: 68px; }
  .site-footer { padding-top: 58px; }
  .audience-card::after { display: none; }
}

/* logo never crowds the menu button on small screens */
.logo img { max-width: min(260px, 50vw); object-fit: contain; }
@media (max-width: 420px) {
  .logo img { height: 38px; }
  .nav-toggle { padding: 8px 10px; font-size: 1rem; }
}

/* fix: .nav a (0,1,1) was beating .btn (0,1,0), so the header Enquire
   button rendered dark-on-blue. Restore white on brand. */
.nav a.btn { color: #fff; }
.nav a.btn:hover { background: var(--brand-dark); color: #fff; }
.nav a.btn[aria-current="page"] { color: #fff; box-shadow: none; }

/* ================================================================
   LAYOUT v2 — structure taken from the current live site:
   coloured header band with a wavy lower edge, a strip of photographs
   in place of a single background image, and a split intro with a
   typographic wordmark.

   Same discipline as before: the strip is a grid and the wave is a
   masked pseudo-element, so no decoration is absolutely positioned
   outside its parent and nothing can escape the viewport.
   ================================================================ */

:root {
  --band: #a9dcf0;          /* header band — recolour freely */
  --band-ink: #12323f;      /* text on the band */
}

/* ---------- header band ---------- */

.site-header {
  background: var(--band);
  backdrop-filter: none;
  border-bottom: 0;
  overflow: visible;
}

.site-header::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -25px;
  height: 26px;
  background: var(--band);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 26' preserveAspectRatio='none'%3E%3Cpath d='M0 0c150 26 260 26 420 12S760 0 900 10s220 14 300 16V0z' fill='%23000'/%3E%3C/svg%3E") 0 0 / 100% 100% no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 26' preserveAspectRatio='none'%3E%3Cpath d='M0 0c150 26 260 26 420 12S760 0 900 10s220 14 300 16V0z' fill='%23000'/%3E%3C/svg%3E") 0 0 / 100% 100% no-repeat;
  pointer-events: none;
}

.site-header.scrolled { box-shadow: 0 2px 18px rgba(0, 41, 60, .14); }

.header-inner { gap: 18px; padding: 14px 24px 16px; }

.nav a { color: var(--band-ink); }
.nav a:hover { background: rgba(255, 255, 255, .6); color: var(--brand); }
/* --brand-light is mixed for a white page and goes muddy on the band, so the
   current page is tinted with the band's own light instead. Held a shade
   stronger than the hover above it, or the marker disappears the moment the
   visitor points at something else. */
.nav a[aria-current="page"] { color: var(--brand); background: rgba(255, 255, 255, .72); }

/* text links rather than platform logos — no third-party marks to license,
   and they stay legible at any size */
.social {
  display: flex;
  gap: 6px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.social a {
  display: block;
  padding: 7px 11px;
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--band-ink);
  background: rgba(255, 255, 255, .55);
  border-radius: 6px;
}
.social a:hover { background: #fff; color: var(--brand); }

/* ---------- photo strip ---------- */

.strip { padding: 0; overflow: clip; }

.strip-grid {
  display: grid;
  grid-template-columns: repeat(var(--panels, 4), 1fr);
  gap: 3px;
}
.strip .panel { overflow: hidden; }
.strip .panel img {
  width: 100%;
  height: clamp(220px, 30vw, 440px);
  object-fit: cover;
  transition: transform .6s ease;
}
.strip .panel:hover img { transform: scale(1.04); }

/* The column count follows the markup rather than being hard-coded per page:
   each rule matches "the Nth panel is also the last one". So changing the
   `count` passed to the strip partial is the only edit a layout change needs —
   home currently runs four, inner pages three.

   These live inside a min-width query on purpose. A `:has()` selector carries
   the specificity of its argument, so `.strip-grid:has(.panel:nth-child(4))`
   scores far above a bare `.strip-grid` and would beat the two-column phone
   rule below no matter which came last — four slivers on a phone. Confining
   them to wide screens means the narrow rule never has to win that fight. */
@media (min-width: 761px) {
  .strip-grid:has(.panel:nth-child(2):last-child) { --panels: 2; }
  .strip-grid:has(.panel:nth-child(3):last-child) { --panels: 3; }
  .strip-grid:has(.panel:nth-child(4):last-child) { --panels: 4; }
  .strip-grid:has(.panel:nth-child(5):last-child) { --panels: 5; }
}

/* ---------- page head (inner pages) ---------- */

.pagehead { padding: 52px 0 8px; }
.pagehead h1 { margin-bottom: .35em; }
.pagehead .lead {
  max-width: 64ch;
  font-size: 1.12rem;
  color: var(--ink-soft);
  margin-bottom: 0;
}

/* ---------- About: the page head and the intro as one block ----------

   About used to open with a page head and then an intro section under it, both
   a single column of text — which left the right-hand half of the page empty
   for about two screens before the first card. The home page had already
   solved that, with copy left and a column of brand and contact on the right,
   so this is that pattern rather than a second one: the logo, the phone
   number and the accreditation badge, right-aligned beside the copy.

   The logo is the header's own file, from the same field of the site
   document, so the client changing it in Pages changes both and the browser
   has it cached by the time this one is asked for. The badge is the home
   page's, for the same reason. Empty alt on the logo: the h1 beside it already
   says the company's name.

   `minmax(0, …)` on both tracks because a grid track's default minimum is
   min-content, and a 1024px-wide image would otherwise hold the second track
   open at 1024px and shove the copy off the page. */

/* The cards below open their own section at 76px, so this one does not need
   to close at 76px as well. */
.about-top { padding-bottom: 28px; }

.about-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 320px);
  gap: 24px 56px;
  align-items: start;
}

.about-copy h1 { margin-bottom: .35em; }
.about-copy .lead {
  max-width: 64ch;
  font-size: 1.12rem;
  margin-bottom: 1.1em;
}
.about-copy p { color: var(--ink-soft); }
.about-copy .lead { color: var(--ink); }

.about-side { text-align: right; }
.about-logo { width: 100%; height: auto; }
.about-side .contact-list,
.about-side .mark-contact h3 { text-align: right; }
/* `img { display: block }` at the top of this sheet, so text-align does not
   move the badge — an auto margin does. */
.about-side .badge-inline { margin-top: 26px; margin-left: auto; margin-right: 0; }

@media (max-width: 920px) {
  .about-grid { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  /* the column stops being a column, so stop pretending it is one */
  .about-side { text-align: left; }
  .about-side .contact-list,
  .about-side .mark-contact h3 { text-align: left; }
  .about-logo { max-width: 260px; }
  .about-side .mark-contact { margin-top: 22px; }
  .about-side .badge-inline { margin-left: 0; }
}

/* The header carries the same logo a couple of hundred pixels above this one,
   and on a phone that is most of the screen. Twice is once too many — the
   contact details and the badge stay. */
@media (max-width: 760px) {
  .about-logo { display: none; }
}

/* ---------- home intro: copy left, wordmark right ---------- */

.intro { padding-top: 60px; }

.intro-grid {
  display: grid;
  grid-template-columns: 1.05fr .95fr;
  gap: 56px;
  align-items: start;
}

.intro-copy .lead { font-size: 1.12rem; }
.intro-copy p { color: var(--ink-soft); }
.intro-copy .lead { color: var(--ink); }
.intro-actions { margin: 26px 0 0; }

.badge-inline {
  max-width: 190px;
  margin-top: 30px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 10px;
  background: #fff;
}

.intro-mark { text-align: right; }

.wordmark {
  display: flex;
  flex-direction: column;
  margin: 0 0 14px;
  font-weight: 700;
  line-height: .86;
  letter-spacing: -.035em;
  text-transform: uppercase;
  color: var(--ink);
}
.wordmark span:first-child { font-size: clamp(2.8rem, 7vw, 5.6rem); }
.wordmark span:last-child  { font-size: clamp(1.7rem, 4.2vw, 3.3rem); }

.wordmark-sub {
  margin: 0 0 22px;
  font-size: 1rem;
  color: var(--ink-soft);
}

.mark-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 0 14px;
}
.mark-links a {
  position: relative;
  padding: 4px 0;
  font-size: .95rem;
  font-weight: 700;
  text-decoration: none;
  color: var(--reef);
}
.mark-links a:hover { text-decoration: underline; }
.mark-links a + a::before {
  content: "";
  position: absolute;
  left: -8px; top: 50%;
  width: 1px; height: 14px;
  margin-top: -7px;
  background: var(--line);
}

/* ---------- responsive ---------- */

@media (max-width: 1080px) {
  .social a { padding: 6px 9px; font-size: .64rem; }
}

@media (max-width: 920px) {
  .intro-grid { grid-template-columns: 1fr; gap: 36px; }
  .intro-mark { text-align: left; order: -1; }
  .mark-links { justify-content: flex-start; }
  .strip .panel img { height: clamp(200px, 34vw, 320px); }
}

@media (max-width: 760px) {
  .social { display: none; }
  .strip-grid { --panels: 2; }     /* every strip drops to two panels on a phone */
  .panel-hide-sm { display: none; }
  .strip .panel img { height: 200px; }
  .site-header::after { bottom: -13px; height: 14px; }
  .pagehead { padding: 36px 0 4px; }
  .intro { padding-top: 40px; }
}

/* header row: the social chips are the first thing to go when space is tight */
.header-inner { flex-wrap: wrap; }
@media (max-width: 1024px) {
  .social { display: none; }
}

/* keep nav and social on one row: an auto margin on .nav ate the free space
   and pushed the chips to a second line */
.nav { margin-left: 0; }
.logo { margin-right: auto; }
.social { margin-left: 14px; }
@media (max-width: 760px) {
  .nav { margin-left: 0; }
  .logo { margin-right: auto; }
}

/* intro sits closer to the section below it */
.intro { padding-bottom: 26px; }
.badge-inline { margin-top: 24px; }

/* tighten the header row so nav + chips fit on one line above 1024px */
@media (min-width: 1025px) {
  .header-inner { gap: 12px; padding-right: 20px; }
  .nav { gap: 2px; }
  .nav a { padding: 8px 10px; font-size: .78rem; letter-spacing: .06em; }
  .nav .btn { margin-left: 6px; padding: 11px 18px; font-size: .76rem; }
  .social a { padding: 6px 9px; font-size: .62rem; letter-spacing: .08em; }
  .social { gap: 5px; margin-left: 10px; }
}

/* real logo arrived: full-colour artwork on a transparent background.
   The footer used to invert it to a white silhouette, which throws away the
   brand colours — give it a white chip instead. */
.footer-logo {
  filter: none;
  height: auto;
  width: 220px;
  max-width: 100%;
  padding: 12px 14px;
  background: #fff;
  border-radius: var(--radius);
}
.logo img { max-width: min(280px, 56vw); }
@media (max-width: 420px) { .logo img { height: 34px; } }

/* give the real logo a bit more room — it carries two lines of type */
.logo img { height: 54px; max-width: min(320px, 58vw); }
.site-header.scrolled .logo img { height: 44px; }
@media (max-width: 760px) { .logo img { height: 44px; } }
@media (max-width: 420px) { .logo img { height: 36px; } }

/* ================================================================
   HEADER: icon discs + the kayak that rides the wave
   ================================================================ */

/* ---------- social icon discs ---------- */

.social { align-items: center; }

.social .ico {
  position: relative;
  display: grid;
  place-items: center;
  width: 38px; height: 38px;
  padding: 0;
  border-radius: 10px;
  background: var(--brand);
  color: #fff;
  overflow: hidden;
  transition: transform .18s ease, background .18s ease;
}
.social .ico:hover,
.social .ico:focus-visible {
  transform: translateY(-2px);
  background: var(--brand-dark);
}

.social .ico img,
.social .ico svg {
  width: 20px; height: 20px;
  display: block;
  position: relative;
  z-index: 1;
}
/* The supplied brand marks are the platforms' full-colour tiles — each one is
   a coloured square with its glyph already on it, not a bare glyph. So they
   are shown as they come: no recolouring, no filter, no redrawing. An earlier
   rule here forced `brightness(0) invert(1)` to whiten a single-colour glyph;
   applied to these it turns each logo into a solid white square.

   The logo therefore *is* the disc: the blue background is dropped and the
   image fills the tile, clipped by the disc's own radius. The phone and map
   discs keep the blue, so the row reads as three brand marks and two of ours.
   A one-pixel inset ring keeps a white tile (TripAdvisor) from dissolving into
   the light blue header band. */
.social .ico.hasimg {
  background: transparent;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .10);
}
.social .ico.hasimg:hover,
.social .ico.hasimg:focus-visible { background: transparent; }
.social .ico.hasimg img {
  width: 100%;
  height: 100%;
  border-radius: inherit;
  object-fit: cover;
}

/* Fail-safe: the lettered label is what shows by default, and the image only
   appears once it has actually loaded (js adds .hasimg). So a missing brand
   file, a failed request or js not running all land on the same tidy result
   rather than a broken-image glyph. */
.social .ico img { display: none; }
.social .ico.hasimg img { display: block; }

.ico-fallback {
  position: relative;
  z-index: 1;
  display: block;
  font-size: .76rem;
  font-weight: 700;
  letter-spacing: .02em;
}
.social .ico.hasimg .ico-fallback { display: none; }

/* ---------- the kayak ---------- */

.site-header { position: sticky; }

:root {
  --kayak-hull: var(--brand);
  --kayak-crew: var(--sun);
  --kayak-cockpit: var(--brand-dark);
}

.kayak {
  position: absolute;
  left: 0; top: 0;
  width: 58px; height: 27px;
  z-index: 3;
  pointer-events: none;
  color: var(--brand);
  /* position lives on the individual translate/rotate properties so the bob
     keyframes can animate `transform` without wiping it */
  translate: -100px 0;
  transition:
    translate .62s cubic-bezier(.34, .8, .28, 1),
    rotate .62s cubic-bezier(.34, .8, .28, 1),
    opacity .3s ease;
  will-change: translate, transform;
}
.kayak svg { display: block; width: 100%; height: 100%; overflow: visible; }

/* a slow bob while it sits still, so it reads as floating rather than parked */
.kayak-bob { animation: bob 3.4s ease-in-out infinite; }
@keyframes bob {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50%      { transform: translateY(-2px) rotate(-1.2deg); }
}

/* The paddle dips as it travels. The origin is the grip — the middle of the
   shaft, in viewBox units — so the blades swing about the paddler's hands
   rather than about a corner of the drawing. Units are viewBox units because
   an SVG element's `transform-box` is `view-box` by default; do not reach for
   `fill-box` to shorten this, it is ignored on some SVG elements. The arc is
   deliberately shorter than it once was: past about 20° the upper blade swings
   over the paddler's head. */
.kayak.moving .paddle { animation: paddle .42s linear infinite; transform-origin: 25.3px 10px; }
@keyframes paddle {
  0%   { transform: rotate(-16deg); }
  50%  { transform: rotate(16deg); }
  100% { transform: rotate(-16deg); }
}

/* a ripple left behind when it arrives */
.kayak-wake {
  position: absolute;
  left: 0; top: 0;
  width: 26px; height: 8px;
  z-index: 2;
  pointer-events: none;
  border-radius: 50%;
  border: 1.5px solid var(--brand);
  opacity: 0;
}
.kayak-wake.go { animation: wake .85s ease-out 1; }
@keyframes wake {
  from { opacity: .55; transform: translate(var(--wx), var(--wy)) scale(.4); }
  to   { opacity: 0;   transform: translate(var(--wx), var(--wy)) scale(2.1); }
}

@media (prefers-reduced-motion: reduce) {
  .kayak { transition: none; translate: 0 0; }
  .kayak-bob, .kayak.moving .paddle, .kayak-wake.go { animation: none; }
  .kayak-wake { display: none; }
}

/* the header is too compact below this for the kayak to read */
@media (max-width: 760px) {
  .kayak, .kayak-wake { display: none; }
  .social { display: none; }
}
@media (max-width: 1024px) {
  .social { display: none; }
}

/* ================================================================
   WILDLIFE
   Coorong regulars, injected by site.js so page markup stays content-only.
   Every one lives inside a container that already carries overflow:clip,
   is aria-hidden, and takes no pointer events. Same rule as every other
   decoration here: nothing absolutely positioned escapes its parent.
   ================================================================ */

.fauna {
  position: absolute;
  z-index: 2;
  pointer-events: none;
  color: var(--brand-dark);
}
.fauna svg { display: block; width: 100%; height: 100%; }

/* ---------- birds crossing the header band ---------- */

/* They used to cross the photo strip, and that was the problem: a drawn
   silhouette sliding over a photograph of real pelicans reads as a smudge on
   the glass. The header band is a drawing, so that is where they belong.

   They get their own layer rather than being appended to the header, because
   `.site-header` carries `overflow: visible` so its wave lip can hang below
   it - clipping the header would take the lip with it. `.hdr-sky` fills the
   header, clips, and sits under the menu; `.header-inner` is lifted above it
   so a bird always passes behind the words and never over them. */
.hdr-sky {
  position: absolute;
  inset: 0;
  overflow: clip;
  pointer-events: none;
  z-index: 0;
}
.site-header .header-inner { position: relative; z-index: 1; }

/* On the band a bird needs no help standing out, and the white edge the
   photographs needed shows up here as a halo. */
.hdr-sky .bird { filter: none; }

.strip { position: relative; }

/* Size, height, speed, direction and flap are all set per bird from
   js/site.js, so every load gets different flocks. The variables below are
   only the fallback for a bird that arrives without them. */
.bird {
  width: 22px; height: 11px;
  top: 18%;
  left: -8%;
  /* A silhouette, not a white bird. The strip runs pale blue sky in one
     panel and near-white overcast in another, and white birds disappear
     into both — which is also why a real bird at that distance reads dark
     however pale it is. The faint light edge keeps them off the one dark
     band, the far dune. */
  color: #1d2f3a;
  filter: drop-shadow(0 0 1px rgba(255, 255, 255, .45));
  opacity: 0;
  will-change: transform, opacity;
  animation: fly var(--fly-dur, 26s) linear var(--fly-delay, 0s) infinite;
}

/* A bird is offstage for most of its cycle, so it reads as one passing
   rather than as a loop. The slight rise and fall across the crossing is
   what stops a flock looking like it is on rails. */
@keyframes fly {
  0%        { transform: translateX(0) translateY(0); opacity: 0; }
  4%        { opacity: var(--fly-peak, .75); }
  50%       { transform: translateX(60vw) translateY(-14px); opacity: var(--fly-peak, .75); }
  92%       { transform: translateX(124vw) translateY(4px); opacity: var(--fly-peak, .75); }
  96%, 100% { transform: translateX(130vw) translateY(6px); opacity: 0; }
}

/* Flocks heading the other way. Mirrored on the container so the bird faces
   its direction of travel; the wing flap is on the svg inside and is
   unaffected. */
.bird-rtl {
  left: auto; right: -8%;
  animation-name: fly-rtl;
}
@keyframes fly-rtl {
  0%        { transform: translateX(0) translateY(0) scaleX(-1); opacity: 0; }
  4%        { opacity: var(--fly-peak, .75); }
  50%       { transform: translateX(-60vw) translateY(-11px) scaleX(-1); opacity: var(--fly-peak, .75); }
  92%       { transform: translateX(-124vw) translateY(3px) scaleX(-1); opacity: var(--fly-peak, .75); }
  96%, 100% { transform: translateX(-130vw) translateY(5px) scaleX(-1); opacity: 0; }
}

/* wings: a small vertical squash reads as a flap at this size. Each bird gets
   its own period and phase — a flock beating in unison is a cartoon. */
.bird svg {
  animation: flap var(--flap-dur, 1.05s) ease-in-out var(--flap-delay, 0s) infinite;
  transform-origin: 50% 60%;
}
@keyframes flap {
  0%, 100% { transform: scaleY(1); }
  50%      { transform: scaleY(.55); }
}

/* ---------- waders standing on the sand-section wave lip ---------- */

.waders {
  width: 96px; height: 52px;
  right: 6%;
  top: 6px;
  opacity: .55;
}
.waders .wader-2 { opacity: .8; }

/* one of them dips for food now and then */
.waders .wader-1 { animation: dip 9s ease-in-out infinite; transform-origin: 14px 34px; }
@keyframes dip {
  0%, 62%, 100% { transform: rotate(0deg); }
  70%           { transform: rotate(16deg); }
  78%           { transform: rotate(0deg); }
  86%           { transform: rotate(12deg); }
}

/* ---------- sleepy lizard basking at a section edge ---------- */

.lizard {
  width: 66px; height: 28px;
  left: 4%;
  bottom: 16px;
  opacity: .5;
  transition: translate 1.1s cubic-bezier(.3, .9, .25, 1);
  translate: 0 0;
}
.lizard.scuttled { translate: 42px 0; }
.lizard .tail { animation: flick 7s ease-in-out infinite; transform-origin: 18px 10px; }
@keyframes flick {
  0%, 70%, 100% { transform: rotate(0deg); }
  80%           { transform: rotate(-7deg); }
  90%           { transform: rotate(5deg); }
}

/* ---------- accessibility and small screens ---------- */

@media (prefers-reduced-motion: reduce) {
  .bird { animation: none; opacity: .65; transform: none; }
  .bird svg, .waders .wader-1, .lizard .tail { animation: none; }
  .lizard { transition: none; }
  .lizard.scuttled { translate: 0 0; }
}

@media (max-width: 760px) {
  .lizard { display: none; }
  .waders { width: 52px; height: 28px; right: 4%; }
}

/* the one-line rationale each Stage 2 outcome group carries in the source doc */
.outcome-why {
  margin: -.4em 0 1em;
  font-size: .93rem;
  font-style: italic;
  color: var(--ink-soft);
}

/* ================================================================
   BOTTOM OF PAGE: one wave language, interlocking blocks
   ================================================================ */

/* The footer used to draw a WHITE wave across its own top edge. The block
   above it is the teal closing band, so that left a white stripe between two
   dark blocks and they read as unrelated. Instead the closing band now ends
   with a wave in the FOOTER's colour rising into it, so the two interlock. */

.site-footer::before { display: none; }

.cta::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 46px;
  background: var(--brand-dark);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 46' preserveAspectRatio='none'%3E%3Cpath d='M0 46V22c150 26 260 26 420 12S760 10 900 20s220 14 300 16v10z' fill='%23000'/%3E%3C/svg%3E") 0 0 / 100% 100% no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 46' preserveAspectRatio='none'%3E%3Cpath d='M0 46V22c150 26 260 26 420 12S760 10 900 20s220 14 300 16v10z' fill='%23000'/%3E%3C/svg%3E") 0 0 / 100% 100% no-repeat;
  pointer-events: none;
}
.cta { padding-bottom: 104px; }
.site-footer { padding-top: 56px; }

/* the same crest shape as the header, so every boundary on the page is
   recognisably the same wave rather than three different ones */
.section-alt::before,
.cta::before {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 46' preserveAspectRatio='none'%3E%3Cpath d='M0 0v24c150-26 260-26 420-12s340 24 480 14 220-14 300-16V0z' fill='%23ffffff'/%3E%3C/svg%3E");
  background-size: 100% 100%;
}
.section-alt::before { height: 46px; }
.cta::before { height: 46px; }

/* ---------- footer layout ---------- */

.footer-grid {
  grid-template-columns: 1.3fr .85fr .85fr;
  gap: 44px;
  align-items: start;
}

.site-footer h3 {
  margin-bottom: 14px;
  font-size: .78rem;
  letter-spacing: .14em;
}
.footer-sub { margin-top: 26px; }

.footer-list { list-style: none; margin: 0; padding: 0; }
.footer-list li { margin-bottom: 9px; line-height: 1.5; }
.footer-list a { text-decoration: none; }
.footer-list a:hover { text-decoration: underline; }

/* the logo and the accreditation badge now sit in matching panels, rather
   than one being a wide white block and the other a small square */
.footer-panel {
  display: inline-block;
  padding: 12px 14px;
  background: #fff;
  border-radius: var(--radius);
}
.footer-panel img { display: block; width: 100%; height: auto; }
.footer-panel { width: 224px; }
.footer-panel-badge { width: 132px; margin-top: 22px; padding: 10px; }

.footer-brand .footer-tag {
  margin: 18px 0 8px;
  font-weight: 700;
  color: #fff;
}
.footer-brand p { max-width: 34ch; }

/* ---------- footer bottom: echoes the header ---------- */

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
}
.footer-bottom p { margin: 0; }

.social-footer { margin: 0; }
.social-footer .ico {
  width: 34px; height: 34px;
  background: rgba(255, 255, 255, .13);
  color: #fff;
}
.social-footer .ico:hover { background: rgba(255, 255, 255, .26); }
/* same treatment as the header: the brand tile fills its disc, and against the
   dark footer the ring is white rather than black */
.social-footer .ico.hasimg { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .22); }
.social-footer .ico img { width: 100%; height: 100%; }

/* the header hides its icons on narrow screens; the footer keeps its own */
@media (max-width: 1024px) {
  .social-footer { display: flex; }
}

@media (max-width: 900px) {
  .footer-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 760px) {
  .footer-grid { grid-template-columns: 1fr; gap: 32px; }
  .cta { padding-bottom: 72px; }
  .cta::after { height: 26px; }
  .section-alt::before, .cta::before { height: 26px; }
  .footer-bottom { justify-content: flex-start; }
}

/* ================================================================
   THE PHOTO STRIP KEEPS THE ORDINARY POINTER.

   There were two custom cursors here, one replacing the other: a paddle
   blade, then a flying pelican drawn at 40px because the blade was
   illegible. Both are gone. A cursor that changes shape is a promise that
   something different happens if you click, and nothing different happens
   on the strip — so it read as a novelty and cost the visitor the one
   pointer they can always recognise.

   If a custom cursor is ever wanted again: the SVG in a url() must use
   single quotes, because a double quote terminates the CSS string and the
   whole declaration is dropped in silence.
   ================================================================ */

/* the two brand names were breaking mid-name in the footer column */
.footer-brand .footer-tag { font-size: .92rem; letter-spacing: 0; max-width: none; }



/* ---------- pelicans ---------- */

/* the pelican now stands in the shallows at the far end of the closing band,
   opposite the two floaters, so the water side has a group and the land side
   has its own */
.pelican-stand {
  width: 62px; height: 52px;
  right: 7%;
  bottom: 84px;
  color: var(--brand-dark);
  opacity: .45;
}

/* emus range through the Coorong, so one stands on the sand lip with the
   waders. Tall and narrow, which reads clearly even at this size. */
.emu {
  width: 46px; height: 60px;
  left: 7%;
  top: 2px;   /* the section clips its overflow, so it must sit fully inside */
  opacity: .5;
}

/* floating on the closing band. They sit just above the navy wave crest, so
   they read as being on the water rather than pasted on the colour. */
.pelican-float {
  color: var(--brand-dark);
  opacity: .5;
}
.pelican-float-a { width: 76px; height: 28px; left: 8%;  bottom: 96px; }
.pelican-float-b { width: 54px; height: 20px; left: 21%; bottom: 112px; opacity: .38; }

/* a slow bob, as if on a swell */
.pelican-float-a { animation: swell 7s ease-in-out infinite; }
.pelican-float-b { animation: swell 9s ease-in-out infinite -3s; }
@keyframes swell {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50%      { transform: translateY(-3px) rotate(-1deg); }
}

@media (prefers-reduced-motion: reduce) {
  .pelican-float-a, .pelican-float-b { animation: none; }
}

@media (max-width: 760px) {
  .pelican-stand { width: 48px; height: 40px; left: 5%; }
  .pelican-float-b { display: none; }
  .pelican-float-a { width: 56px; height: 21px; bottom: 66px; }
}


@media (max-width: 760px) {
  .emu { width: 34px; height: 44px; top: 4px; }
  .pelican-stand { width: 46px; height: 38px; bottom: 58px; }
}

/* enquiry form: honeypot stays out of sight and out of the tab order */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.form-sent { text-align: left; }
.form-sent h2 { margin-top: 0; color: var(--brand); }

/* a photo that has not been uploaded yet — see the note in site.js */
.img-pending {
  display: block;
  width: 100%;
  min-height: 180px;
  aspect-ratio: 4 / 3;
  border-radius: 10px;
  background:
    linear-gradient(135deg, rgba(0,76,109,.05), rgba(242,165,65,.10)),
    var(--sand, #f4ede1);
  border: 1px solid rgba(0,76,109,.10);
}

/* ---------- contact block on the home page ----------
   Shares partials/contact.php with the footer, so the details can only ever
   be edited in one place (Site-wide in the admin). The footer keeps its own
   look via .footer-list; this is the light version beside the wordmark. */

.mark-contact { margin-top: 30px; }
.mark-contact h3 {
  margin: 0 0 10px;
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--brand);
}
.contact-list { list-style: none; margin: 0; padding: 0; line-height: 1.7; }
.contact-list li { color: var(--ink); }
.contact-list a { color: var(--brand); text-decoration: none; }
.contact-list a:hover { text-decoration: underline; }

/*
 * One partial, two backgrounds.
 *
 * partials/contact.php renders in both places these details appear: the home
 * page, on white, and the footer, on navy. The three rules above are the white
 * one's — and because they sit later in this file than
 * `.site-footer a { color: #fff }`, at equal specificity, they won in the
 * footer too. The result was the owner's name and the street address in
 * near-black on navy, and the phone number and email in brand navy on navy:
 * the one part of the footer a customer is actually looking for, invisible.
 *
 * Scoped to the footer rather than changed above, because the home page's
 * version is right and this is the exception. The partial stays the single
 * source of the phone number, which is the whole point of it — a number that
 * is correct in the footer and a year stale halfway up the home page is
 * exactly what it exists to prevent.
 *
 * Not #fff for the plain lines: the footer's own body colour is
 * rgba(255,255,255,.84) on this navy, which is still about 8.9:1, and matching
 * it keeps the contact column reading as part of the footer rather than
 * shouting over the headings above it. Links get full white, like every other
 * link down here.
 */
.site-footer .contact-list li { color: rgba(255, 255, 255, .84); }
.site-footer .contact-list a { color: #fff; }

/* the home-page column is right-aligned; the footer's is not */
.intro-mark .contact-list,
.intro-mark .mark-contact h3 { text-align: right; }

@media (max-width: 920px) {
  /* the wordmark column goes left-aligned below this width, so follow it */
  .intro-mark .contact-list,
  .intro-mark .mark-contact h3 { text-align: left; }
}

/* ==================== drawn backgrounds ====================

   Two scenes, from partials/scene.php: the Coorong dunes behind the home
   page's intro, and the Murray behind the School Programs page head.

   They sit under the content rather than beside it, so three things have to
   be true or they break out or cover the words:

   1. The section must clip. Every .section already does; .pagehead did not,
      which is why .has-scene adds it — without it the dune runs on down the
      page, which is the trap this stylesheet already records for the other
      decoration.
   2. The section must be a positioning context, and so must the .wrap, or the
      absolutely-positioned scene paints over the text rather than under it.
      A positioned element beats an unpositioned one whatever the source order.
   3. Nothing in the scene may take a pointer or a caret.
   ============================================================ */

.scene {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  user-select: none;
}
.section.intro > .wrap,
.pagehead.has-scene > .wrap { position: relative; }

/* .pagehead is not in the overflow:clip list at the top of this file, and the
   river reaches past it. It also needs room underneath, or the gums are
   cropped at the knees by a section that was only ever as tall as three lines
   of text. */
.pagehead.has-scene {
  position: relative;
  overflow: clip;
  overflow: hidden;
  padding-bottom: 104px;
}

/* A page head is a single column of text with no gutter beside it, so a
   pelican ends up behind the lead rather than next to it. The dune carries the
   band on its own. The birds stay on the home page, whose two-column intro
   leaves them a gap to stand in — which is where they were placed. */
.pagehead.has-scene .sc-birds { display: none; }

/* A narrow viewport crops the sides of a scene and scales up what is left, so
   the pelicans arrive at roughly twice the size they were drawn and land on
   the wordmark. The land still reads at that scale; the birds do not survive
   it, so they go — the same call this stylesheet already makes for the kayak
   below this width. The gums are large enough that the crop suits them. */
@media (max-width: 760px) {
  .sc-birds { display: none; }
  .scene { opacity: .85; }
  .pagehead.has-scene { padding-bottom: 72px; }
}


/* ---------- a scene spanning more than one section ----------

   .scene-band wraps two sections so one drawing runs behind both, used on
   School Programs for the page head and the stages beneath it. The band clips,
   and the sections inside are positioned — .section already is, .pagehead is
   not, and an unpositioned child paints under an absolutely-positioned sibling
   whatever the source order. */

.scene-band {
  position: relative;
  overflow: clip;
  overflow: hidden;
}
.scene-band > section { position: relative; }
.scene-band > .pagehead { padding-bottom: 8px; }

/* ---------- where a scene band meets the section under it ----------

   Nothing here. Each tall scene draws its own sand-coloured wave along its
   bottom edge, in the exact colour of the section below, so the handover
   happens inside the drawing.

   The wave lip is suppressed rather than recoloured. Recolouring it worked for
   one band — the river resolves to a flat #e6f2f4 — but it is a constant in a
   stylesheet that has to be kept in step with the opacity of a band of water
   in an SVG, and the dune band does not resolve to one colour at all: it is
   water on the left and sand on the right. A scene that owns its own edge has
   neither problem. */

.scene-band + .section-alt::before { display: none; }


/* ---------- birds crossing a scene ----------

   The same idea as the flocks over the photo strip, and for the same reason:
   three fixed birds on a still drawing read as decoration, and a bird that
   crosses reads as a bird. Each one gets its own duration and its own phase —
   a flock beating in unison is a cartoon, which is the note site.js already
   makes about the flocks.

   No wingbeat. There was one, and it was the bouncing: `transform-box:
   fill-box` does not take on a <use>, so scaleY resolved about the SVG's own
   origin instead of the bird's centre and threw each one 100 to 157 pixels up
   and down every cycle — measured, not guessed. A bird at this size and this
   opacity does not need beating wings anyway, and a soaring bird should not
   have them: these glide, which is what they were asked to do.

   These translate in user units, so a bird crosses the drawing rather than the
   viewport, and the band's own overflow:clip takes care of the exit. Transform
   and opacity only: no layout, no paint, cheap enough to leave running. */

.sc-fly { animation: sc-cross 54s linear infinite; }

/* Straight across, and level.
   This used to rise and fall a little on the way over. It reads as bouncing
   rather than as gliding, which is the opposite of what a pelican or a kite
   does over open water — they hold a line and let the wings do the work. The
   only movement now is the wingbeat. */
@keyframes sc-cross {
  from { transform: translateX(-420px); }
  to   { transform: translateX(1640px); }
}

.sc-fly-1 { animation-duration: 62s; animation-delay:  -4s; }
.sc-fly-2 { animation-duration: 78s; animation-delay: -31s; }
.sc-fly-3 { animation-duration: 47s; animation-delay: -12s; }
.sc-fly-4 { animation-duration: 53s; animation-delay: -38s; }

/* Asked for stillness, get stillness — and the birds stay where they were
   drawn rather than an empty sky. */
@media (prefers-reduced-motion: reduce) {
  .sc-fly { animation: none; }
}

/* ---------- cloud ----------

   Alternating, not looping. A cloud 420 units wide cannot be snapped back to
   its start without the jump being the most visible thing on the page, so it
   eases one way and eases back. Minutes per pass — slow enough that it reads
   as weather rather than as an animation, and you only catch it if you stop
   and look. Different distances and periods so the three never line up. */

.sc-drift { animation: sc-drift 240s ease-in-out infinite alternate; }
@keyframes sc-drift {
  from { transform: translateX(0); }
  to   { transform: translateX(96px); }
}
.sc-drift-1 { animation-duration: 260s; }
.sc-drift-2 { animation-duration: 340s; animation-delay: -70s; }
.sc-drift-3 { animation-duration: 195s; animation-delay: -30s; }

@media (prefers-reduced-motion: reduce) {
  .sc-drift { animation: none; }
}


/* ================================================================
   THE DUNES IN THE HEADER BAND

   The band was a flat sky-blue strip with a wave lip under it and the kayak
   sailing along that wave. It is now a view across the channel: pale sky at
   the top, a range of dunes with scrub along the ridge, and the water below
   them - which the kayak is already sitting on.

   **The water is the band's own `--band`, not a colour drawn in the SVG.**
   That is deliberate and it is the whole reason this works.
   `.site-header::after` - the wave lip that hangs below the header, and that
   `site.js` samples to float the kayak on - is filled with `var(--band)`. If
   the drawing painted its own water, that colour and the lip's would be two
   constants that have to be kept in step, which is exactly the trap the river
   band fell into on the public pages. So the SVG paints a white sky *wash*
   over the top instead and simply stops above the waterline. Recolour
   `--band` and the sky, the water and the lip all move together.

   Far range only, no near dunes. On the right the beach comes forward and the
   sand runs down to meet the wave lip with no water between them, which is
   where the waders and the reeds live: six birds and eleven clumps of water
   grass standing on the waterline, placed by sampling the shoreline path with
   `getPointAtLength` so they sit on the curve rather than near it. Reeds stop
   at x 1290 - right of that the sand meets the lip and there is no water for
   them to stand in.

   **Ten trees on the ridge, 9 to 17 units tall - 6 to 12px on screen.** `gum`
   and `pine` are lifted from `partials/scene.php` verbatim rather than
   redrawn, so the header cannot drift into a second visual style; at this
   reduction their twenty-odd crown ellipses simply merge into the right
   silhouette, which is what a distant tree looks like anyway. They carry about
   2.5KB of the data URI and they are worth it. They get smaller to the left
   because the ridge recedes that way.

   **A tree on the ridge comes out smaller than a wader on the shoreline, and
   that is correct.** The ridge is across the water and the shoreline is near;
   that gap is the depth of the picture. Do not "fix" it by growing the trees.

   Their colour is a grey-green, not the navy the public scenes use for scrub.
   Same reason the scrub clumps had to go: anything standing on the ridge is
   mostly silhouetted against the **sky**, and a cool wash over sky blue
   disappears. Check a new element against what is behind it, not what it
   stands on.

   **Two dunes, not one.** A second wavy crest runs through the sand: the far
   range is shaded a shade deeper down to that line, and everything below it -
   the near dune and the beach - is left at the plain sand colour. It is one
   translucent path, not a second sand shape, and that is deliberate for two
   reasons. The near crest has to stay below the far ridge or the depth
   reverses, and above the waterline or the shading spills into the channel;
   both are asserted against the sampled paths when the drawing is generated.
   And **the bottom-right beach must keep the exact colour `--dune-sand`
   names**, because that is where the wave lip's own sand wedge meets it -
   shading the near dune instead of the far one would have put a seam there.

   **Three sizes have to agree here too.** The kayak is 58x27 CSS px on an
   84px band, which is 83x39 in viewBox units; the waders are 15-26 units
   tall. The kayak is the immediate foreground and the birds are across the
   water, so the birds stay well under half its height. Change one and check
   it against the other, in the browser.

   Where the beach meets the lip is fixed to the drawing, but where the Enquire
   button sits is not: `.header-inner` is a centred `max-width`, so at 1100 the
   button is 265px from the right edge and at 1920 it is 635px. The sand
   reaches the lip in the rightmost ~400px at every width, which puts it just
   right of Enquire at about 1440 and further out on a wide screen. That is as
   close as a background image can track a flex-positioned button.

   **The scrub is the ridge's own profile going rough, not clumps sitting on
   it.** The first pass used the `bush` symbol from `partials/scene.php` at
   navy/.11, the way the public scenes do, and it did not work - the reason is
   worth keeping. Those clumps stand *on* the ridge, so most of each one is
   silhouetted against the sky rather than against sand, and a faint navy wash
   over sky blue is a pale blue dome with spikes, not a bush. There is no room
   in an 84px band to draw a bush that reads as a bush, so the ridge line is
   tufted instead: bumps in the sand's own colour, inside the same group and
   at the same opacity as the dune, so there is nothing to misread and no
   overlap composited twice. Their bases overlap the ridge by 1.5 units so no
   hairline can open up along it.

   The drawing keeps its aspect ratio (`auto 100%`) and is anchored bottom
   right, so a narrow window crops it from the left rather than squashing it.
   A mask fades that left edge, so the crop never shows a hard edge and the
   wordmark always has plain sky behind it.

   Watch, if it is ever redrawn: the crest has to leave sky above it at
   *every* width. Tying the height to the band means a narrower window shows a
   bigger crop of the right-hand end, and a crest that clears the top at 1440
   is cut off at 1100. Checked at 1440, 1100 and 390.

   No version bump needed here - `asset()` stamps this file with its own mtime.
   ================================================================ */

:root { --dunes-band: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1600 120'%3E%3Cdefs%3E%3Csymbol id='r' viewBox='0 0 30 40'%3E%3Cpath d='M15 40 C13.4 27 10.6 15 6.4 4 L9.2 3 C13.2 14.6 15.8 27 16.4 40 Z'/%3E%3Cpath d='M15 40 C14.6 27 14.2 15 13.4 2 L16.2 2 C16.4 15 16.4 27 16.4 40 Z'/%3E%3Cpath d='M15 40 C16.6 27 19.4 15.6 23.4 5 L26 6.2 C21.8 16.4 18.4 27.4 17.4 40 Z'/%3E%3Cpath d='M15 40 C16 30 17.6 21 20 12.6 L22.2 13.6 C19.6 22 18 30 17.6 40 Z'/%3E%3Cpath d='M15 40 C13.6 30 11.4 22 8 14 L10.4 12.8 C13.6 21 15.6 30 16.2 40 Z'/%3E%3C/symbol%3E%3Csymbol id='w' viewBox='0 0 44 58'%3E%3Cpath d='M17.8 29.4 L19.2 29.4 L18.4 52.8 L17 52.8 Z'/%3E%3Cpath d='M23 29.4 L24.4 29.4 L25.6 52.8 L24.2 52.8 Z'/%3E%3Cpath d='M15 52.2 L19.6 52.2 L19.6 53.6 L15 53.6 Z'/%3E%3Cpath d='M23.4 52.2 L28 52.2 L28 53.6 L23.4 53.6 Z'/%3E%3Cpath d='M4.6 21.4 L13 24.6 L11.2 28.4 Z'/%3E%3Cellipse cx='19.2' cy='25.2' rx='12' ry='5.9'/%3E%3Cpath d='M24.2 21.8 C 26 17.2 27.8 14 29.8 11.8 L 32.2 13.8 C 30.4 16 29 19 28.2 22.4 Z'/%3E%3Ccircle cx='31.4' cy='10.6' r='3.1'/%3E%3Cpath d='M33.8 9.4 L43.4 7.2 L43.6 8.6 L34.2 11.9 Z'/%3E%3C/symbol%3E%3Csymbol id='f' viewBox='0 0 44 58'%3E%3Cpath d='M17.8 27.4 L19.2 27.4 L18.4 52.8 L17 52.8 Z'/%3E%3Cpath d='M23 27.4 L24.4 27.4 L25.6 52.8 L24.2 52.8 Z'/%3E%3Cpath d='M15 52.2 L19.6 52.2 L19.6 53.6 L15 53.6 Z'/%3E%3Cpath d='M23.4 52.2 L28 52.2 L28 53.6 L23.4 53.6 Z'/%3E%3Cpath d='M4.6 18.4 L13 21.6 L11.2 25.4 Z'/%3E%3Cellipse cx='19.2' cy='22.6' rx='12' ry='5.9'/%3E%3Cpath d='M25.6 18.6 C 29 18.6 31.6 20.4 33 23.2 L 30.4 25.2 C 29.4 23.2 27.8 22.2 25.8 22.4 Z'/%3E%3Ccircle cx='33.2' cy='25.4' r='3'/%3E%3Cpath d='M34.6 27.6 L38.8 35.8 L37.4 36.4 L32.6 28.8 Z'/%3E%3C/symbol%3E%3ClinearGradient id='sky' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23fff' stop-opacity='.55'/%3E%3Cstop offset='.50' stop-color='%23fff' stop-opacity='.24'/%3E%3Cstop offset='.72' stop-color='%23fff' stop-opacity='0'/%3E%3C/linearGradient%3E%3ClinearGradient id='gh' x1='0' y1='0' x2='1' y2='0'%3E%3Cstop offset='0' stop-color='%23000'/%3E%3Cstop offset='.12' stop-color='%23232323'/%3E%3Cstop offset='.50' stop-color='%23fff'/%3E%3C/linearGradient%3E%3Cmask id='mh'%3E%3Crect width='1600' height='120' fill='url(%23gh)'/%3E%3C/mask%3E%3Csymbol id='g' viewBox='0 0 220 300'%3E%3Cpath d='M86 300 C 89 252 91 218 95 190 L 119 189 C 123 218 125 252 128 300 Z' fill='currentColor'/%3E%3Cg stroke='currentColor' fill='none' stroke-linecap='round'%3E%3Cpath d='M104 186 L84 150 L62 118 L44 92' stroke-width='16'/%3E%3Cpath d='M112 186 L136 150 L160 120 L180 96' stroke-width='15'/%3E%3Cpath d='M107 192 L103 146 L106 110 L110 80' stroke-width='11'/%3E%3Cpath d='M90 162 L68 142 L50 132' stroke-width='7'/%3E%3Cpath d='M130 164 L154 148 L174 140' stroke-width='7'/%3E%3C/g%3E%3Cg fill='currentColor'%3E%3Cellipse cx='81' cy='146' rx='20' ry='14'/%3E%3Cellipse cx='73' cy='134' rx='22' ry='16'/%3E%3Cellipse cx='62' cy='119' rx='24' ry='17'/%3E%3Cellipse cx='40' cy='98' rx='26' ry='19'/%3E%3Cellipse cx='150' cy='145' rx='20' ry='14'/%3E%3Cellipse cx='161' cy='121' rx='22' ry='16'/%3E%3Cellipse cx='164' cy='109' rx='24' ry='17'/%3E%3Cellipse cx='176' cy='103' rx='26' ry='19'/%3E%3Cellipse cx='95' cy='132' rx='20' ry='14'/%3E%3Cellipse cx='101' cy='126' rx='22' ry='16'/%3E%3Cellipse cx='112' cy='96' rx='24' ry='17'/%3E%3Cellipse cx='114' cy='81' rx='26' ry='19'/%3E%3Cellipse cx='112' cy='62' rx='26' ry='19'/%3E%3Cellipse cx='74' cy='78' rx='23' ry='17'/%3E%3Cellipse cx='150' cy='82' rx='24' ry='17'/%3E%3Cellipse cx='34' cy='99' rx='18' ry='13'/%3E%3Cellipse cx='190' cy='101' rx='17' ry='12'/%3E%3Cellipse cx='96' cy='109' rx='21' ry='15'/%3E%3Cellipse cx='128' cy='111' rx='19' ry='14'/%3E%3Cellipse cx='58' cy='125' rx='16' ry='12'/%3E%3Cellipse cx='166' cy='127' rx='15' ry='11'/%3E%3Cellipse cx='40' cy='120' rx='13' ry='9'/%3E%3Cellipse cx='184' cy='124' rx='12' ry='9'/%3E%3Cellipse cx='64' cy='144' rx='11' ry='8'/%3E%3Cellipse cx='160' cy='146' rx='11' ry='8'/%3E%3C/g%3E%3C/symbol%3E%3Csymbol id='p' viewBox='0 0 120 300'%3E%3Cpath d='M54 300 C 55 270 56 250 57 234 L 65 234 C 66 250 67 270 68 300 Z' fill='currentColor'/%3E%3Cg fill='currentColor'%3E%3Cellipse cx='60' cy='238' rx='39' ry='30'/%3E%3Cellipse cx='59' cy='229' rx='38' ry='29'/%3E%3Cellipse cx='58' cy='219' rx='36' ry='28'/%3E%3Cellipse cx='62' cy='208' rx='35' ry='27'/%3E%3Cellipse cx='58' cy='196' rx='33' ry='26'/%3E%3Cellipse cx='60' cy='184' rx='31' ry='24'/%3E%3Cellipse cx='62' cy='171' rx='29' ry='23'/%3E%3Cellipse cx='58' cy='158' rx='27' ry='21'/%3E%3Cellipse cx='60' cy='145' rx='25' ry='19'/%3E%3Cellipse cx='61' cy='131' rx='23' ry='18'/%3E%3Cellipse cx='58' cy='118' rx='20' ry='16'/%3E%3Cellipse cx='59' cy='104' rx='18' ry='14'/%3E%3Cellipse cx='61' cy='89' rx='15' ry='12'/%3E%3Cellipse cx='60' cy='75' rx='13' ry='11'/%3E%3Cellipse cx='61' cy='61' rx='9' ry='11'/%3E%3Cellipse cx='58' cy='46' rx='5' ry='11'/%3E%3C/g%3E%3C/symbol%3E%3C/defs%3E%3Cg mask='url(%23mh)'%3E%3Crect width='1600' height='120' fill='url(%23sky)'/%3E%3Cg fill='%23ecdcba' opacity='.92'%3E%3Cpath d='M0 82 C 140 80 250 75 380 73 C 490 71 540 77 650 74 C 760 71 810 63 920 60 C 1010 57 1060 62 1150 58 C 1240 54 1290 45 1390 42 C 1470 40 1540 42 1600 41 L1600 120 C 1500 120 1400 119 1300 118 C 1215 116 1160 104 1105 95 C 1065 89 1032 88 1000 88 C 860 89 700 90 560 91 C 330 92 150 92 0 93 Z'/%3E%3Cpath d='M560 76.2q11 -14.3 23 0ZM572 76.3q9 -9.9 18 0ZM585 76.4q6 -10.0 13 0ZM603 76.3q5 -7.0 10 0ZM620 76.1q9 -12.5 17 0ZM632 75.9q10 -11.2 21 0ZM653 75.4q12 -9.3 24 0ZM669 74.9q9 -11.8 18 0ZM681 74.4q8 -12.3 17 0ZM699 73.7q9 -13.3 19 0ZM722 72.5q6 -11.1 13 0ZM737 71.6q9 -13.2 18 0ZM754 70.5q7 -8.9 14 0ZM773 69.3q7 -7.2 14 0ZM795 67.8q11 -8.3 22 0ZM820 66.1q9 -29.7 18 0ZM831 65.4q8 -6.5 16 0ZM853 64.2q12 -13.1 24 0ZM872 63.2q12 -12.6 24 0ZM897 62.2q8 -14.1 15 0ZM911 61.7q12 -14.3 23 0ZM924 61.4q9 -7.7 17 0ZM947 60.8q7 -9.8 14 0ZM965 60.6q7 -13.8 15 0ZM989 60.5q10 -9.8 20 0ZM1013 60.6q9 -8.3 19 0ZM1030 60.8q10 -11.0 21 0ZM1053 61.1q6 -11.6 12 0ZM1073 61.1q11 -8.4 22 0ZM1085 61.1q9 -10.9 18 0ZM1104 60.9q8 -10.1 17 0ZM1115 60.7q8 -26.1 15 0ZM1129 60.3q10 -7.8 20 0ZM1147 59.6q6 -12.2 11 0ZM1168 58.6q9 -11.0 18 0ZM1183 57.6q11 -7.0 23 0ZM1207 56.0q8 -12.8 17 0ZM1227 54.4q7 -9.0 14 0ZM1243 53.1q12 -9.2 23 0ZM1260 51.6q11 -10.3 21 0ZM1275 50.4q7 -7.0 14 0ZM1290 49.1q11 -18.7 22 0ZM1303 48.1q9 -10.0 18 0ZM1318 47.0q11 -8.4 22 0ZM1338 45.7q5 -13.1 11 0ZM1355 44.9q6 -25.9 12 0ZM1372 44.1q10 -18.0 20 0ZM1393 43.4q6 -14.5 12 0ZM1406 43.1q5 -22.2 10 0ZM1424 42.9q10 -11.1 20 0ZM1448 42.6q9 -11.3 18 0ZM1461 42.6q6 -13.5 11 0ZM1478 42.6q7 -11.5 14 0ZM1502 42.6q8 -9.3 16 0ZM1524 42.7q11 -8.9 23 0ZM1550 42.8q12 -7.4 24 0ZM1572 42.8q11 -6.6 22 0ZM1594 42.6q10 -10.8 21 0Z'/%3E%3C/g%3E%3Cpath d='M0 82 C 140 80 250 75 380 73 C 490 71 540 77 650 74 C 760 71 810 63 920 60 C 1010 57 1060 62 1150 58 C 1240 54 1290 45 1390 42 C 1470 40 1540 42 1600 41 L1600 62 C 1545 61 1510 58 1480 60 C 1440 63 1410 68 1380 68 C 1340 69 1310 72 1280 74 C 1245 76 1210 73 1180 72 C 1145 71 1110 76 1080 78 C 1045 80 1010 81 980 82 C 945 83 910 84 880 84 C 840 84 800 83 760 84 C 715 85 660 86 620 86 C 565 87 510 87 460 87 C 400 87 340 87 280 87 C 190 87 90 88 0 88 Z' fill='%23c9ab74' opacity='.24'/%3E%3Cg fill='%236e7a63' opacity='.50'%3E%3Cuse href='%23p' x='952' y='51.2' width='3.6' height='9'/%3E%3Cuse href='%23g' x='1002' y='50.1' width='7.3' height='10'/%3E%3Cuse href='%23p' x='1042' y='51.4' width='3.6' height='9'/%3E%3Cuse href='%23g' x='1176' y='45.6' width='8.8' height='12'/%3E%3Cuse href='%23p' x='1212' y='44.2' width='4.4' height='11'/%3E%3Cuse href='%23p' x='1352' y='29.5' width='6.0' height='15'/%3E%3Cuse href='%23g' x='1388' y='27.1' width='11.7' height='16'/%3E%3Cuse href='%23p' x='1428' y='28.3' width='5.6' height='14'/%3E%3Cuse href='%23g' x='1468' y='25.1' width='12.5' height='17'/%3E%3Cuse href='%23p' x='1512' y='29.2' width='5.2' height='13'/%3E%3C/g%3E%3Cg fill='%236f7d5c' opacity='.34'%3E%3Cuse href='%23r' x='620' y='80.6' width='17' height='12'/%3E%3Cuse href='%23r' x='664' y='73.6' width='23' height='19'/%3E%3Cuse href='%23r' x='741' y='77.5' width='19' height='14'/%3E%3Cuse href='%23r' x='820' y='74.2' width='19' height='17'/%3E%3Cuse href='%23r' x='895' y='73.7' width='22' height='17'/%3E%3Cuse href='%23r' x='939' y='77.8' width='15' height='13'/%3E%3Cuse href='%23r' x='983' y='73.4' width='20' height='17'/%3E%3Cuse href='%23r' x='1021' y='76.5' width='22' height='14'/%3E%3Cuse href='%23r' x='1109' y='82.3' width='22' height='15'/%3E%3C/g%3E%3Cg fill='%231d2f3a'%3E%3Cuse href='%23w' x='884' y='69.8' width='17' height='22' opacity='0.30'/%3E%3Cuse href='%23f' x='916' y='73.6' width='14' height='18' opacity='0.24'/%3E%3Cuse href='%23w' x='946' y='76.4' width='11' height='15' opacity='0.19'/%3E%3Cuse href='%23w' x='1090' y='69.9' width='20' height='26' opacity='0.30'/%3E%3Cuse href='%23f' x='1128' y='80.9' width='16' height='21' opacity='0.24'/%3E%3Cuse href='%23w' x='1162' y='90.6' width='13' height='17' opacity='0.19'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); }

.site-header {
  background-image: var(--dunes-band);
  background-repeat: no-repeat;
  background-position: right bottom;
  background-size: auto 100%;
}

/* the band is scenery, not information */
@media print { .site-header { background-image: none; } }


/* ================================================================
   THE HEADER'S ENQUIRE BUTTON

   Two things, and the first is a bug that had been sitting there.

   **`.btn` asks for `border-radius: 999px` and never got it.** `.nav a` sets
   `border-radius: 6px`, and `.nav a` (0,1,1) outranks `.btn` (0,1,0), so the
   pill has been rendering as a rounded rectangle in the header - and nowhere
   else, because nowhere else is a `.btn` also a `.nav a`. This is the *same*
   specificity collision that ate the button's white text, which is fixed
   further up this file with a comment about `.nav a` beating `.btn`; the
   radius was missed at the time. Anything else `.btn` sets that `.nav a` also
   sets will lose the same way - check both when adding to either.

   **And it was 46px tall against 37px for the links**, which made it tower
   over the row rather than lead it. 42px sits it between the two.

   `.nav a.btn` is (0,2,1), so it beats both `.btn` and the `.nav .btn` rule in
   the >=1025px block whatever the source order. The shrink is kept inside that
   block on purpose: below it the nav becomes a dropdown, where the button is a
   tap target and 46px is the right size for one.
   ================================================================ */

.nav a.btn { border-radius: 999px; }

@media (min-width: 1025px) {
  .nav a.btn { padding: 9px 17px; }
}


/* ================================================================
   THE BEACH CONTINUES INTO THE WAVE LIP

   The drawing stops at the header's bottom edge, because a background image
   is clipped to its own box. The wave lip - `.site-header::after`, hanging
   26px below the header - is a separate element, so at the right-hand end the
   sand ran down to the header's edge and then turned back into water for the
   last 26px. What should be one beach meeting one waterline was a beach, a
   blue strip, and then the wave.

   So the lip carries the end of the beach itself: a sand wedge anchored to the
   right edge, feathered out over the 90px to its left, painted over the band
   colour and then cut by the same wave mask as everything else. The drawing's
   sand reaches the bottom of its canvas from about x 1300 to 1600, which is a
   wider stretch than the wedge at any band height the header takes - so the
   wedge always has sand directly above it and the two read as one shape.

   **`--dune-sand` is the one constant this costs**, and it is the composite of
   the SVG's `#ecdcba` at `.92` over `--band`, worked out once rather than
   guessed. If either the fill, that opacity or `--band` changes, this value
   has to change with them or the beach will show a seam exactly where the
   header ends. That is the trap the river band fell into on the public pages,
   accepted here deliberately because a pseudo-element cannot be reached by the
   drawing any other way - but it is the only place in this stylesheet where a
   colour is duplicated, and it should stay that way.
   ================================================================ */

:root { --dune-sand: rgba(236, 220, 186, .92); }

.site-header::after {
  background-color: var(--band);
  background-image: linear-gradient(to left,
    var(--dune-sand) 0, var(--dune-sand) 150px, transparent 240px);
}


/* ================================================================
   THE ENQUIRE BUTTON ON THE ENQUIRE PAGE

   White text on a near-white pill: unreadable, and live.

   `.nav a[aria-current="page"]` sets `background: rgba(255,255,255,.72)` so
   the current page reads as a light tint on the band. `.nav a.btn[aria-current]`
   is more specific and sets the text white - but it never set a background,
   so the tint from the less specific rule still applied and white type landed
   on 72% white.

   **This is the third time `.nav a` has beaten `.btn`** - it took the button's
   white text once, its pill radius once, and now its fill. The pattern is
   always the same: a property `.btn` owns that `.nav a` also sets. When
   touching either, check what the other declares.
   ================================================================ */

.nav a.btn[aria-current="page"] {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}
.nav a.btn[aria-current="page"]:hover {
  background: var(--brand-dark);
  border-color: var(--brand-dark);
}


/* Said to a screen reader, never drawn. Used by ext_note() so a link that
   opens a new tab announces that it will, without putting the words on the
   page beside every external link. Clipped rather than display:none, because
   display:none is not read out. */
.vh {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}


/* ================================================================
   SCHOOL PROGRAMS — the river journey, and the educator half
   ================================================================

   The page has two readers and one of them was eating the other. A teacher
   books the trip, so the learning outcomes have to be here in full; a
   teacher also has to want to come, and four screens of bulleted terms is a
   syllabus, not an invitation. So the page is split: the three stages are a
   journey down a river at the top, and the outcomes sit below it, folded
   away until asked for.

   Nothing here adds a word of copy. Every string on the journey is the
   stage name, the year levels and the duration line the content store
   already held; the label on the educator half is the page head's own
   eyebrow.

   ONE RIVER ON THE PAGE. This was built first with the tall river scene
   behind the journey as well as the head, and it does not work: that
   drawing's water is a horizontal band across the page, the journey's is a
   ribbon running down it, and where they met the reader got two rivers at
   right angles. The page head carries the short river scene, the way
   /contact does, and below it the journey owns the water outright.
   ================================================================ */

/* ---------- the journey ---------- */

.journey {
  position: relative;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* The river AND the country either side of it. It started as a 190px ribbon
   and the ground beside it stayed white, which is what the client saw and
   said so about: a river with nothing on its banks is a blue stripe.

   The tile is now the full width of the journey — sandy banks, a wash of
   dry ground fading away from the water, red gums and Murray pines biggest
   on the bank and smaller back from it, scrub stipple, reeds on the
   waterline and a couple of billabongs. It is the same vocabulary as the
   `map` scene on the stage sections below, which is the point: both are the
   river seen from above.

   preserveAspectRatio="none" and a tile that REPEATS rather than one
   drawing stretched to fit: the height of this list depends on its content,
   and stretching a fixed drawing over 1.5x its own height thickens every
   stroke in one direction only. The tile is 1200 units tall in a 1240px
   box, so the stretch is 3% and nothing shows it.

   Two things hold and both are easy to break:

   - THE TILE IS SEAMLESS because the left bank leaves the bottom on the
     same heading it enters the top on — both control handles pull 42 units
     left. Change one and change the other, or a kink appears every 1240px.
   - THE ELEMENT IS A FIXED 1120px WIDE, not a percentage. `none` means the
     drawing stretches to whatever box it is given, so a percentage width
     would make the trees fatter on a wide screen than a narrow one. The
     section clips the overflow at narrower widths, which is the right
     trade.

   Nothing that has to keep its shape exactly goes in here even so — the
   trees are map glyphs with that 3% of slack in them, while a pelican
   stretched 20% is a heron. The wildlife stays in the scene above, where
   the aspect ratio is controlled. */
.journey::before {
  content: "";
  position: absolute;
  top: -30px; bottom: -30px;
  left: 50%;
  width: 1120px;
  margin-left: -560px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1120 1200' preserveAspectRatio='none'%3E%3Cdefs%3E%3Csymbol id='jgum' viewBox='0 0 40 52'%3E%3Cpath d='M18 52 L18 30 L22 30 L22 52 Z'/%3E%3Cellipse cx='20' cy='22' rx='15' ry='11'/%3E%3Cellipse cx='12' cy='16' rx='10' ry='8'/%3E%3Cellipse cx='28' cy='15' rx='10' ry='8'/%3E%3Cellipse cx='20' cy='10' rx='11' ry='9'/%3E%3C/symbol%3E%3Csymbol id='jpine' viewBox='0 0 28 52'%3E%3Cpath d='M12 52 L12 34 L16 34 L16 52 Z'/%3E%3Cellipse cx='14' cy='32' rx='10' ry='8'/%3E%3Cellipse cx='14' cy='24' rx='9' ry='7'/%3E%3Cellipse cx='14' cy='17' rx='7' ry='6'/%3E%3Cellipse cx='14' cy='10' rx='5' ry='5'/%3E%3C/symbol%3E%3ClinearGradient id='jwl' x1='0' y1='0' x2='1' y2='0'%3E%3Cstop offset='0' stop-color='%23e8dcc8' stop-opacity='0'/%3E%3Cstop offset='1' stop-color='%23e8dcc8' stop-opacity='.62'/%3E%3C/linearGradient%3E%3ClinearGradient id='jwr' x1='0' y1='0' x2='1' y2='0'%3E%3Cstop offset='0' stop-color='%23e8dcc8' stop-opacity='.62'/%3E%3Cstop offset='1' stop-color='%23e8dcc8' stop-opacity='0'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect x='0' y='0' width='532' height='1200' fill='url(%23jwl)'/%3E%3Crect x='588' y='0' width='532' height='1200' fill='url(%23jwr)'/%3E%3Cpath d='M486 0C444 200 528 400 486 600C444 800 528 1000 486 1200L634 1200C592 1000 676 800 634 600C592 400 676 200 634 0Z' fill='%23e8dcc8' fill-opacity='.75'/%3E%3Cg fill='%231b8a9c' opacity='.13'%3E%3Cellipse cx='214' cy='410' rx='54' ry='22' transform='rotate(-12 214 410)'/%3E%3Cellipse cx='880' cy='1020' rx='46' ry='19' transform='rotate(9 880 1020)'/%3E%3Cellipse cx='838' cy='214' rx='38' ry='16' transform='rotate(-6 838 214)'/%3E%3C/g%3E%3Cg fill='%23004c6d' opacity='.1'%3E%3Ccircle cx='347' cy='153' r='3.5'/%3E%3Ccircle cx='332' cy='295' r='2.6'/%3E%3Ccircle cx='265' cy='42' r='2.6'/%3E%3Ccircle cx='921' cy='857' r='2.8'/%3E%3Ccircle cx='375' cy='400' r='3.8'/%3E%3Ccircle cx='1076' cy='860' r='3.3'/%3E%3Ccircle cx='835' cy='64' r='3.9'/%3E%3Ccircle cx='351' cy='995' r='3.0'/%3E%3Ccircle cx='229' cy='668' r='4.0'/%3E%3Ccircle cx='871' cy='43' r='2.8'/%3E%3Ccircle cx='837' cy='256' r='2.8'/%3E%3Ccircle cx='969' cy='308' r='2.5'/%3E%3Ccircle cx='298' cy='958' r='2.8'/%3E%3Ccircle cx='783' cy='999' r='3.9'/%3E%3Ccircle cx='381' cy='165' r='3.3'/%3E%3Ccircle cx='359' cy='658' r='3.3'/%3E%3Ccircle cx='258' cy='701' r='3.5'/%3E%3Ccircle cx='307' cy='867' r='2.6'/%3E%3Ccircle cx='348' cy='746' r='3.3'/%3E%3Ccircle cx='119' cy='740' r='3.3'/%3E%3Ccircle cx='900' cy='547' r='3.3'/%3E%3Ccircle cx='268' cy='74' r='2.8'/%3E%3Ccircle cx='331' cy='471' r='3.2'/%3E%3Ccircle cx='179' cy='1007' r='3.5'/%3E%3Ccircle cx='996' cy='499' r='3.0'/%3E%3Ccircle cx='897' cy='386' r='3.1'/%3E%3Ccircle cx='285' cy='47' r='2.9'/%3E%3Ccircle cx='960' cy='715' r='3.7'/%3E%3Ccircle cx='820' cy='995' r='2.9'/%3E%3Ccircle cx='260' cy='317' r='3.8'/%3E%3Ccircle cx='303' cy='465' r='3.0'/%3E%3Ccircle cx='166' cy='271' r='3.4'/%3E%3Ccircle cx='922' cy='951' r='4.0'/%3E%3Ccircle cx='164' cy='366' r='3.5'/%3E%3Ccircle cx='202' cy='866' r='3.1'/%3E%3Ccircle cx='916' cy='945' r='3.2'/%3E%3Ccircle cx='75' cy='635' r='3.0'/%3E%3Ccircle cx='323' cy='467' r='2.8'/%3E%3Ccircle cx='982' cy='334' r='3.9'/%3E%3Ccircle cx='978' cy='553' r='3.2'/%3E%3Ccircle cx='48' cy='124' r='3.4'/%3E%3Ccircle cx='959' cy='370' r='3.5'/%3E%3Ccircle cx='346' cy='1030' r='2.9'/%3E%3Ccircle cx='379' cy='643' r='4.0'/%3E%3Ccircle cx='180' cy='789' r='2.9'/%3E%3Ccircle cx='948' cy='148' r='3.6'/%3E%3Ccircle cx='117' cy='412' r='3.9'/%3E%3Ccircle cx='761' cy='98' r='2.7'/%3E%3Ccircle cx='777' cy='342' r='3.8'/%3E%3Ccircle cx='902' cy='917' r='2.6'/%3E%3Ccircle cx='1054' cy='298' r='3.4'/%3E%3Ccircle cx='729' cy='1035' r='3.5'/%3E%3Ccircle cx='181' cy='96' r='2.8'/%3E%3Ccircle cx='278' cy='22' r='3.1'/%3E%3C/g%3E%3Cg fill='%23004c6d' opacity='.15'%3E%3Cuse href='%23jgum' x='906' y='66' width='35' height='45'/%3E%3Cuse href='%23jgum' x='747' y='440' width='47' height='61'/%3E%3Cuse href='%23jpine' x='896' y='676' width='24' height='45'/%3E%3Cuse href='%23jgum' x='301' y='232' width='41' height='53'/%3E%3Cuse href='%23jgum' x='245' y='1074' width='52' height='67'/%3E%3Cuse href='%23jpine' x='278' y='317' width='24' height='45'/%3E%3Cuse href='%23jgum' x='770' y='904' width='52' height='68'/%3E%3Cuse href='%23jgum' x='365' y='812' width='49' height='64'/%3E%3Cuse href='%23jpine' x='858' y='615' width='33' height='61'/%3E%3Cuse href='%23jgum' x='888' y='337' width='36' height='47'/%3E%3Cuse href='%23jgum' x='1009' y='734' width='36' height='47'/%3E%3Cuse href='%23jpine' x='989' y='549' width='28' height='52'/%3E%3Cuse href='%23jgum' x='968' y='286' width='41' height='53'/%3E%3Cuse href='%23jgum' x='886' y='442' width='45' height='58'/%3E%3Cuse href='%23jpine' x='775' y='55' width='27' height='49'/%3E%3Cuse href='%23jgum' x='285' y='507' width='40' height='52'/%3E%3Cuse href='%23jgum' x='126' y='1103' width='44' height='56'/%3E%3Cuse href='%23jpine' x='785' y='564' width='34' height='63'/%3E%3Cuse href='%23jgum' x='357' y='68' width='53' height='69'/%3E%3Cuse href='%23jgum' x='297' y='675' width='48' height='63'/%3E%3Cuse href='%23jpine' x='187' y='936' width='30' height='57'/%3E%3Cuse href='%23jgum' x='856' y='1081' width='43' height='56'/%3E%3Cuse href='%23jgum' x='853' y='875' width='44' height='57'/%3E%3Cuse href='%23jpine' x='222' y='425' width='30' height='57'/%3E%3Cuse href='%23jgum' x='737' y='983' width='53' height='68'/%3E%3Cuse href='%23jgum' x='870' y='185' width='37' height='48'/%3E%3Cuse href='%23jpine' x='938' y='799' width='29' height='54'/%3E%3Cuse href='%23jgum' x='264' y='1003' width='44' height='56'/%3E%3Cuse href='%23jgum' x='392' y='158' width='48' height='62'/%3E%3Cuse href='%23jpine' x='103' y='74' width='23' height='42'/%3E%3Cuse href='%23jgum' x='929' y='945' width='49' height='64'/%3E%3Cuse href='%23jgum' x='159' y='268' width='44' height='57'/%3E%3Cuse href='%23jpine' x='229' y='109' width='32' height='60'/%3E%3Cuse href='%23jgum' x='298' y='150' width='41' height='53'/%3E%3Cuse href='%23jgum' x='814' y='243' width='40' height='51'/%3E%3Cuse href='%23jpine' x='1014' y='866' width='25' height='47'/%3E%3C/g%3E%3Cg stroke='%23004c6d' stroke-opacity='.24' stroke-width='2.2' fill='none' stroke-linecap='round'%3E%3Cpath d='M476 14l-5 -13M476 14l0 -17M476 14l6 -11'/%3E%3Cpath d='M651 85l-5 -15M651 85l0 -19M651 85l6 -13'/%3E%3Cpath d='M653 125l-5 -13M653 125l0 -17M653 125l6 -11'/%3E%3Cpath d='M472 232l-5 -13M472 232l0 -17M472 232l6 -11'/%3E%3Cpath d='M478 286l-5 -16M478 286l0 -20M478 286l6 -14'/%3E%3Cpath d='M637 358l-5 -13M637 358l0 -17M637 358l6 -11'/%3E%3Cpath d='M632 406l-5 -14M632 406l0 -18M632 406l6 -12'/%3E%3Cpath d='M490 505l-5 -15M490 505l0 -19M490 505l6 -13'/%3E%3Cpath d='M486 559l-5 -16M486 559l0 -20M486 559l6 -14'/%3E%3Cpath d='M644 602l-5 -13M644 602l0 -17M644 602l6 -11'/%3E%3Cpath d='M651 684l-5 -15M651 684l0 -19M651 684l6 -13'/%3E%3Cpath d='M468 777l-5 -18M468 777l0 -22M468 777l6 -16'/%3E%3Cpath d='M472 832l-5 -18M472 832l0 -22M472 832l6 -16'/%3E%3Cpath d='M642 886l-5 -12M642 886l0 -16M642 886l6 -10'/%3E%3Cpath d='M637 943l-5 -15M637 943l0 -19M637 943l6 -13'/%3E%3Cpath d='M491 1050l-5 -19M491 1050l0 -23M491 1050l6 -17'/%3E%3Cpath d='M490 1105l-5 -17M490 1105l0 -21M490 1105l6 -15'/%3E%3Cpath d='M634 1170l-5 -11M634 1170l0 -15M634 1170l6 -9'/%3E%3C/g%3E%3Cg fill='%238a6a3d' opacity='.12'%3E%3Cellipse cx='552' cy='330' rx='24' ry='8' transform='rotate(-14 552 330)'/%3E%3Cellipse cx='570' cy='900' rx='21' ry='7' transform='rotate(12 570 900)'/%3E%3C/g%3E%3Cpath d='M516 0C474 200 558 400 516 600C474 800 558 1000 516 1200L604 1200C562 1000 646 800 604 600C562 400 646 200 604 0Z' fill='%231b8a9c' fill-opacity='.15'/%3E%3Cg stroke='%231b8a9c' stroke-opacity='.3' fill='none' stroke-width='2.5'%3E%3Cpath d='M516 0C474 200 558 400 516 600C474 800 558 1000 516 1200'/%3E%3Cpath d='M604 0C646 200 562 400 604 600C646 800 562 1000 604 1200'/%3E%3C/g%3E%3Cg stroke='%231b8a9c' stroke-opacity='.2' fill='none' stroke-width='4' stroke-linecap='round'%3E%3Cpath d='M544 96C564 126 568 156 554 188'/%3E%3Cpath d='M534 286C552 316 556 346 542 378'/%3E%3Cpath d='M556 452C576 482 580 512 566 542'/%3E%3Cpath d='M538 690C558 720 562 750 548 782'/%3E%3Cpath d='M560 880C542 910 538 940 550 972'/%3E%3Cpath d='M542 1060C562 1090 566 1118 552 1148'/%3E%3C/g%3E%3C/svg%3E");
  background-position: 0 0;
  background-size: 100% 1240px;
  background-repeat: repeat-y;
  pointer-events: none;
  /* The river draws its own ends. A repeating tile stops on a ruled line at
     both ends otherwise, and a river that begins with a straight edge above
     the first stop reads as a mistake — the same lesson the header band and
     the tall scenes are already written around. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 90px,
                      #000 calc(100% - 100px), transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0, #000 90px,
                      #000 calc(100% - 100px), transparent 100%);
}

/* Both children are placed on row 1 explicitly. Without that, the buoy
   takes row 1 column 2 and auto-placement refuses to go backwards for the
   card, which lands on row 2 — the buoy floating above its own stop, which
   is exactly how the first build rendered. */
.stop {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 190px 1fr;
  align-items: center;
}
.stop + .stop { margin-top: 56px; }

.stop > .stop-card {
  grid-row: 1;
  grid-column: 1;
  justify-self: end;
  width: 100%;
  max-width: 460px;
}
/* Stops alternate across the water, which is what makes it read as a course
   rather than a list with a stripe down it. */
.stop:nth-child(even) > .stop-card { grid-column: 3; justify-self: start; }

/* ---------- the buoys ----------

   `.stage-num` already draws a numbered buoy in the educator half and this
   is deliberately NOT that class. Two different things sharing a class name
   is a trap this stylesheet has paid for once already: this buoy is 56px
   and sits on water, that one is 30px and sits in a card, and the day one
   of them changes is the day the other breaks in silence. */
.stop > .stop-buoy {
  grid-row: 1;
  grid-column: 2;
  justify-self: center;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px; height: 56px;
  font-size: 1.25rem;
  font-weight: 700;
  color: #fff;
  background: var(--sun);
  border: 4px solid var(--bg);
  border-radius: 50%;
  box-shadow: 0 4px 14px rgba(0, 41, 60, .18);
  animation: buoy-bob 5.5s ease-in-out infinite;
}
.stop:nth-child(2) > .stop-buoy { animation-duration: 6.8s; animation-delay: -2.2s; }
.stop:nth-child(3) > .stop-buoy { animation-duration: 4.9s; animation-delay: -3.7s; }

@keyframes buoy-bob {
  0%, 100% { transform: translateY(-4px); }
  50%      { transform: translateY(4px); }
}

.stop-card img { aspect-ratio: 16 / 9; }
.stop-card .eyebrow { margin-bottom: 6px; }
.stop-card h3 { margin: 0 0 10px; font-size: 1.28rem; color: var(--brand); }
.stop-meta { margin: 0 0 20px; font-size: .92rem; color: var(--ink-soft); }

/* Below 900 the water runs down the left margin and every stop sits to the
   right of it: alternating needs two columns of card width to alternate
   between, and a phone has one. */
@media (max-width: 900px) {
  /* The narrow tile: water and its banks only. The wide one is a landscape
     either side of the channel and there is no either side on a phone. */
  .journey::before {
    left: 0; width: 84px; margin-left: 0;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 600' preserveAspectRatio='none'%3E%3Cpath d='M56 0C14 200 98 400 56 600L144 600C186 400 102 200 144 0Z' fill='%231b8a9c' fill-opacity='.14'/%3E%3Cg stroke='%231b8a9c' stroke-opacity='.3' fill='none' stroke-width='2.5'%3E%3Cpath d='M56 0C14 200 98 400 56 600'/%3E%3Cpath d='M144 0C102 200 186 400 144 600'/%3E%3C/g%3E%3Cg stroke='%231b8a9c' stroke-opacity='.22' fill='none' stroke-width='4' stroke-linecap='round'%3E%3Cpath d='M84 96C104 126 108 156 94 188'/%3E%3Cpath d='M74 286C92 316 96 346 82 378'/%3E%3Cpath d='M96 452C116 482 120 512 106 542'/%3E%3C/g%3E%3C/svg%3E");
    background-size: 100% 460px;
  }
  .stop { grid-template-columns: 84px 1fr; }
  .stop > .stop-card,
  .stop:nth-child(even) > .stop-card { grid-column: 2; justify-self: stretch; max-width: none; }
  .stop > .stop-buoy { grid-column: 1; }
  .stop + .stop { margin-top: 36px; }
}
@media (max-width: 420px) {
  .journey::before { width: 62px; background-size: 100% 380px; }
  .stop { grid-template-columns: 62px 1fr; }
  .stop > .stop-buoy { width: 44px; height: 44px; font-size: 1.05rem; border-width: 3px; }
}

@media (prefers-reduced-motion: reduce) {
  .stop > .stop-buoy { animation: none; transform: none; }
}

/* ---------- the educator half ----------

   One label, in the client's own words from the page head, so the reader
   knows the register has changed and the rest of the page is reference
   rather than invitation. */

.edu-flag {
  display: flex;
  align-items: center;
  gap: 18px;
  margin: 0 0 40px;
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--brand);
}
.edu-flag::before, .edu-flag::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}

/* ---------- outcome groups ----------

   These were a `<details>`: shut on arrival, then open on arrival, and now
   not a disclosure at all. The client's call and the right one — this is a
   page a teacher reads rather than navigates, and everything in these cards
   is the thing the page exists to say. A control whose only job was to hide
   that was a control in the way. The matching handler is out of site.js.

   Two things the fold left behind that are worth keeping, because both were
   found because of it: `align-items: start` on the row above, and the
   `min()` in its track size.

   The card keeps the hover lift it has always had. It is not a button and
   never was — the lift is the same one .outcome-group carried before any of
   this. */

/* The enquire button used to butt straight up against the row of cards and
   read as part of it rather than as the thing to do after it. */
.outcome-groups + p { margin-top: 34px; }

/* ---------- print ----------

   A teacher prints this to take to a staff meeting. Nothing is hidden on
   the page any more, so there is nothing to unfold for the print; what is
   left is dropping the water, which costs ink and says nothing on paper,
   and keeping a card off a page break. */
@media print {
  .journey::before { display: none; }
  .stop > .stop-buoy { animation: none; box-shadow: none; }
  .outcome-group { break-inside: avoid; box-shadow: none; }
}


/* ---------- something moves when you lean on a stop ----------

   Point at a stage card and a bird comes out from behind its top edge — a
   wader at the first stop, a pelican at the second, a gull leaving at the
   third. Three different ones on purpose: the same silhouette appearing
   three times is a widget, three different ones is a river with things
   living in it.

   The shapes are `wader`, `pelStand` and `gull` from partials/scene.php,
   lifted path for path rather than redrawn, which is what stops the page
   growing a second visual style. They are navy at .45 instead of the
   scenes' tenth: a background scrub clump should barely register, and a
   bird that has just popped out from behind a card has to be seen or the
   hover reads as a rendering glitch.

   Anchored to the card's RIVER side, which is the one edge whose position
   is arithmetic rather than guesswork: the card is justify-self:end in a
   `1fr 190px 1fr` grid, so its inner edge is exactly 95px from the centre
   line at every width, while its outer edge moves with the free space.

   `.stop` isolates so the bird can sit behind the card on z-index -1
   without disappearing behind the section it is standing in. The card
   clips its own overflow — that is what crops the photo — so the bird
   cannot live inside it.

   Off below 900px: there is no hover on a touch screen, and the layout
   there has the card against the water with no room beside it. `:focus-within`
   is there so a keyboard reaches the same thing the pointer does. */

.stop { isolation: isolate; }

.stop::after {
  content: "";
  position: absolute;
  z-index: -1;
  top: 0;
  right: calc(50% + 113px);
  width: 47px; height: 62px;
  background: bottom center / contain no-repeat;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 44 58' fill='%23004c6d' fill-opacity='.45'%3E%3Cpath d='M17.8 29.4 L19.2 29.4 L18.4 52.8 L17 52.8 Z'/%3E%3Cpath d='M23 29.4 L24.4 29.4 L25.6 52.8 L24.2 52.8 Z'/%3E%3Cpath d='M15 52.2 L19.6 52.2 L19.6 53.6 L15 53.6 Z'/%3E%3Cpath d='M23.4 52.2 L28 52.2 L28 53.6 L23.4 53.6 Z'/%3E%3Cpath d='M4.6 21.4 L13 24.6 L11.2 28.4 Z'/%3E%3Cellipse cx='19.2' cy='25.2' rx='12' ry='5.9'/%3E%3Cpath d='M24.2 21.8 C 26 17.2 27.8 14 29.8 11.8 L 32.2 13.8 C 30.4 16 29 19 28.2 22.4 Z'/%3E%3Ccircle cx='31.4' cy='10.6' r='3.1'/%3E%3Cpath d='M33.8 9.4 L43.4 7.2 L43.6 8.6 L34.2 11.9 Z'/%3E%3C/svg%3E");
  opacity: 0;
  transform: translateY(14px);
  transition: transform .38s cubic-bezier(.34, 1.26, .48, 1), opacity .22s ease;
  pointer-events: none;
}
.stop:nth-child(even)::after {
  right: auto;
  left: calc(50% + 113px);
}

.stop:nth-child(2)::after {
  width: 75px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 70 58'%3E%3Cg fill='%23004c6d' fill-opacity='.45'%3E%3Cpath d='M24 41v14M31 41v14' stroke='%23004c6d' stroke-opacity='.45' stroke-width='2.4' fill='none' stroke-linecap='round'/%3E%3Cpath d='M3 31.5 10 30C11.5 25 16.5 21 23 19.8c7-1.4 14 .2 18 3.6 3.5 3 3.5 8-.5 11C36 37.6 28.5 39 22 38c-7-1-11.5-3-13-6.2z'/%3E%3Cpath d='M33 24c-1-4 .5-7.5 3.5-9.5l4 3c-2 1.5-3 4-2.5 6.5z'/%3E%3Cg transform='translate(35,5)'%3E%3Cpath d='M0 17 C-1.5 9.5 .5 2.5 6.5 .8 C9.5 0 11.5 1.2 11.5 3.2 L28 6.6 C29 6.9 29 8.1 28 8.4 C22 10.6 18.5 13.2 15 14.8 C11.5 16.4 8 16.4 5.5 14.6 C3.8 16.2 2 17 0 17 Z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
}
.stop:nth-child(3)::after {
  width: 62px; height: 31px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 26 13' fill='%23004c6d' fill-opacity='.45'%3E%3Cpath d='M1 8.6C4.2 2.8 8.6 2 12.2 6.4c.4.5.6.9.8 1.4.2-.5.4-.9.8-1.4C17.4 2 21.8 2.8 25 8.6c-3-2.2-6.4-1.8-9.4 1-.9.8-1.7 1.6-2.6 2.5-.9-.9-1.7-1.7-2.6-2.5-3-2.8-6.4-3.2-9.4-1Z'/%3E%3C/svg%3E");
}

.stop:hover::after,
.stop:focus-within::after { opacity: 1; transform: translateY(-52px); }

/* The gull is the only one leaving: it lifts further and banks as it goes,
   which is the difference between a bird standing up and a bird taking off. */
.stop:nth-child(3):hover::after,
.stop:nth-child(3):focus-within::after {
  transform: translate(14px, -74px) rotate(-7deg);
}

@media (max-width: 900px) {
  .stop::after { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .stop::after { transition: opacity .22s ease; }
  .stop:hover::after, .stop:focus-within::after { transform: translateY(-52px); }
  .stop:nth-child(3):hover::after,
  .stop:nth-child(3):focus-within::after { transform: translate(14px, -74px); }
}
@media print { .stop::after { display: none; } }


/* ---------- scenery on the educator half ----------

   The stage sections had no background at all, which next to the journey
   above them read as the page giving up halfway down.

   Stage 1 gets the drawn picture from partials/art.php beside its
   explanation. Stages 2 and 3 get `map` from partials/scene.php: the same
   river seen from above, the way a chart of it would draw it, pinned to the
   top right where the section head's 62ch column leaves the width free.

   The map is NOT stretched over the section the way the landscape scenes
   are. It is a fixed aspect ratio at the top right with
   preserveAspectRatio="xMidYMid meet", so it is never cropped and its size
   does not depend on how long the section happens to be — which is the trap
   `slice` sets for every other scene in this file and the reason the tall
   ones had to be redrawn. */

.section.stage > .wrap { position: relative; }

.section.stage > .scene.mapscape {
  /* Bleeding off the right rather than sitting flush: at inset 0 the chart's
     own corner ticks land exactly on the section boundary and read as the
     section being cut off. The left pair of ticks still shows, which is all
     that is needed to say "chart". */
  inset: 30px -46px auto auto;
  width: min(48%, 560px);
  height: auto;
  aspect-ratio: 5 / 4;
}

/* Below 1080 the section head takes the whole width and the map would be
   behind the words rather than beside them. */
@media (max-width: 1080px) {
  .section.stage > .scene.mapscape { display: none; }
}
@media print {
  .section.stage > .scene.mapscape { display: none; }
}

/* ---------- the picture beside stage one ---------- */

.stage-art svg { display: block; width: 100%; height: auto; }

@media (min-width: 901px) {
  .stage-intro.has-art {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(300px, 460px);
    gap: 44px;
    align-items: center;
  }
  /* .section-head carries its own 44px below it; inside the grid that would
     only push the picture's column off centre. */
  .stage-intro.has-art .section-head { margin-bottom: 0; }
  .stage-intro.has-art { margin-bottom: 44px; }
}

@media (max-width: 900px) {
  .stage-art { max-width: 460px; margin: 0 auto 36px; }
}

/* It is a picture, not a chart: on paper it costs a page of ink and adds
   nothing a teacher is going to read out. */
@media print { .stage-art { display: none; } }
