/* ==========================================================================
   The Ashton Effect — Paper
   A light and dark theme built on warm paper tones, with Poppins throughout.
   Everything is a token, so a colour is changed in one place.
   ========================================================================== */

@import url('/assets/fonts/poppins.css');

/* --------------------------------------------------------------------------
   1. Tokens — light is the base, dark overrides only what changes.
   -------------------------------------------------------------------------- */
:root {
  color-scheme: light;

  /* Paper: warm off-whites rather than pure white, so the page reads as a
     printed sheet rather than a screen. */
  --paper:        #ffffff;
  --paper-raised: #ffffff;
  --paper-sunk:   #f4faf8;
  --paper-edge:   #e4ece9;
  --paper-line:   #d8e3df;

  /* Ink */
  --ink:          #1b201e;
  --ink-soft:     #3f4744;
  --ink-muted:    #5d6663;   /* 5.6:1 on paper — readable, not just decorative */
  --ink-faint:    #66716d;   /* 5.1:1 on paper, 4.8:1 on the sunk panels — the
                                quietest text still has to be read. Was a sandy
                                brown carried over from another site's palette. */

  /* The accent */
  --accent:       #12805d;
  --accent-hover: #0d6448;
  --accent-soft:  #e8f9f2;
  --accent-ink:   #0b4f39;

  /* Supporting */
  --green:        #12805d;
  --green-soft:   #e8f9f2;
  --amber:        #a86a1a;
  --amber-soft:   #fbf0dd;
  --red:          #a83232;
  --red-soft:     #fbe7e5;

  --focus:        #12805d;

  /* Light greys. The paper palette is warm all the way through, so a cooler
     set is kept beside it for the surfaces that need to sit back rather than
     glow. */

  /* Depth. Paper casts a soft, warm shadow — never a grey drop shadow. */
  --shadow-sm: 0 1px 2px rgba(60, 48, 30, .06), 0 1px 1px rgba(60, 48, 30, .04);
  --shadow:    0 2px 6px rgba(60, 48, 30, .07), 0 1px 2px rgba(60, 48, 30, .05);
  --shadow-lg: 0 12px 32px rgba(60, 48, 30, .10), 0 3px 8px rgba(60, 48, 30, .06);

  /* Geometry */
  --radius-sm: 6px;
  --radius:    10px;
  --radius-lg: 16px;
  --radius-pill: 999px;

  --space-1: .25rem;  --space-2: .5rem;   --space-3: .75rem;
  --space-4: 1rem;    --space-5: 1.5rem;  --space-6: 2rem;
  --space-7: 3rem;    --space-8: 4rem;    --space-9: 6rem;

  --measure: 68ch;
  --container: 1440px;
  --container-narrow: 760px;

  --font: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;

  /* The Ashton Effect's own colours, carried over from the site as it is.
     --mint is the signature and is used exactly as it was — on the buttons,
     behind the sparkles, along the rules. It is a pale colour, so anything
     written ON it is set in --mint-ink rather than white: the original site
     put white on it, which measured 1.9:1 and could not be read in sunlight. */
  --mint:      #42d6a3;
  --mint-deep: #2bbd8a;
  --mint-ink:  #0a3a2a;
  --navy:      #131f60;
  --sky-from:  #7ed3fc;
  --sky-to:    #0cabf3;

  --header-h: 68px;
  --ease: cubic-bezier(.4, 0, .2, 1);
}

:root[data-theme="dark"] {
  color-scheme: dark;

  /* Dark paper: a warm charcoal, not a blue-black, so it still reads as paper. */
  --paper:        #14181a;
  --paper-raised: #1c2124;
  --paper-sunk:   #101315;
  --paper-edge:   #2a3134;
  --paper-line:   #333b3f;

  --ink:          #eef3f1;
  --ink-soft:     #c4cecb;
  --ink-muted:    #9aa5a2;
  --ink-faint:    #93a09b;

  --accent:       #4fdcaa;
  --accent-hover: #7ee9c4;
  --accent-soft:  #0f2a22;
  --accent-ink:   #a8f0d6;

  --green:        #4fdcaa;
  --green-soft:   #0f2a22;
  --mint:      #42d6a3;
  --mint-deep: #2bbd8a;
  --mint-ink:  #06251b;
  --navy:      #8ea0ff;
  --sky-from:  #7ed3fc;
  --sky-to:    #0cabf3;
  --amber:        #d9a24e;
  --amber-soft:   #2c2318;
  --red:          #e08a80;
  --red-soft:     #2e1c1a;

  --focus:        #4fdcaa;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);
  --shadow:    0 2px 8px rgba(0, 0, 0, .35);
  --shadow-lg: 0 14px 36px rgba(0, 0, 0, .45);
}

/* Respect the operating system when the visitor has expressed no preference. */
/* The same palette again for the visitor who has expressed no preference on
   the site and whose device is set to dark. This block had been left as
   another site's browns and blue, so a dark-mode phone was shown the wrong
   site entirely. Keep the two lists identical. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    /* Dark paper: a warm charcoal, not a blue-black, so it still reads as paper. */
    --paper:        #14181a;
    --paper-raised: #1c2124;
    --paper-sunk:   #101315;
    --paper-edge:   #2a3134;
    --paper-line:   #333b3f;

    --ink:          #eef3f1;
    --ink-soft:     #c4cecb;
    --ink-muted:    #9aa5a2;
    --ink-faint:    #93a09b;

    --accent:       #4fdcaa;
    --accent-hover: #7ee9c4;
    --accent-soft:  #0f2a22;
    --accent-ink:   #a8f0d6;

    --green:        #4fdcaa;
    --green-soft:   #0f2a22;
    --mint:      #42d6a3;
    --mint-deep: #2bbd8a;
    --mint-ink:  #06251b;
    --navy:      #8ea0ff;
    --sky-from:  #7ed3fc;
    --sky-to:    #0cabf3;
    --amber:        #d9a24e;
    --amber-soft:   #2c2318;
    --red:          #e08a80;
    --red-soft:     #2e1c1a;

    --focus:        #4fdcaa;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);
    --shadow:    0 2px 8px rgba(0, 0, 0, .35);
    --shadow-lg: 0 14px 36px rgba(0, 0, 0, .45);
  }
}

/* --------------------------------------------------------------------------
   2. Reset and base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

/* Several components below set `display`, which would otherwise win against
   the browser default for [hidden]. Anything marked hidden stays hidden. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}

body {
  margin: 0;
  font-family: var(--font);
  /* A little larger on a wide screen, where the reader is further away and
     the measure is longer. */
  font-size: clamp(1rem, .97rem + .16vw, 1.075rem);
  line-height: 1.68;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;

  /* The faintest paper grain. Two tiny gradients, no image request. */
  background-image:
    radial-gradient(circle at 15% 12%, rgba(140, 120, 80, .028), transparent 45%),
    radial-gradient(circle at 85% 78%, rgba(90, 120, 140, .022), transparent 42%);
  background-attachment: fixed;
}

h1, h2, h3, h4, h5, h6 {
  margin: 0 0 var(--space-4);
  font-weight: 600;
  line-height: 1.22;
  letter-spacing: -.018em;
  color: var(--ink);
  text-wrap: balance;
}
h1 { font-size: clamp(2rem, 1.4rem + 2.6vw, 3.1rem); font-weight: 700; letter-spacing: -.028em; }
h2 { font-size: clamp(1.6rem, 1.24rem + 1.6vw, 2.35rem); letter-spacing: -.022em; }
h3 { font-size: clamp(1.2rem, 1.08rem + .6vw, 1.5rem); }
h4 { font-size: 1.1rem; }
h5, h6 { font-size: 1rem; }

p  { margin: 0 0 var(--space-4); text-wrap: pretty; }
a  { color: var(--accent); text-decoration-color: color-mix(in srgb, var(--accent) 35%, transparent); text-underline-offset: .18em; transition: color .15s var(--ease); }
a:hover { color: var(--accent-hover); text-decoration-color: currentColor; }

strong, b { font-weight: 600; }
small { font-size: .875rem; }

img, video, svg, iframe { max-width: 100%; height: auto; }
img { border-radius: var(--radius); display: block; }

hr { border: 0; border-top: 1px solid var(--paper-line); margin: var(--space-6) 0; }

blockquote {
  margin: var(--space-5) 0;
  padding: var(--space-4) var(--space-5);
  background: var(--paper-sunk);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  color: var(--ink-soft);
}
blockquote p:last-child { margin-bottom: 0; }

code, pre { font-family: var(--font-mono); font-size: .9em; }
code { background: var(--paper-sunk); padding: .15em .4em; border-radius: var(--radius-sm); }
pre { background: var(--paper-sunk); padding: var(--space-4); border-radius: var(--radius); overflow-x: auto; border: 1px solid var(--paper-edge); }
pre code { background: none; padding: 0; }

ul, ol { margin: 0 0 var(--space-4); padding-left: 1.35em; }
li { margin-bottom: .4em; }
li::marker { color: var(--ink-faint); }

/* Every interactive thing gets a visible focus ring. The plugins this
   replaces set outline:none on inputs, which fails WCAG outright. */
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 999;
  background: var(--accent); color: #fff; padding: var(--space-3) var(--space-4);
  border-radius: 0 0 var(--radius) 0; font-weight: 600;
}
.skip-link:focus { left: 0; }

.visually-hidden {
  position: absolute !important; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --------------------------------------------------------------------------
   3. Layout
   -------------------------------------------------------------------------- */
.container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--space-5); }
.row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); }
@media (max-width: 640px) { .row-2 { grid-template-columns: 1fr; } }
.container-narrow { max-width: var(--container-narrow); }
.section { padding-block: clamp(var(--space-6), 6vw, calc(var(--space-8) * 1.35)); }
.section-sunk { background: var(--paper-sunk); border-block: 1px solid var(--paper-edge); }

.stack > * + * { margin-top: var(--space-4); }
.grid { display: grid; gap: var(--space-5); }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.cluster { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; }
.between { display: flex; flex-wrap: wrap; gap: var(--space-4); align-items: center; justify-content: space-between; }

.prose { max-width: var(--measure); }
.prose > h2 { margin-top: var(--space-7); }
.prose > h3 { margin-top: var(--space-6); }
/* The picture at the head of a page or a post: one shape, filled. */
.page-shot {
  width: 100%; aspect-ratio: 16 / 9; object-fit: cover;
  margin-bottom: var(--space-6); box-shadow: var(--shadow); border-radius: var(--radius-lg);
}
.prose img { margin-block: var(--space-5); box-shadow: var(--shadow); }
/* A picture in the writing is shown whole, at its own shape.
   This used to force every one of them into a 3:2 box and crop to fill, to
   reserve space while the file loaded. That is the wrong trade: Faye's price
   banners are square and her course flyers are portrait, so the rule was
   slicing the top off "£75 PER COURSE" and cutting the middle out of a
   poster. The browser reserves the right space on its own as soon as the
   image's own dimensions arrive, so nothing is lost by letting it. */
.prose img { max-width: 100%; height: auto; }
.prose img:not([width]) { width: auto; }
.prose figure { margin: var(--space-5) 0; }
.prose figcaption { font-size: .875rem; color: var(--ink-muted); margin-top: var(--space-2); }
.prose table { width: 100%; border-collapse: collapse; margin: var(--space-5) 0; }
.prose th, .prose td { padding: var(--space-3); border-bottom: 1px solid var(--paper-line); text-align: left; }
.prose th { font-weight: 600; background: var(--paper-sunk); }
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* --------------------------------------------------------------------------
   4. The paper card — the motif the whole site is built from
   -------------------------------------------------------------------------- */
.card {
  background: var(--paper-raised);
  border: 1px solid var(--paper-edge);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--space-5);
  transition: box-shadow .2s var(--ease), transform .2s var(--ease), border-color .2s var(--ease);
}
.card-link:hover, a.card:hover { box-shadow: var(--shadow-lg); transform: translateY(-2px); border-color: color-mix(in srgb, var(--accent) 30%, var(--paper-edge)); }
.card-flush { padding: 0; overflow: hidden; }
.card-body { padding: var(--space-5); }

.eyebrow {
  display: inline-flex; align-items: center; gap: .4rem;
  font-size: .72rem; font-weight: 600; letter-spacing: .14em;
  text-transform: uppercase; color: var(--accent); margin-bottom: var(--space-3);
}
.lead { font-size: clamp(1.08rem, 1rem + .34vw, 1.24rem); color: var(--ink-soft); line-height: 1.6; max-width: 62ch; }
.muted { color: var(--ink-muted); }
.faint { color: var(--ink-faint); }

/* --------------------------------------------------------------------------
   5. Buttons
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  padding: .7rem 1.35rem;
  font: inherit; font-weight: 600; font-size: .95rem; line-height: 1.2;
  border: 1px solid transparent; border-radius: var(--radius);
  cursor: pointer; text-decoration: none; white-space: nowrap;
  transition: background .15s var(--ease), border-color .15s var(--ease), transform .1s var(--ease), box-shadow .15s var(--ease);
}
.btn:active { transform: translateY(1px); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .55; cursor: not-allowed; transform: none; }

/* The primary button is the site's mint, not the dark green. The dark green
   stays where it belongs — links, small marks, anything that has to be read
   as text — but a button is a surface, and on this site that surface is the
   mint from the logo. Dark ink on mint reads at 6.9:1, comfortably past AA;
   white on mint would be 1.9:1 and unreadable, which is why the text is dark
   rather than light. */
.btn-primary {
  background: var(--mint); color: var(--mint-ink);
  border-color: var(--mint-deep);
  box-shadow: var(--shadow-sm);
  font-weight: 700;
}
.btn-primary:hover {
  background: var(--mint-deep); color: var(--mint-ink);
  border-color: var(--mint-deep); box-shadow: var(--shadow);
}

.btn-secondary { background: var(--paper-raised); color: var(--ink); border-color: var(--paper-line); }
.btn-secondary:hover { background: var(--paper-sunk); color: var(--ink); border-color: var(--ink-faint); }

.btn-ghost { background: transparent; color: var(--ink-soft); }
.btn-ghost:hover { background: var(--paper-sunk); color: var(--ink); }

.btn-danger { background: var(--red); color: #fff; }
.btn-danger:hover { filter: brightness(.92); color: #fff; }

.btn-sm { padding: .4rem .8rem; font-size: .85rem; }
.btn-lg { padding: .9rem 1.8rem; font-size: 1.05rem; }
/* The quiet half of a pair — the second option beside a mint primary, on
   "Explore the services", "Send a message", "Ask a question" and the rest.
   It was written as white-on-glass for use over a photograph, but every one
   of the fourteen places it is actually used sits on paper, where white text
   on a white page is an invisible button. Outlined ink is the version the
   site needs; the glass one is kept below for the dark surfaces that want
   it. */
.btn-quiet { background: transparent; color: var(--ink); border-color: var(--paper-line); }
.btn-quiet:hover { background: var(--paper-sunk); color: var(--ink); border-color: var(--accent); }

/* Over the dark masthead, or anything that opts in with .on-dark, glass is
   still right: it belongs to the picture rather than sitting on top of it. */
.site-head .btn-quiet,
.on-dark .btn-quiet {
  background: rgba(255, 255, 255, .12); color: #fff;
  border-color: rgba(255, 255, 255, .55);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.site-head .btn-quiet:hover,
.on-dark .btn-quiet:hover { background: rgba(255, 255, 255, .22); color: #fff; border-color: #fff; }
.btn-block { width: 100%; }

.icon { flex: none; fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; vertical-align: -.15em; }

/* --------------------------------------------------------------------------
   6. Forms
   -------------------------------------------------------------------------- */
.field { margin-bottom: var(--space-4); }
.field > label, .label {
  display: block; margin-bottom: var(--space-2);
  font-weight: 600; font-size: .9rem; color: var(--ink-soft);
}
.hint { font-size: .82rem; color: var(--ink-muted); margin-top: var(--space-2); }
/* What a field is complaining about, said next to the field. */
.field-error { font-size: .82rem; color: var(--red); margin-top: var(--space-2); font-weight: 600; }
/* A column of ticks — the parts of the site somebody looks after. */
.check-stack { display: grid; gap: var(--space-3); }
.check-stack .check span { font-size: .9rem; }
/* The honeypot: off-screen for people, filled in by robots. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.error-text { font-size: .85rem; color: var(--red); margin-top: var(--space-2); font-weight: 500; }

input[type="text"], input[type="email"], input[type="password"], input[type="tel"],
input[type="url"], input[type="search"], input[type="number"], input[type="date"],
input[type="datetime-local"], input[type="time"], select, textarea {
  width: 100%;
  padding: .65rem .85rem;
  font: inherit; font-size: .95rem;
  color: var(--ink);
  background: var(--paper-raised);
  border: 1px solid var(--paper-line);
  border-radius: var(--radius);
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
input:hover:not(:disabled), select:hover:not(:disabled), textarea:hover:not(:disabled) { border-color: var(--ink-faint); }
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
input[aria-invalid="true"], .has-error input, .has-error textarea { border-color: var(--red); }
textarea { min-height: 8rem; resize: vertical; line-height: 1.6; }
select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%23857c6c' stroke-width='1.75' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right .85rem center;
  padding-right: 2.4rem;
}
input:disabled, select:disabled, textarea:disabled { background: var(--paper-sunk); color: var(--ink-muted); cursor: not-allowed; }

.check { display: flex; gap: var(--space-3); align-items: flex-start; cursor: pointer; }
.check input[type="checkbox"], .check input[type="radio"] {
  flex: none; width: 1.15rem; height: 1.15rem; margin-top: .18rem; accent-color: var(--accent); cursor: pointer;
}
.check span { font-size: .93rem; color: var(--ink-soft); }

fieldset { border: 1px solid var(--paper-edge); border-radius: var(--radius); padding: var(--space-4); margin: 0 0 var(--space-4); }
legend { padding-inline: var(--space-2); font-weight: 600; font-size: .9rem; color: var(--ink-soft); }

/* Chip-style multi-select, used for choosing a post's categories. */
.chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.chip { position: relative; }
.chip input { position: absolute; opacity: 0; width: 0; height: 0; }
.chip span {
  display: inline-block; padding: .5rem 1rem;
  font-size: .9rem; font-weight: 500;
  background: var(--paper-raised); color: var(--ink-soft);
  border: 1px solid var(--paper-line); border-radius: var(--radius-pill);
  cursor: pointer; transition: all .15s var(--ease); user-select: none;
}
.chip span:hover { border-color: var(--accent); color: var(--accent); }
.chip input:checked + span { background: var(--accent); border-color: var(--accent); color: #fff; }
.chip input:focus-visible + span { outline: 2px solid var(--focus); outline-offset: 2px; }

/* --------------------------------------------------------------------------
   7. Badges, pills and notices
   -------------------------------------------------------------------------- */
.badge {
  display: inline-flex; align-items: center; gap: .35em;
  padding: .22rem .6rem; font-size: .76rem; font-weight: 600;
  letter-spacing: .01em; border-radius: var(--radius-pill);
  background: var(--paper-sunk); color: var(--ink-soft); border: 1px solid var(--paper-edge);
  white-space: nowrap;
}
.badge-accent { background: var(--accent-soft); color: var(--accent-ink); border-color: color-mix(in srgb, var(--accent) 25%, transparent); }
.badge-green  { background: var(--green-soft); color: var(--green); border-color: color-mix(in srgb, var(--green) 25%, transparent); }
.badge-amber  { background: var(--amber-soft); color: var(--amber); border-color: color-mix(in srgb, var(--amber) 25%, transparent); }
.badge-red    { background: var(--red-soft); color: var(--red); border-color: color-mix(in srgb, var(--red) 25%, transparent); }

.notice {
  display: flex; gap: var(--space-3); align-items: flex-start;
  padding: var(--space-4);
  border: 1px solid var(--paper-edge); border-left-width: 3px;
  border-radius: var(--radius); background: var(--paper-raised);
  margin-bottom: var(--space-4);
}
.notice p:last-child { margin-bottom: 0; }
.notice .icon { margin-top: .18rem; }
.notice-success { border-left-color: var(--green); background: var(--green-soft); color: var(--green); }
.notice-error   { border-left-color: var(--red);   background: var(--red-soft);   color: var(--red); }
.notice-warn    { border-left-color: var(--amber); background: var(--amber-soft); color: var(--amber); }
.notice-info    { border-left-color: var(--accent); background: var(--accent-soft); color: var(--accent-ink); }
.notice strong { color: inherit; }

/* --------------------------------------------------------------------------
   8. Site header and footer
   -------------------------------------------------------------------------- */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--paper-raised) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(12px);
  -webkit-backdrop-filter: saturate(1.4) blur(12px);
  border-bottom: 1px solid var(--paper-edge);
}
.site-header .container { display: flex; align-items: center; gap: var(--space-4); min-height: var(--header-h); }

.brand { display: flex; align-items: center; gap: var(--space-3); text-decoration: none; color: var(--ink); font-weight: 700; letter-spacing: -.02em; }
.brand:hover { color: var(--ink); }
.brand-mark { flex: none; width: 38px; height: 38px; border-radius: 50%; background: var(--accent); display: grid; place-items: center; color: #fff; }
.brand-name { font-size: 1.02rem; line-height: 1.15; }
.brand-sub { display: block; font-size: .72rem; font-weight: 500; color: var(--ink-muted); letter-spacing: .04em; }

.nav { display: flex; align-items: center; gap: 2px; margin-left: auto; }
.nav a {
  padding: .5rem .7rem; font-size: .9rem; font-weight: 500; white-space: nowrap;
  color: var(--ink-soft); text-decoration: none; border-radius: var(--radius-sm);
  transition: background .15s var(--ease), color .15s var(--ease);
}
.nav a:hover { background: var(--paper-sunk); color: var(--ink); }
.nav a[aria-current="page"] { color: var(--accent); background: var(--accent-soft); }

.theme-toggle {
  flex: none; width: 38px; height: 38px; display: grid; place-items: center;
  background: transparent; border: 1px solid var(--paper-line); border-radius: var(--radius);
  color: var(--ink-soft); cursor: pointer; transition: all .15s var(--ease);
}
.theme-toggle:hover { background: var(--paper-sunk); color: var(--ink); border-color: var(--ink-faint); }
.theme-toggle .icon-sun { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-sun { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .icon-sun { display: block; }
  :root:not([data-theme="light"]) .theme-toggle .icon-moon { display: none; }
}

.nav-toggle { display: none; }

.site-footer {
  margin-top: var(--space-8);
  padding-block: var(--space-7) var(--space-5);
  background: var(--paper-sunk);
  border-top: 1px solid var(--paper-edge);
  font-size: .92rem;
}
.site-footer h3 { font-size: .8rem; text-transform: uppercase; letter-spacing: .09em; color: var(--ink-muted); margin-bottom: var(--space-3); }
.site-footer ul { list-style: none; padding: 0; margin: 0; }
.site-footer li { margin-bottom: var(--space-2); }
.site-footer a { color: var(--ink-soft); text-decoration: none; }
.site-footer a:hover { color: var(--accent); }
/* Three things on one line: the site's copyright, who built it, and the way
   in. The credit sits in the middle and stays quiet. */
.footer-credit { color: var(--ink-faint); }
/* The version, quieter still than the credit beside it: there for whoever
   needs it, invisible to everybody who does not. */
.footer-version { color: var(--ink-faint); font-variant-numeric: tabular-nums; opacity: .75;
  display: inline-flex; align-items: center; gap: .5rem; }
.footer-version form { display: inline; }
.footer-version button { display: inline-flex; align-items: center; gap: .3rem;
  font: inherit; font-size: .82em; color: inherit; cursor: pointer;
  background: none; border: 1px solid var(--paper-edge); border-radius: 999px;
  padding: .12rem .6rem; line-height: 1.6; }
.footer-version button:hover { color: var(--accent); border-color: currentColor; }
.footer-credit a { color: inherit; text-decoration: none; border-bottom: 1px solid var(--paper-edge); }
.footer-credit a:hover { color: var(--accent); border-bottom-color: currentColor; }
.footer-bottom {
  margin-top: var(--space-6); padding-top: var(--space-4);
  border-top: 1px solid var(--paper-edge);
  display: flex; flex-wrap: wrap; gap: var(--space-4);
  justify-content: space-between; color: var(--ink-muted); font-size: .85rem;
}

/* --------------------------------------------------------------------------
   9. The announcement strip above the masthead
   -------------------------------------------------------------------------- */
.banner-strip {
  background: var(--accent); color: #fff;
  padding: var(--space-2) 0; font-size: .9rem; text-align: center;
}
.banner-strip a { color: #fff; font-weight: 600; }
.banner-strip p { margin: 0; }

/* --------------------------------------------------------------------------
   10. Post lists
   -------------------------------------------------------------------------- */
.post-card { display: flex; flex-direction: column; height: 100%; }
.post-card .thumb { aspect-ratio: 16 / 10; overflow: hidden; background: var(--paper-sunk); }
.post-card .thumb img { width: 100%; height: 100%; object-fit: cover; border-radius: 0; transition: transform .4s var(--ease); }
.post-card:hover .thumb img { transform: scale(1.03); }
.post-card .card-body { flex: 1; display: flex; flex-direction: column; }
.post-card h3 { font-size: 1.12rem; margin-bottom: var(--space-2); }
.post-card h3 a { color: var(--ink); text-decoration: none; }
.post-card h3 a:hover { color: var(--accent); }
.post-card .meta { font-size: .82rem; color: var(--ink-muted); margin-top: auto; padding-top: var(--space-3); }

/* --------------------------------------------------------------------------
   11. Pagination
   -------------------------------------------------------------------------- */
.pagination { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-top: var(--space-6); }
.pagination a, .pagination span {
  min-width: 2.4rem; padding: .45rem .7rem; text-align: center;
  border: 1px solid var(--paper-line); border-radius: var(--radius-sm);
  text-decoration: none; color: var(--ink-soft); font-size: .9rem; background: var(--paper-raised);
}
.pagination a:hover { border-color: var(--accent); color: var(--accent); }
.pagination .current { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }
.pagination .gap { border: 0; background: none; color: var(--ink-faint); min-width: auto; padding-inline: .2rem; }
.pagination .summary { margin-left: auto; border: 0; background: none; color: var(--ink-muted); font-size: .85rem; }

@media (max-width: 640px) {
  .pagination .summary { margin-left: 0; width: 100%; order: -1; padding: 0 0 var(--space-2); }
}

/* --------------------------------------------------------------------------
   12. Responsive navigation
   -------------------------------------------------------------------------- */
@media (max-width: 1080px) {
  .nav-toggle {
    display: grid; place-items: center; margin-left: auto;
    width: 40px; height: 40px; background: transparent;
    border: 1px solid var(--paper-line); border-radius: var(--radius);
    color: var(--ink-soft); cursor: pointer;
  }
  .nav {
    position: fixed; inset: var(--header-h) 0 auto 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--paper-raised); border-bottom: 1px solid var(--paper-edge);
    box-shadow: var(--shadow-lg); padding: var(--space-3);
    max-height: calc(100vh - var(--header-h)); overflow-y: auto;
    margin-left: 0;
  }
  .nav:not(.is-open) { display: none; }
  .nav a { padding: var(--space-3) var(--space-4); border-radius: var(--radius); }
  .site-header .container { flex-wrap: wrap; }
  .theme-toggle { order: 2; }
}

/* --------------------------------------------------------------------------
   13. Print — it is paper, after all
   -------------------------------------------------------------------------- */
@media print {
  .site-header, .site-footer, .theme-toggle, .nav-toggle, .pagination, .no-print { display: none !important; }
  body { background: #fff; color: #000; }
  .card { box-shadow: none; border: 1px solid #ccc; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: .8em; color: #555; }
}

/* ==========================================================================
   14. The public site — the masthead, the bar under it, and the pages below.
   ========================================================================== */

/* ---------- sections arriving as you reach them ---------- */
/* Eight pixels and a fade. Anything more and an ordinary page of writing
   starts to feel like a slideshow. Nothing is hidden unless the script is
   there to show it again, so the page reads fine with no script at all. */
.will-arrive {
  opacity: 0; transform: translateY(8px);
  transition: opacity .5s var(--ease), transform .5s var(--ease);
}
.will-arrive.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .will-arrive { opacity: 1; transform: none; transition: none; }
}
@media print {
  .will-arrive { opacity: 1 !important; transform: none !important; }
}

/* ---------- the top of the site ---------- */
.site-head { position: relative; }

/* ---------- the bar under the masthead, which follows you down ---------- */
.menubar {
  background: color-mix(in srgb, var(--paper-raised) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(10px); -webkit-backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--paper-edge);
  position: sticky; top: 0; z-index: 60;
  transition: box-shadow .2s var(--ease);
}
.menubar .container { display: flex; align-items: center; gap: var(--space-3); min-height: 60px; }
/* What stands for the site in the bar: the mark, the name in words, or both. */
.bar-crest { display: flex; align-items: center; flex: 0 0 auto; text-decoration: none; color: var(--ink); font-weight: 600; }
/* The mark is bright line art with nothing behind it, which vanishes on a
   pale bar. It gets its own disc of the accent colour to sit on — the same
   mark, legible in both themes. */
.bar-crest img {
  width: 40px; height: 40px; object-fit: contain; padding: 4px;
  background: var(--accent); border-radius: 50%;
  box-shadow: 0 1px 3px rgba(60, 48, 30, .18);
}
/* The site's name in words, when that is what the bar carries. Sized to sit
   with the menu rather than compete with it, and allowed on to a second line
   on a narrow screen, where the alternative is squeezing the menu out. */
.bar-word {
  font-family: var(--font);
  font-size: clamp(.95rem, .88rem + .3vw, 1.12rem);
  font-weight: 700; line-height: 1.12; letter-spacing: -.015em;
  color: var(--ink); max-width: 11ch;
}
.bar-crest.has-word { gap: var(--space-3); }
@media (min-width: 700px) { .bar-word { max-width: none; white-space: nowrap; } }

.menu { display: flex; align-items: center; gap: 2px; margin: 0 0 0 auto; padding: 0; list-style: none; flex-wrap: wrap; justify-content: flex-end; }
.menu > li { position: relative; }
.menu > li > a, .menu .submenu a {
  display: flex; align-items: center; gap: .3rem;
  padding: .55rem .8rem; font-size: .93rem; font-weight: 500;
  color: var(--ink-soft); text-decoration: none; border-radius: var(--radius-sm);
  white-space: nowrap; transition: background .15s var(--ease), color .15s var(--ease);
}
.menu > li > a:hover, .menu > li:focus-within > a { background: var(--paper-sunk); color: var(--ink); }
.menu > li > a[aria-current="page"] { color: var(--accent); font-weight: 600; }
.menu .caret { transition: transform .18s var(--ease); }
.menu > li:hover > a .caret, .menu > li:focus-within > a .caret { transform: rotate(180deg); }

.submenu {
  position: absolute; top: 100%; left: 0; z-index: 70;
  min-width: 232px; margin: 0; padding: var(--space-2); list-style: none;
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .16s var(--ease), transform .16s var(--ease), visibility .16s;
}
.menu > li:hover > .submenu, .menu > li:focus-within > .submenu,
.submenu li:hover > .submenu, .submenu li:focus-within > .submenu {
  opacity: 1; visibility: visible; transform: none;
}
.submenu li { position: relative; }
.submenu a { padding: .5rem .7rem; font-size: .9rem; }
.submenu a:hover { background: var(--paper-sunk); color: var(--ink); }
.submenu .submenu { top: -.4rem; left: 100%; }

@media (max-width: 1024px) {
  .menubar .container { justify-content: space-between; }
  .menu {
    position: absolute; inset: 56px 0 auto 0; margin: 0;
    flex-direction: column; align-items: stretch; justify-content: flex-start;
    background: var(--paper-raised); border-bottom: 1px solid var(--paper-edge);
    box-shadow: var(--shadow-lg); padding: var(--space-3);
    max-height: calc(100vh - 56px); overflow-y: auto;
  }
  .menu:not(.is-open) { display: none; }
  .submenu {
    position: static; opacity: 1; visibility: visible; transform: none;
    box-shadow: none; border: 0; border-left: 2px solid var(--paper-edge);
    border-radius: 0; margin-left: var(--space-4); padding: 0 0 0 var(--space-2);
  }
  .menu .caret { margin-left: auto; }
}

/* ---------- the home page: content left, blog right ---------- */
.home-split { display: grid; gap: clamp(var(--space-5), 4vw, var(--space-7)); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 1000px) { .home-split { grid-template-columns: minmax(0, 1.55fr) minmax(300px, .95fr); } }
@media (max-width: 999px) { .blog-rail { position: static; } }
/* Videos, two across rather than three, so each one is big enough
   to see. One per row once there is no longer room for two. */
.video-grid { display: grid; grid-template-columns: 1fr; gap: clamp(var(--space-4), 3vw, var(--space-6)); }
@media (min-width: 760px) { .video-grid { grid-template-columns: 1fr 1fr; } }
/* A film is a still with a play badge until somebody asks for it. Every tile
   is the same shape, so the column stays level whatever the clips are, and
   nothing downloads while the page is only being read. */
.video-tile {
  position: relative; display: block; width: 100%; padding: 0; cursor: pointer;
  aspect-ratio: 16 / 9; border: 0; border-radius: var(--radius); overflow: hidden;
  /* With a still it shows the still; without one, the accent colour rather
     than a grey rectangle. */
  background:
    var(--tile-still, none) center/cover no-repeat,
    linear-gradient(140deg, var(--accent) 0%, var(--accent-ink) 100%);
  box-shadow: var(--shadow-sm);
  transition: transform .18s var(--ease), box-shadow .18s var(--ease);
}
.video-tile::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(to bottom, rgba(12, 18, 24, .10) 0%, rgba(12, 18, 24, .55) 100%);
}
.video-tile:hover, .video-tile:focus-visible { transform: translateY(-2px); box-shadow: var(--shadow-lg); }
.video-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.video-play {
  position: absolute; z-index: 1; inset: 0; margin: auto;
  width: 58px; height: 58px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(255, 255, 255, .92); color: var(--accent);
  box-shadow: 0 6px 18px rgba(0, 0, 0, .28);
  transition: transform .18s var(--ease), background .18s var(--ease);
}
.video-tile:hover .video-play { transform: scale(1.07); background: #fff; }
.video-name {
  position: absolute; z-index: 1; left: 0; right: 0; bottom: 0;
  padding: var(--space-4); text-align: left;
  color: #fff; font-size: .9rem; font-weight: 600; line-height: 1.35;
  text-shadow: 0 1px 8px rgba(0, 0, 0, .5);
}

/* The film itself, once asked for: black, centred, and closed with Escape or
   a click anywhere off it. */
.video-box {
  position: fixed; inset: 0; z-index: 90; border: 0; padding: 0; margin: 0;
  width: 100%; max-width: 100%; height: 100%; max-height: 100%;
  background: rgba(8, 12, 16, .88); display: grid; place-items: center;
}
.video-box::backdrop { background: rgba(8, 12, 16, .88); }
.video-box video { width: min(94vw, 1200px); max-height: 84vh; border-radius: var(--radius); background: #000; box-shadow: var(--shadow-lg); }
.video-close {
  position: absolute; top: var(--space-4); right: var(--space-4);
  width: 2.6rem; height: 2.6rem; border-radius: 50%; cursor: pointer;
  background: rgba(255, 255, 255, .14); color: #fff; border: 1px solid rgba(255, 255, 255, .4);
  display: grid; place-items: center;
}
.video-close:hover { background: rgba(255, 255, 255, .26); }
@media (prefers-reduced-motion: reduce) {
  .video-tile, .video-tile:hover, .video-play, .video-tile:hover .video-play { transform: none; }
}

.band-intro { margin-bottom: var(--space-6); }
.band-intro > :last-child, .band-outro > :last-child { margin-bottom: 0; }
.band-outro { margin-top: var(--space-6); }
.band-intro h2, .band-outro h2 { margin-bottom: var(--space-3); }

.blog-rail { position: sticky; top: 76px; }
.blog-rail h2 { font-size: 1.15rem; padding-bottom: var(--space-3); border-bottom: 2px solid var(--accent); }
/* A post is a card, and the whole card is the link. */
.blog-rail-posts { display: grid; gap: var(--space-3); margin-top: var(--space-4); }
.rail-post {
  display: flex; gap: var(--space-4); align-items: center;
  padding: var(--space-3); border-radius: var(--radius); text-decoration: none;
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  transition: transform .16s var(--ease), box-shadow .16s var(--ease), border-color .16s var(--ease);
}
.rail-post:hover { transform: translateY(-1px); border-color: var(--paper-line); box-shadow: var(--shadow); }
.rail-shot {
  flex: 0 0 76px; height: 76px; border-radius: var(--radius-sm); overflow: hidden; background: var(--paper-sunk);
}
.rail-shot img { width: 100%; height: 100%; object-fit: cover; display: block; margin: 0; box-shadow: none; }
.rail-words { display: block; min-width: 0; }
.rail-title {
  display: block; font-size: .95rem; font-weight: 600; line-height: 1.35; color: var(--ink);
  /* Two lines, then an ellipsis: the rail is narrow and a long title would
     otherwise push everything else down the page. */
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.rail-post:hover .rail-title { color: var(--accent); }
.rail-post .when { display: block; margin-top: var(--space-2); font-size: .78rem; color: var(--ink-muted); }
@media (prefers-reduced-motion: reduce) { .rail-post, .rail-post:hover { transform: none; } }

/* ---------- the notice strip at the top of the home page ---------- */
.notice-post {
  display: grid; gap: var(--space-5); align-items: center; grid-template-columns: 1fr;
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-sm);
}
@media (min-width: 760px) { .notice-post { grid-template-columns: minmax(0, 280px) 1fr; } }
.notice-post img {
  width: 100%; height: 100%; border-radius: 0;
  /* A frame of a fixed shape, filled by the picture. Whatever is uploaded —
     a collage, a portrait, a wide landscape — the card is the same size and
     the page does not jump as it loads. */
  aspect-ratio: 4 / 3; max-height: 260px; object-fit: cover; object-position: center;
}
.notice-post .body { padding: var(--space-5); }

/* ---------- the module sign-in buttons ---------- */
.module-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3);
  margin-top: var(--space-4); padding-top: var(--space-4);
  border-top: 1px dashed var(--paper-line);
  font-size: .85rem; color: var(--ink-muted);
}
.module-bar .btn { margin-left: auto; }
.module-login {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .35rem .8rem; font-size: .82rem; font-weight: 600;
  background: var(--paper-sunk); color: var(--ink-muted);
  border: 1px solid var(--paper-line); border-radius: var(--radius-pill); text-decoration: none;
}
.module-login:hover { border-color: var(--accent); color: var(--accent); }
/* The two doors sit together and stay on the right of the bar. */
.module-doors { display: inline-flex; align-items: center; gap: var(--space-3); margin-left: auto; flex-wrap: wrap; }
.module-ask { font-size: .8rem; color: var(--ink-faint); text-decoration: none; border-bottom: 1px solid var(--paper-line); }
.module-ask:hover { color: var(--accent); border-bottom-color: currentColor; }

/* Shown across the top of the public site while it is hidden — and only to
   somebody signed in, since nobody else gets this far. */
.hidden-note {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: var(--space-3); padding: var(--space-2) var(--space-4);
  background: var(--amber); color: #fff; font-size: .82rem; font-weight: 600;
}
.hidden-note a { color: #fff; text-underline-offset: 3px; }

/* ---------- people on a page ---------- */
/* Every photograph fills the same frame whatever size it was uploaded at, so
   the page reads as a set of people rather than a column of odd pictures.
   Cover rather than contain, biased a little above centre, because these are
   portraits and the face is nearer the top than the middle. */
.people-grid {
  display: grid; gap: var(--space-5); margin: var(--space-6) 0;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
.person {
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
}
.prose .person img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 4 / 3; object-fit: cover; object-position: center 28%;
  margin: 0; border-radius: 0; box-shadow: none; background: var(--paper-sunk);
}
.person-body { padding: var(--space-5); }
.person-body > :last-child { margin-bottom: 0; }
.person h3 { margin: 0 0 var(--space-2); font-size: 1.05rem; line-height: 1.3; }
.person-role {
  margin: 0 0 var(--space-3); font-size: .8rem; font-weight: 600; line-height: 1.4;
  color: var(--accent);
}
.person p { font-size: .9rem; margin-bottom: var(--space-3); }
/* The wording above the grid keeps a readable measure; the grid gets the
   whole column. */
.prose:has(.people-grid) { max-width: none; }
.prose:has(.people-grid) > p, .prose:has(.people-grid) > h2 { max-width: var(--measure); }

/* ==========================================================================
   THE ASHTON EFFECT — the parts of the old site that had to survive the move
   ========================================================================== */

/* --------------------------------------------------------------------------
   The sparkle
   --------------------------------------------------------------------------
   This is the one piece of the old site everybody names. It is carried over
   as it was written — the same twenty-five sparkles, twelve stars, glow and
   eight light rays, in the same mint — because it is the site's signature and
   a reimplementation would have been a different effect wearing its name.

   Two things were added. The whole effect is decorative, so it is switched
   off for anyone who has asked their computer to stop things moving; and the
   pieces are drawn on their own layer, so twenty-five of them appearing at
   once cannot force the rest of the page to be laid out again.
   -------------------------------------------------------------------------- */
#effect-container { position: relative; display: inline-block; }
#effect-img       { display: block; position: relative; z-index: 2; max-width: 100%; height: auto; }

.effect-shimmer { animation: shimmer 2s ease-in-out infinite; }
@keyframes shimmer {
  0%, 100% { filter: brightness(1) saturate(1); }
  50%      { filter: brightness(1.5) saturate(1.3); }
}

.sparkle {
  position: absolute; width: 4px; height: 4px;
  background: var(--mint); border-radius: 50%;
  pointer-events: none; opacity: 0; will-change: transform, opacity;
  box-shadow: 0 0 8px var(--mint), 0 0 12px var(--mint);
}
.sparkle-animate { animation: sparkle-float 1.5s ease-out; }
@keyframes sparkle-float {
  0%   { opacity: 0; transform: translate(0, 0) scale(0); }
  20%  { opacity: 1; transform: translate(var(--tx), var(--ty)) scale(1); }
  80%  { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(var(--tx) * 1.5), calc(var(--ty) * 1.5)) scale(.5); }
}

.star { position: absolute; width: 8px; height: 8px; pointer-events: none; opacity: 0; will-change: transform, opacity; }
.star::before, .star::after {
  content: ''; position: absolute;
  background: var(--mint); box-shadow: 0 0 6px var(--mint);
}
.star::before { width: 8px; height: 2px; top: 3px; left: 0; }
.star::after  { width: 2px; height: 8px; top: 0;   left: 3px; }
.star-animate { animation: star-twinkle 1.2s ease-in-out; }
@keyframes star-twinkle {
  0%, 100% { opacity: 0; transform: translate(var(--sx), var(--sy)) scale(0) rotate(0deg); }
  50%      { opacity: 1; transform: translate(var(--sx), var(--sy)) scale(1) rotate(180deg); }
}

.glow {
  position: absolute; top: 50%; left: 50%; width: 150px; height: 150px;
  background: radial-gradient(circle, rgba(66, 214, 163, .3) 0%, transparent 70%);
  border-radius: 50%; transform: translate(-50%, -50%);
  opacity: 0; pointer-events: none;
}
.glow-animate { animation: glow-pulse 1.5s ease-out; }
@keyframes glow-pulse {
  0%   { opacity: 0;  transform: translate(-50%, -50%) scale(.5); }
  50%  { opacity: .8; transform: translate(-50%, -50%) scale(1.2); }
  100% { opacity: 0;  transform: translate(-50%, -50%) scale(1.5); }
}

.light-ray {
  position: absolute; top: 50%; left: 50%; width: 2px; height: 60px;
  background: linear-gradient(to bottom,
              rgba(66, 214, 163, 0) 0%, rgba(66, 214, 163, .8) 50%, rgba(66, 214, 163, 0) 100%);
  transform-origin: center top; opacity: 0; pointer-events: none;
  box-shadow: 0 0 8px rgba(66, 214, 163, .6);
}
.light-ray-animate { animation: light-ray-burst 1s ease-out; }
@keyframes light-ray-burst {
  0%   { opacity: 0; height: 20px; }
  50%  { opacity: 1; height: 80px; }
  100% { opacity: 0; height: 100px; }
}

@media (prefers-reduced-motion: reduce) {
  .effect-shimmer, .sparkle, .star, .glow, .light-ray { animation: none !important; opacity: 0; }
  .effect-shimmer { opacity: 1; }
}

/* The masthead graphic sits on its own, centred, with the menu beneath it —
   the arrangement the site already has and visitors already know. */
.effect-hero { text-align: center; padding: var(--space-6) 0 var(--space-4); }
.effect-hero #effect-img { max-height: 450px; margin: 0 auto; }

/* --------------------------------------------------------------------------
   The squares — courses and services
   --------------------------------------------------------------------------
   Faye's diagnosis of the old pages was that everything a course involved sat
   on the courses page, one paragraph after another, so finding the right one
   meant reading all of them. A square shows only enough to be recognised.

   The grid is deliberately not equal-height-by-stretching: every card is the
   same height because the summary is capped, so a long description cannot
   push one square out of line with its neighbours.
   -------------------------------------------------------------------------- */
.card-grid {
  display: grid; gap: var(--space-5);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  margin: var(--space-6) 0;
  padding: 0; list-style: none;
}
.card-grid > li { display: flex; }

.card-square {
  display: flex; flex-direction: column; width: 100%;
  background: var(--paper-raised);
  border: 1px solid var(--paper-edge);
  border-radius: var(--radius-lg);
  overflow: hidden;
  text-decoration: none; color: inherit;
  box-shadow: var(--shadow-sm);
  transition: transform .18s var(--ease), box-shadow .18s var(--ease), border-color .18s var(--ease);
}
.card-square:hover,
.card-square:focus-visible {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg);
  border-color: var(--mint);
  text-decoration: none;
}
/* The whole square is the link, so the focus ring belongs to the square and
   not to the words inside it. */
.card-square:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }

.card-square-media {
  aspect-ratio: 4 / 3; background: var(--paper-sunk);
  overflow: hidden; position: relative;
}
.card-square-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* No picture yet — see _card_grid.php. The square keeps no placeholder at
   all now; a text card is styled by .card-square.is-textual further down. */
:root {
  --sparkle-mark: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l1.9 5.6L19.5 10.5l-5.6 1.9L12 18l-1.9-5.6L4.5 10.5l5.6-1.9z"/><path d="M18.5 16.5l.7 2 2 .7-2 .7-.7 2-.7-2-2-.7 2-.7z"/></svg>');
}
/* Every square's picture area is the same shape, whether there is a picture
   in it or not.
   
   Giving the empty ones a shallower box made the cards in a row different
   heights, and a grid where the cards do not line up reads as broken rather
   than as varied. One aspect for all of them, and the placeholder simply has
   more room to be quiet in. */
.card-square-media { aspect-ratio: 4 / 3; }
/* Faye's course flyers are posters: the title is across the middle, so that
   is what a crop should keep. */
.card-square-media img { object-position: center; }
.card-square-body { padding: var(--space-5); display: flex; flex-direction: column; gap: var(--space-2); flex: 1; }
.card-square h3 { margin: 0; font-size: 1.125rem; line-height: 1.3; }
.card-square-strap { margin: 0; color: var(--ink-soft); font-size: .95rem; }
.card-square-meta {
  margin: 0; font-size: .82rem; font-weight: 600; letter-spacing: .02em;
  color: var(--accent-ink); text-transform: none;
}
.card-square-summary {
  margin: 0; color: var(--ink-muted); font-size: .92rem; line-height: 1.55;
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical;
  line-clamp: 4; overflow: hidden;
}
.card-square-more {
  margin-top: auto; padding-top: var(--space-3);
  font-weight: 600; color: var(--accent); display: inline-flex; align-items: center; gap: .35em;
}
.card-square:hover .card-square-more .icon { transform: translateX(3px); }
.card-square-more .icon { transition: transform .18s var(--ease); }
.card-square-flag {
  position: absolute; top: var(--space-3); left: var(--space-3);
  background: var(--mint); color: var(--mint-ink);
  font-size: .72rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  padding: .25em .7em; border-radius: var(--radius-pill);
}

/* The page behind a square. */
.card-page-head { display: grid; gap: var(--space-5); margin-bottom: var(--space-6); }
@media (min-width: 800px) { .card-page-head { grid-template-columns: 1fr 1fr; align-items: center; } }
.card-page-head img { width: 100%; border-radius: var(--radius-lg); display: block; }
.card-facts { list-style: none; padding: 0; margin: var(--space-4) 0; display: grid; gap: var(--space-2); }
.card-facts li { display: flex; gap: var(--space-3); align-items: baseline; }
.card-facts dt, .card-facts .k { color: var(--ink-muted); min-width: 6.5em; font-size: .9rem; }
.card-nav { display: flex; justify-content: space-between; gap: var(--space-4); margin-top: var(--space-7); flex-wrap: wrap; }

/* --------------------------------------------------------------------------
   Booking
   -------------------------------------------------------------------------- */
.booking-types { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); padding: 0; list-style: none; }
.booking-type-card {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-5); border: 1px solid var(--paper-edge); border-radius: var(--radius-lg);
  background: var(--paper-raised); text-decoration: none; color: inherit; height: 100%;
  transition: border-color .18s var(--ease), transform .18s var(--ease), box-shadow .18s var(--ease);
}
.booking-type-card:hover, .booking-type-card:focus-visible {
  border-color: var(--mint); transform: translateY(-2px); box-shadow: var(--shadow); text-decoration: none;
}
.booking-type-card h2, .booking-type-card h3 { margin: 0; font-size: 1.05rem; }
.booking-type-when { color: var(--accent-ink); font-weight: 600; font-size: .9rem; }

.booking-cal { margin: var(--space-5) 0; }
.booking-cal-days {
  display: flex; gap: var(--space-2); overflow-x: auto; padding: 0 0 var(--space-3);
  list-style: none; margin: 0; scroll-snap-type: x proximity;
}
.booking-cal-day {
  flex: 0 0 auto; scroll-snap-align: start;
  min-width: 5.5rem; padding: var(--space-3) var(--space-4);
  border: 1px solid var(--paper-edge); border-radius: var(--radius);
  background: var(--paper-raised); text-align: center; text-decoration: none; color: inherit;
  display: flex; flex-direction: column; gap: .15em; line-height: 1.2;
}
.booking-cal-day .dow  { font-size: .78rem; color: var(--ink-muted); text-transform: uppercase; letter-spacing: .04em; }
.booking-cal-day .dnum { font-size: 1.3rem; font-weight: 600; }
.booking-cal-day .free { font-size: .72rem; color: var(--accent); font-weight: 600; }
.booking-cal-day:hover { border-color: var(--mint); text-decoration: none; }
.booking-cal-day.is-selected {
  border-color: var(--mint); background: var(--mint); color: var(--mint-ink); box-shadow: var(--shadow);
}
.booking-cal-day.is-selected .dow,
.booking-cal-day.is-selected .free { color: var(--mint-ink); }
/* A day with nothing free is shown, not hidden — an empty Tuesday is
   information, and a calendar that silently skips days looks broken. */
.booking-cal-day.is-empty { opacity: .45; pointer-events: none; }
.booking-cal-day.is-empty .free { color: var(--ink-faint); }

.booking-slots {
  display: grid; gap: var(--space-2);
  grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr));
  list-style: none; padding: 0; margin: var(--space-4) 0;
}
.booking-slot {
  display: block; text-align: center; cursor: pointer;
  padding: var(--space-3); border: 1px solid var(--paper-edge); border-radius: var(--radius);
  background: var(--paper-raised); font-weight: 600; color: var(--ink);
  transition: border-color .15s var(--ease), background .15s var(--ease);
}
.booking-slot input { position: absolute; opacity: 0; pointer-events: none; }
.booking-slot:hover { border-color: var(--mint); }
.booking-slot.is-chosen,
.booking-slot:has(input:checked) { background: var(--mint); border-color: var(--mint-deep); color: var(--mint-ink); }
.booking-slot:has(input:focus-visible) { outline: 3px solid var(--focus); outline-offset: 2px; }
.booking-slots-empty { color: var(--ink-muted); padding: var(--space-5); background: var(--paper-sunk); border-radius: var(--radius); }

.booking-form { margin-top: var(--space-6); }
.booking-summary {
  background: var(--accent-soft); border: 1px solid var(--mint);
  border-radius: var(--radius); padding: var(--space-4) var(--space-5); margin: var(--space-5) 0;
}
.booking-summary h2, .booking-summary h3 { margin: 0 0 var(--space-2); font-size: 1rem; }
.booking-confirm { text-align: center; padding: var(--space-7) 0; }
.booking-confirm .ref {
  display: inline-block; font-family: var(--font-mono); font-size: 1.05rem;
  background: var(--paper-sunk); padding: .4em .8em; border-radius: var(--radius-sm);
}

/* --------------------------------------------------------------------------
   Buttons in the site's own colour
   -------------------------------------------------------------------------- */
.btn-mint, .button.btn-mint, a.btn-mint {
  background: var(--mint); color: var(--mint-ink); border: 1px solid var(--mint-deep);
  font-weight: 700; text-decoration: none;
}
.btn-mint:hover, a.btn-mint:hover { background: var(--mint-deep); color: var(--mint-ink); text-decoration: none; }

/* The old site drew a thick underline under every link in body copy and it is
   part of how the pages read, so it is kept — but at 3px it was competing
   with the headings for weight. Two is still unmistakably a link and lets the
   writing be the loudest thing on the page. */
.prose a:not(.btn):not(.button):not(.card-square):not(.booking-type-card) {
  text-decoration: underline;
  text-decoration-color: var(--mint);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}
.prose a:hover { text-decoration-color: var(--accent); }

/* What the contact form will send back, said before the form rather than
   after it. */
.guide-offer {
  background: var(--accent-soft); border: 1px solid var(--mint);
  border-radius: var(--radius); padding: var(--space-4) var(--space-5); margin: var(--space-5) 0;
}
.guide-offer h2 { margin: 0 0 var(--space-3); font-size: 1rem; display: flex; align-items: center; gap: .5em; }
.guide-offer ul { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-3); }
.guide-offer li { display: grid; gap: .15em; }
.guide-offer span { color: var(--ink-muted); font-size: .92rem; }

/* The day strip scrolls inside itself. Without min-width:0 it refuses to
   shrink below its content — the default for a flex or grid child — and a
   fortnight of days pushes the whole page sideways instead. */
.booking-cal, .booking-cal-days { min-width: 0; max-width: 100%; }
.booking-cal-days { scrollbar-width: thin; }

/* The summary of what is about to be booked, read as label and answer rather
   than as an indented list. */
.booking-summary dl { display: grid; grid-template-columns: auto 1fr; gap: .35em var(--space-4); margin: 0; }
.booking-summary dt { color: var(--ink-muted); font-size: .9rem; }
.booking-summary dd { margin: 0; font-weight: 600; }
@media (max-width: 480px) {
  .booking-summary dl { grid-template-columns: 1fr; gap: 0 0; }
  .booking-summary dd { margin-bottom: var(--space-3); }
}

/* The previous/next buttons carry a course title, and some of those are a
   whole sentence. On a narrow screen the pair has to stack and each has to be
   allowed to wrap, or one button alone is wider than the phone. */
.card-nav .btn {
  max-width: 100%;
  white-space: normal;
  text-align: left;
  min-width: 0;
}
@media (max-width: 620px) {
  .card-nav { flex-direction: column; align-items: stretch; }
  .card-nav .btn { justify-content: flex-start; }
}

/* ==========================================================================
   THE MASTHEAD — dark, in both themes, always
   --------------------------------------------------------------------------
   The graphic is bright mint line art with nothing behind it. On the pale
   paper of the light theme it washed out and read as cyan rather than as the
   green the rest of the site uses — the same colour, but the eye judges a
   colour against what surrounds it, and white surrounds badly.

   So the masthead carries its own dark ground and keeps it whichever theme
   the reader has chosen. That is also how Faye's own flyers are made: bright
   green on near-black. The tokens below are fixed values rather than theme
   variables on purpose — a dark band that turns pale in the light theme is
   exactly the thing being fixed.
   ========================================================================== */
.site-head {
  --head-bg:     #0d1512;
  --head-bg-2:   #14211c;
  --head-line:   #223029;
  --head-ink:    #eaf5f0;
  --head-ink-dim:#9db3aa;
  background: var(--head-bg);
  color: var(--head-ink);
}

/* A little depth behind the graphic, so it is not a flat rectangle. */
.site-head .effect-hero {
  background:
    radial-gradient(ellipse 120% 80% at 50% 0%, var(--head-bg-2) 0%, var(--head-bg) 70%);
  padding: var(--space-6) var(--space-4) var(--space-5);
  margin: 0; max-width: none;
}
.site-head .effect-hero > * { max-width: var(--container); margin-inline: auto; }

/* The bar keeps the dark ground rather than the paper one, and stays dark
   when it sticks to the top of the screen. */
.site-head .menubar {
  background: color-mix(in srgb, var(--head-bg) 92%, transparent);
  border-bottom: 1px solid var(--head-line);
  color: var(--head-ink);
}

.site-head .bar-word,
.site-head .bar-crest { color: var(--head-ink); }

.site-head .menu > li > a,
.site-head .menu .submenu a { color: var(--head-ink-dim); }
.site-head .menu > li > a:hover,
.site-head .menu > li:focus-within > a {
  background: rgba(255, 255, 255, .07);
  color: var(--head-ink);
}
/* The current page is marked in the site's mint, which on this ground has
   plenty of contrast — unlike the darker accent green used on paper. */
.site-head .menu > li > a[aria-current="page"] { color: var(--mint); font-weight: 600; }

/* The dropdown belongs to the dark bar it hangs from. */
.site-head .submenu {
  background: var(--head-bg-2);
  border-color: var(--head-line);
  box-shadow: 0 16px 40px rgba(0, 0, 0, .5);
}
.site-head .submenu a:hover { background: rgba(255, 255, 255, .07); color: var(--head-ink); }

.site-head .theme-toggle,
.site-head .nav-toggle {
  color: var(--head-ink-dim);
  border-color: var(--head-line);
  background: transparent;
}
.site-head .theme-toggle:hover,
.site-head .nav-toggle:hover { color: var(--head-ink); background: rgba(255, 255, 255, .07); }

/* Focus rings have to be visible on the dark ground too, not just on paper. */
.site-head a:focus-visible,
.site-head button:focus-visible { outline: 3px solid var(--mint); outline-offset: 2px; }

/* The graphic sits a little tighter to the bar now that there is a ground
   holding the two together. */
.effect-hero { padding: var(--space-6) 0 var(--space-4); }
.effect-hero #effect-img { max-height: 400px; }

/* On a phone the menu opens as a panel; it inherits the dark ground. */
@media (max-width: 1024px) {
  .site-head .menu {
    background: var(--head-bg-2);
    border-color: var(--head-line);
  }
  .effect-hero #effect-img { max-height: 220px; }
}

/* ==========================================================================
   BANDS — the pages divided the way the old site divides them
   --------------------------------------------------------------------------
   The old site is built in sections, and inside a section the content sits in
   one, two or four columns. Flattening that into a single column of prose is
   what made an imported page feel like a wall of text — the same words, with
   the thing that paced them thrown away.

   Divi writes its widths as twenty-fourths, so the grid here is 24 columns
   wide and each column carries the span it had. On a phone every column is
   full width, which is what the original does too.
   ========================================================================== */
.band {
  --band-bg: transparent;
  background: var(--band-bg);
  padding-block: clamp(var(--space-6), 4vw, var(--space-8));
}
/* A band that carries a colour needs room to show it and a join to the next. */
.band[style*="--band-bg"] { padding-block: clamp(var(--space-7), 5vw, var(--space-9)); }

/* Consecutive plain bands would otherwise double their padding at the join,
   leaving a gap far bigger than anything on the old site. */
.band + .band:not([style*="--band-bg"]) { padding-top: 0; }
.band:first-child { padding-top: var(--space-5); }
.band:last-child  { padding-bottom: var(--space-6); }

.band-row {
  display: grid;
  grid-template-columns: repeat(24, minmax(0, 1fr));
  gap: clamp(var(--space-4), 3vw, var(--space-7));
  align-items: start;
  max-width: var(--container);
  margin-inline: auto;
}
.band-row + .band-row { margin-top: clamp(var(--space-5), 3vw, var(--space-7)); }

.band-col {
  grid-column: span var(--span, 24);
  min-width: 0;   /* a long word or a wide table must not push the grid open */
}

/* A column of writing is unreadable at full page width, so a full-width
   column holds itself to a comfortable measure — while a half or a quarter,
   already narrow, uses everything it has. */
.band-col[style*="--span:24"] > * { max-width: var(--measure); }
.band-col[style*="--span:24"] > h1,
.band-col[style*="--span:24"] > h2 { max-width: 24ch; }

.band-col img { max-width: 100%; height: auto; border-radius: var(--radius); display: block; }
.band-col > :first-child { margin-top: 0; }
.band-col > :last-child  { margin-bottom: 0; }

/* The same typography the rest of the site uses, applied inside a band. */
.band-col h2 { font-size: clamp(1.5rem, 1.2rem + 1.2vw, 2.1rem); line-height: 1.2; margin: 0 0 var(--space-4); }
.band-col h3 { font-size: clamp(1.2rem, 1.05rem + .5vw, 1.4rem); margin: var(--space-5) 0 var(--space-3); }
.band-col h4 { font-size: 1.02rem; color: var(--ink-soft); margin: var(--space-4) 0 var(--space-2); }
.band-col p, .band-col li { line-height: 1.65; }
.band-col p { margin: 0 0 var(--space-4); }
.band-col ul, .band-col ol { margin: 0 0 var(--space-4); padding-left: 1.25em; }
.band-col li { margin-bottom: var(--space-2); }
.band-col a:not(.btn) {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-color: var(--mint);
  text-decoration-thickness: 3px;
  text-underline-offset: 3px;
}
.band-col a:not(.btn):hover { text-decoration-color: var(--accent); }
.band-col .btn { display: inline-flex; }

/* Two columns become one on a tablet, and a quarter-width column — which is
   almost always a small image or a caption beside something — pairs up rather
   than going full width on its own. */
@media (max-width: 900px) {
  .band-col { grid-column: span 24; }
  .band-col[style*="--span:6"], .band-col[style*="--span:8"] { grid-column: span 12; }
  .band-col[style*="--span:24"] > * { max-width: none; }
}
/* Below this width every column is full width, so the twenty-four tracks have
   nothing left to do — and they were doing harm: twenty-three gaps of 16px is
   368px of gutter inside a 342px row, which pushed the page 4px wider than the
   phone. One column, one gap. */
@media (max-width: 560px) {
  .band-row { grid-template-columns: 1fr; }
  .band-col,
  .band-col[style*="--span:6"], .band-col[style*="--span:8"] { grid-column: 1 / -1; }
}

/* A page that is bands does not want the prose wrapper's own width limit on
   top of the grid's. */
.prose:has(.band) { max-width: none; }
.prose > .band:first-child { padding-top: 0; }

/* Some of the buttons carried over from the old site have a whole sentence
   for a label. A button that will not wrap is simply wider than the page, and
   a centred one overflows both edges at once. Every button may wrap and none
   may exceed its column. */
.btn, .button, a.btn {
  max-width: 100%;
  white-space: normal;
  overflow-wrap: anywhere;
}
.band-col .btn {
  display: inline-flex;
  text-align: left;
  align-items: center;
}

/* The portrait that opens the home page.
   It is a tall photograph, and a full-width column of writing is the wrong
   shape for one — stretched to the measure it was taller than the screen and
   pushed everything else below the fold. Half that width reads as a portrait,
   and the space above it separates it from the menu it was sitting under. */
/* The portrait that opens the home page.
   --------------------------------------------------------------------------
   Done here rather than by wrapping the image in the stored content, because
   content only reaches an installed site through the installer, and the
   installer does not run again. A rule keyed off the page's own layout ships
   with the code, so a redeploy is enough — which is what a change to how
   something LOOKS ought to cost.

   Both spellings are matched: the bare image on a site whose content predates
   the change, and the figure a fresh install now writes.

   Written to out-specify the two band rules that would otherwise catch it —
   the one giving every full-width child the reading measure, and the one that
   strips the top margin from whatever comes first in a column. Both are right
   for a paragraph and wrong for a portrait. */
.home-invite .band:first-child .band-col > img:first-child,
.home-invite .band:first-child .band-col > .lead-portrait,
.band-col > .lead-portrait,
.band-col > .lead-portrait:first-child,
.prose .lead-portrait {
  display: block;
  max-width: 340px;
  width: 100%;
  height: auto;
  margin-top: clamp(var(--space-6), 5vw, var(--space-8));
  margin-bottom: var(--space-6);
  margin-inline: 0;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}
/* The figure is the frame; the picture inside it fills the frame and carries
   no second shadow. The grouped selector above is the more specific of the
   two, so the figure was keeping a shadow and a radius of its own and the
   portrait was sitting in a second, slightly larger frame. */
.lead-portrait,
.home-invite .band:first-child .band-col > .lead-portrait,
.band-col > .lead-portrait,
.band-col > .lead-portrait:first-child,
.prose .lead-portrait { box-shadow: none; border-radius: 0; }
.lead-portrait img {
  width: 100%; height: auto; display: block;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}
@media (max-width: 560px) {
  .home-invite .band:first-child .band-col > img:first-child,
  .home-invite .band:first-child .band-col > .lead-portrait,
  .band-col > .lead-portrait,
  .band-col > .lead-portrait:first-child,
  .prose .lead-portrait { max-width: 240px; }
}

/* --------------------------------------------------------------------------
   The masthead, smaller on the pages that are not the home page
   --------------------------------------------------------------------------
   At full size the graphic is 400px tall, which is right on the home page —
   it is the first thing anybody sees and the sparkle is the point. On every
   other page it was pushing the heading, and often the whole first paragraph,
   below the fold: somebody arriving at the booking form had to scroll before
   they could see what they were booking.

   So the graphic keeps its full height where it is doing a job and steps back
   where the page's own content should lead. The mark is still there, still
   sparkling, still a link home — just not taking the top third of the screen
   on the way to a form.
   -------------------------------------------------------------------------- */
.site-head:not(.is-home) .effect-hero {
  padding-top: var(--space-5);
  padding-bottom: var(--space-3);
}
.site-head:not(.is-home) #effect-img {
  max-height: 190px;
}
@media (max-width: 1024px) {
  .site-head:not(.is-home) #effect-img { max-height: 130px; }
}

/* The page's own heading needs air under the bar, on every page. Several
   templates were setting their own top margin and several were not, so the
   first line sat at a different height depending which page you were on. */
main > .section:first-child,
main > .container:first-child { padding-top: clamp(var(--space-5), 3vw, var(--space-7)); }
.page-head { margin-bottom: var(--space-6); }
.crumbs { margin-bottom: var(--space-4); }

/* Course dates in a month row.
   The cards were sizing to their own content, so a date that wrapped onto two
   lines made its card taller than the one beside it and the row looked
   accidental. Stretching them puts the Book buttons on one line, which is
   also where the eye goes when it is choosing between dates. */
.booking-types > li { display: flex; }
.booking-type-card { width: 100%; }
.booking-type-card .btn { margin-top: auto; align-self: flex-start; }

/* A picture inside the wording above a grid is illustration, not the point of
   the page — at the full width of a column of prose it was bigger than the
   squares it was introducing. */
.band-col > p > img,
.band-col > img { max-width: min(100%, 420px); }

/* ==========================================================================
   HOME BLOCKS, POST GRID AND THE ODDS AND ENDS THAT HAD NO RULES
   --------------------------------------------------------------------------
   These classes were being written by the templates but never styled, so the
   browser fell back to plain block layout: the news posts stacked edge to
   edge at full width with nothing between them, and the section headings sat
   on top of their grids. Everything below is the missing half.
   ========================================================================== */

/* Each band of the home page — services, courses, news — is a room of its
   own, so it gets air above and below rather than running into its
   neighbour. */
.home-block { margin: var(--space-8) 0; }
.home-block:last-of-type { margin-bottom: var(--space-7); }

/* Heading on the left, "all of them" link on the right, sharing a baseline
   and separated from the grid beneath. On a phone the link drops under the
   heading rather than squeezing beside it. */
.block-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-4) var(--space-5); flex-wrap: wrap;
  margin-bottom: var(--space-5);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--paper-line);
}
.block-head h2 { margin: 0; }
.block-head > a {
  display: inline-flex; align-items: center; gap: .4em;
  font-size: .92rem; font-weight: 600; color: var(--accent);
  text-decoration: none; white-space: nowrap;
}
.block-head > a:hover { text-decoration: underline; }

/* The news posts. This is the rule that was missing entirely — without it
   the cards were block-level, full width and touching. */
.post-grid {
  display: grid; gap: var(--space-5);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  align-items: stretch;
}
.post-grid > .post-card { margin: 0; }
/* One post on its own would otherwise stretch the full width of the page and
   read as a banner rather than as a card. */
.post-grid > .post-card:only-child { max-width: 34rem; }

/* The opening paragraph of a page, a size up from the body but not a
   heading. */
.lede { font-size: 1.06rem; line-height: 1.65; color: var(--ink-soft, var(--ink-muted)); }
.lede > p:first-child { margin-top: 0; }
.lede > p:last-child { margin-bottom: 0; }

/* The two buttons under the home page invitation, and the "next free time"
   line beneath them. */
.home-actions {
  display: flex; flex-wrap: wrap; gap: var(--space-3);
  margin: var(--space-6) 0 var(--space-4);
}
.home-next {
  display: flex; align-items: center; gap: .45em; flex-wrap: wrap;
  margin: 0; font-size: .94rem; color: var(--ink-muted);
}
.home-next a { font-weight: 600; color: var(--accent); }

/* The closing invitation. Set apart from the page above it so it reads as a
   destination rather than as one more paragraph. */
.cta-panel {
  margin: var(--space-8) 0 var(--space-7);
  padding: clamp(var(--space-5), 4vw, var(--space-7));
  background: var(--paper-sunk);
  border: 1px solid var(--paper-edge);
  border-radius: var(--radius-lg);
  text-align: center;
}
.cta-panel h2 { margin: 0 0 var(--space-3); }
.cta-panel > p { margin: 0 auto var(--space-5); max-width: 46ch; color: var(--ink-muted); }
.cta-panel > p:last-child {
  display: flex; flex-wrap: wrap; gap: var(--space-3);
  justify-content: center; margin-bottom: 0; max-width: none;
}

/* "There is nothing here yet" — an answer, so it is given the weight of one
   rather than left as a stray sentence. */
.empty-note {
  display: flex; align-items: flex-start; gap: var(--space-3);
  margin: var(--space-6) 0;
  padding: var(--space-5);
  background: var(--paper-sunk);
  border: 1px dashed var(--paper-edge);
  border-radius: var(--radius);
  color: var(--ink-muted);
}
.empty-note svg { flex: 0 0 auto; margin-top: .1em; color: var(--accent); }

/* Label-and-answer lists — booking summaries, the details on a confirmation
   page. Inside .booking-summary this is already handled; this is the same
   shape for everywhere else it is used. */
.kv { display: grid; grid-template-columns: auto 1fr; gap: .4em var(--space-4); margin: var(--space-4) 0; }
.kv dt { color: var(--ink-muted); font-size: .9rem; }
.kv dd { margin: 0; font-weight: 600; }
@media (max-width: 480px) {
  .kv { grid-template-columns: 1fr; gap: 0; }
  .kv dd { margin-bottom: var(--space-3); }
}

/* The day tiles in the appointment calendar name their parts .dom/.mon/.how;
   the rules here were written against two older names, so the date, the month
   and the count were all rendering at body size. */
.booking-cal-day .dom { display: block; font-size: 1.3rem; font-weight: 600; line-height: 1.15; }
.booking-cal-day .mon { display: block; font-size: .78rem; color: var(--ink-muted); text-transform: uppercase; letter-spacing: .04em; }
.booking-cal-day .how { display: block; margin-top: .25em; font-size: .72rem; color: var(--accent); font-weight: 600; }
.booking-cal-day.is-selected .dom,
.booking-cal-day.is-selected .mon,
.booking-cal-day.is-selected .how { color: var(--mint-ink); }
.booking-cal-day.is-empty .how { color: var(--ink-faint); }

/* A footer link that carries an icon keeps the icon on the same line as the
   words — an email address is long enough to wrap, and it was leaving the
   envelope stranded on the line above. */
.site-footer a { display: inline-flex; align-items: baseline; gap: .45em; }
.site-footer a svg { flex: none; align-self: center; }

/* .panel is an admin card, and the two public pages that borrow it —
   "Ask for an account" is the one that matters — load only this stylesheet,
   so it arrived with no card at all. Same shape as the admin one. */
.panel {
  background: var(--paper-raised);
  border: 1px solid var(--paper-edge);
  border-radius: var(--radius-lg);
  padding: clamp(var(--space-4), 3vw, var(--space-5));
  margin-bottom: var(--space-4);
}
.panel > h2, .panel > h3 {
  font-size: 1.02rem; margin-bottom: var(--space-4);
  padding-bottom: var(--space-3); border-bottom: 1px solid var(--paper-edge);
}

/* ==========================================================================
   A CARD WITH NO PICTURE — A TEXT HEADER, NOT A GREEN BLOCK
   --------------------------------------------------------------------------
   The placeholder these cards used to carry was a mint panel with the site's
   mark in it. One looked deliberate; twelve down a services page looked like
   the page had failed to load. A card with nothing to show now shows nothing
   and leads with its title, under a short rule that keeps the mint present as
   an accent rather than as a surface.

   Rows stay even without it: every square in a row is stretched to the same
   height, so a text card beside a picture card simply gets more room for its
   words.
   ========================================================================== */
.card-square.is-textual .card-square-body {
  padding-top: var(--space-5);
  gap: var(--space-3);
}
.card-square.is-textual .card-square-body::before {
  content: '';
  display: block;
  width: 34px; height: 3px;
  border-radius: 2px;
  background: var(--mint);
  margin-bottom: var(--space-2);
}
/* The title carries the card on its own here, so it is allowed to be a
   little larger than the one sitting under a photograph. */
.card-square.is-textual h3 { font-size: 1.22rem; }
/* The rule is the card's own mark: it picks up the hover like the border
   does, so the whole square still reads as one object. */
.card-square.is-textual:hover .card-square-body::before,
.card-square.is-textual:focus-visible .card-square-body::before { background: var(--accent); }

/* Without a picture to sit on, "Popular" is a line of the card rather than a
   badge floating over a corner. */
.card-square-flag.is-inline {
  position: static; align-self: flex-start;
  margin-bottom: calc(var(--space-1) * -1);
}

/* ==========================================================================
   THE HOME PAGE OPENING — THE PORTRAIT BESIDE THE WORDS
   --------------------------------------------------------------------------
   The picture sat on its own line above the writing, and because a full-width
   column holds its children to a reading measure, the whole opening finished
   around 810px on a 1600px screen: a tall photograph, a column of text under
   it, and half the page empty to the right.

   It is now two columns — the portrait in a narrow one, the writing in a
   wider one beside it — and the pair is centred, so the white space falls
   evenly either side instead of piling up on the right.

   Two columns rather than a float: a float lets the text run under the
   picture, and the writing below would then be a full 1000px line, which is
   half again longer than anyone reads comfortably. Holding the words to one
   column keeps every line at the same readable width whether it is beside the
   photograph or below it.
   ========================================================================== */
@media (min-width: 900px) {
  .home-invite .band:first-child .band-row {
    /* Wide enough for the portrait, the gap and a full measure of text, and
       no wider — so centring it actually centres the content. */
    max-width: calc(290px + var(--space-7) + var(--measure));
    margin-inline: auto;
  }

  .home-invite .band:first-child .band-col:has(> .lead-portrait),
  .home-invite .band:first-child .band-col:has(> img:first-child) {
    display: grid;
    grid-template-columns: 290px minmax(0, 1fr);
    column-gap: var(--space-7);
    align-items: start;
  }

  /* The portrait spans the left column rather than sitting in its first cell.
     Holding one cell made the first row as tall as the photograph, so the
     heading beside it floated at the top of a 400px void with its own first
     paragraph pushed below the picture. Spanning lets each row on the right
     take its own height and the picture simply run alongside them. */
  .home-invite .band:first-child .band-col > .lead-portrait,
  .home-invite .band:first-child .band-col > img:first-child {
    grid-column: 1; grid-row: 1 / span 50; align-self: start;
    width: 100%; max-width: 290px;
    /* level with the cap height of the first line, not with its box */
    margin: .3rem 0 var(--space-5);
  }

  /* Everything else runs down the right-hand column, at the measure. */
  .home-invite .band:first-child .band-col > *:not(.lead-portrait):not(img:first-child) {
    grid-column: 2;
    max-width: var(--measure);
  }
  .home-invite .band:first-child .band-col > .lead-portrait + * { margin-top: 0; }
}

/* Narrower than that there is no room to put the picture beside anything, so
   it goes back to being a block of its own above the writing. */

/* ==========================================================================
   WHERE THE WRITING SITS ON THE PAGE
   --------------------------------------------------------------------------
   Every page was laying its text at the left edge of a 1440px container and
   capping each paragraph at a 68-character measure, so on a 1600px screen the
   writing ran from 104px to 838px and the whole right-hand half of the page
   was empty. It read as a page that had failed to load rather than a design.

   The measure is right — 68 characters is about as long a line as anyone
   reads comfortably, and stretching the text to 1400px would make the pages
   harder to read, not better. What was wrong is where the column sat. So a
   page that is nothing but an article gets the narrow container (see
   front/page.php, which decides that from the page's own columns) and the
   heading, the writing and the white space all line up together.

   Intro and outro wording on a page that also has a grid — the services and
   courses pages — is deliberately NOT centred: it tops and tails the squares,
   so it lines up with their left edge instead of floating in the middle of
   them.
   ========================================================================== */

/* A row with one full-width column has nothing for its twenty-four tracks to
   do, and their twenty-three gaps add up to more than the row is: the same
   arithmetic that was pushing phones sideways. One track, no gaps. */
.band-row:has(> .band-col[style*="--span:24"]:only-child) {
  grid-template-columns: minmax(0, 1fr);
}
.band-row:has(> .band-col[style*="--span:24"]:only-child) > .band-col { grid-column: 1 / -1; }

/* A call to action written as a sentence — "Read Faye's full story" — is
   marked up as a button in the content itself, with class="btn btn-primary",
   rather than being promoted automatically here. An earlier version of this
   file promoted any paragraph whose only ELEMENT child was a link, which CSS
   cannot tell apart from a link sitting inside a sentence: it turned the
   words "consultancy packages" in the middle of the services pricing line
   into a green button. Faye can add the same two classes in the editor. */

/* The home page opening is the one single-column band that is NOT just a
   column of writing — it has the portrait beside the words — so it is wider
   than the measure by exactly the width of the picture and its gutter. This
   has to come after the rule above, which would otherwise cap it at the
   measure and squeeze the text into 47 characters a line. */
@media (min-width: 900px) {
  .home-invite .band:first-child .band-row {
    max-width: calc(290px + var(--space-7) + var(--measure));
  }
}

/* The narrow-screen cap on the portrait, restated after the centring rules
   above so it is not undone by them. Dominic asked for this photograph at
   half size on a phone and that is still what it should be. */
@media (max-width: 560px) {
  .band-row:has(> .band-col[style*="--span:24"]:only-child) .band-col > .lead-portrait,
  .home-invite .band:first-child .band-col > .lead-portrait,
  .band-col > .lead-portrait,
  .prose .lead-portrait { max-width: 240px; }
}

/* ==========================================================================
   THE LIGHT BEHIND THE MASTHEAD
   --------------------------------------------------------------------------
   The graphic was sitting on a flat rectangle. This puts a source of light
   above it — soft beams thrown down past the type, swinging a few degrees
   over half a minute — which picks up the flare already painted into the
   artwork and gives the band some depth.

   Three things it is careful about:

   The sparkle is Faye's, and it must not be touched. The beams are drawn on
   this element's own ::before and ::after and clipped with clip-path rather
   than by putting overflow:hidden on the hero, because the sparkle script
   appends its stars into #effect-container inside this box and hiding the
   overflow would cut the ones near the edges.

   The menu below has to keep its contrast. The vignette darkens the outside
   of the band rather than lightening it, and the beams are strongest at the
   top where there is nothing to read, so the ground behind "Home / About /
   Services" is no lighter than it was.

   And it stops for anyone who has asked their machine for less motion — a
   slow sweep behind large type is exactly the sort of thing that bothers
   people who get motion sick.
   ========================================================================== */
.site-head .effect-hero { position: relative; isolation: isolate; }
.site-head .effect-hero > * { position: relative; z-index: 1; }
.site-head .effect-hero::before,
.site-head .effect-hero::after {
  content: ''; position: absolute; inset: 0; z-index: 0;
  pointer-events: none;
  clip-path: inset(0);       /* keeps the blur inside the band */
}

/* The beams. Only the transform animates, so the blurred layer is rasterised
   once and then moved by the compositor rather than redrawn every frame. */
.site-head .effect-hero::before {
  background:
    conic-gradient(from 200deg at 50% 4%,
      transparent   0deg, rgba(66, 214, 163, .20)  11deg, transparent  24deg,
      transparent  36deg, rgba(66, 214, 163, .13)  48deg, transparent  62deg,
      transparent  92deg, rgba(66, 214, 163, .18) 104deg, transparent 118deg,
      transparent 130deg, rgba(66, 214, 163, .12) 142deg, transparent 156deg,
      transparent 360deg);
  filter: blur(14px);
  transform-origin: 50% 4%;
  will-change: transform;
  animation: head-sweep 34s ease-in-out infinite alternate;
}

/* The source itself, and the vignette that keeps the edges down. */
.site-head .effect-hero::after {
  background:
    radial-gradient(ellipse 34% 40% at 50% 6%, rgba(126, 233, 196, .24), transparent 72%),
    radial-gradient(ellipse 90% 85% at 50% 45%, transparent 40%, rgba(0, 0, 0, .58) 100%);
}

@keyframes head-sweep {
  from { transform: rotate(-4.5deg); }
  to   { transform: rotate(4.5deg); }
}

@media (prefers-reduced-motion: reduce) {
  .site-head .effect-hero::before { animation: none; transform: rotate(0deg); }
}
