/* ==========================================================================
   Paper Air — the house design language

   The system is Starting Point; the look it wears is Paper Air, and the two
   are separate on purpose: the system gains releases, the look gains
   refinements, and neither should be mistaken for the other.

   Influences, for talking about it: Apple's own type stack, concentric radii,
   the translucent capsule, tactile press. It is not a copy of anything — these
   greys, these hairlines, this voice.

   THE FIVE COMMANDMENTS
   1. NO ICONS in an action row, in navigation, or in a list of channels.
      Words in the menu voice scan faster than pictures that need decoding.
      An icon survives only where a word cannot do the job. `.acts` is the
      mechanism: put it on a row and its buttons become menu-voice pills with
      their icons hidden.
   2. THE MENU VOICE is the one costume for an action chip — 600 11.5px, .5px
      tracking, uppercase, 10px/15px, a full pill. Hover lifts by 1px; press
      scales to .95. Reduced motion stills both, always.
   3. Uppercase micro-pills are for ACTION CHIPS, never form submits. "Save"
      and "Add this date" stay sentence case in a standard .btn — capitals on
      a form shout.
   4. COLOUR MEANS SOMETHING. One filled button per surface: the thing
      somebody came to do. Everything else is neutral. A tone lives in a 5px
      dot, not a painted box, and the accent is never spent on a label.
   5. One component, one recipe. A surface that wants the look wears the
      shared class or copies the exact spec. It does not approximately match.

   Every value here is a token, and Admin → Look writes a handful of them per
   site. Nothing in this file needs editing to give a site its own colours,
   heading face or spacing.
   ========================================================================== */

/* Poppins is bundled rather than fetched, so no site built from this makes a
   request to a font host on every page load — which is a privacy question for
   a client site, not only a speed one. It is offered as a heading face in
   Admin → Look; it is deliberately not the body face any more. See --font.

   Its @font-face rules are LINKED from each layout, not @imported here. An
   @import is found only after this file has arrived and been parsed, which
   makes it a second request in series before anything can be drawn. */

/* --------------------------------------------------------------------------
   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:        #faf7f0;
  --paper-raised: #fffdf8;
  --paper-sunk:   #f2eee4;
  --paper-edge:   #e6e0d2;
  --paper-line:   #ded7c6;

  /* Ink */
  --ink:          #24211c;
  --ink-soft:     #514a3f;
  --ink-muted:    #6a6355;   /* 5.6:1 on paper — readable, not just decorative */
  --ink-faint:    #736b5c;   /* 4.6:1 — the quietest text still has to be read */

  /* The organisation’s blue */
  --accent:       #0053c2;
  --accent-hover: #00429b;
  --accent-soft:  #e6eefc;
  --accent-ink:   #00306f;
  /* THE INK THAT SITS ON THE ACCENT, and it is not always white.
     A dark theme needs a lighter accent to lift off the page, and white text
     on a light blue is about 2.3:1 — a filled button nobody outside this room
     can read. So the ink flips with the theme: white on a dark fill, the page
     colour on a light one. Every filled button reaches for this rather than
     typing #fff, which is what let the dark theme ship unreadable. */
  --on-accent:    #ffffff;

  /* Supporting */
  --green:        #2c7a52;
  --green-soft:   #e3f1e9;
  --amber:        #a86a1a;
  --amber-soft:   #fbf0dd;
  --red:          #a83232;
  --red-soft:     #fbe7e5;

  /* THE KEYBOARD FOCUS RING — ink, not the accent.
     A ring has to reach 3:1 against what is behind it or a keyboard user
     cannot see where they are, and the accent is a colour each site chooses:
     a pale one fails outright. Ink measures about 15:1 on any page colour the
     contrast check will allow, and it is the one value that cannot be made
     wrong by a choice on the Look screen. */
  --focus:        var(--ink);

  /* THE BOUNDARY OF A CONTROL, and nothing else.
     WCAG 1.4.11 asks 3:1 of any visual boundary somebody needs to see in
     order to operate something. The hairline that separates a card is about
     1.2:1 on paper — decorative, and rightly so — but every text field and
     every radio was drawn in it too, which made them invisible rectangles to
     a low-vision visitor. This is for the things you have to aim at: inputs,
     textareas, selects, radios, checkboxes. IT IS NOT FOR CARDS — painting
     every hairline on the site this dark would wreck the look for no gain. */
  --edge-ctl:     #8b8577;

  /* Light greys. The paper palette is warm all the way through; the enquiry
     widget wants a cooler, quieter surface behind the conversation so the
     white bubbles sitting on it have something to lift off. */
  --grey-1:       #eeeef1;
  --grey-2:       #e2e2e6;
  --grey-3:       #cfcfd6;
  --grey-ink:     #6d6c70;

  /* 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 — tightened for Paper Air.
     Was 6/10/16, which is a lot of curve at small sizes. Big radii read
     friendly and consumer; tighter ones read precise, which is what a site
     somebody runs their organisation from wants. --radius is the one Admin →
     Look writes, and the others follow from it, so a site that chooses softer
     corners gets them everywhere at once rather than in patches.

     CONCENTRIC RADII: when one rounded thing sits inside another, the inner
     radius is the outer radius minus the gap between them. --r-in does that
     arithmetic; use it rather than guessing, or the two curves fight. */
  --radius-sm: 8px;
  --radius:    12px;
  --radius-lg: 16px;
  --radius-xl: 22px;
  --radius-pill: 999px;
  --r-in: calc(var(--radius-lg) - var(--space-3));

  --space-1: calc(.25rem * var(--density));  --space-2: calc(.5rem * var(--density));
  --space-3: calc(.75rem * var(--density));  --space-4: calc(1rem * var(--density));
  --space-5: calc(1.5rem * var(--density));  --space-6: calc(2rem * var(--density));
  --space-7: calc(3rem * var(--density));    --space-8: calc(4rem * var(--density));
  --space-9: calc(6rem * var(--density));

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

  /* THE BODY FACE, and why it is what it is.

     Apple-native first: a Mac and an iPhone draw this in San Francisco, which
     is the single change that makes an interface read as belonging on the
     machine rather than having been dropped onto it. SF Pro cannot legally be
     self-hosted, so the stack is how a Mac gets it natively.

     Then Inter, for anyone who has it. Then POPPINS, which this site already
     carries — deliberately ahead of Segoe UI, because a Windows visitor
     falling through to Segoe gets the one face on this list that was not
     chosen. Poppins is bundled, so that costs no request.

     Body text is not offered in Admin → Look on purpose: a site can be tried
     in a different heading voice without anybody being able to make it hard to
     read. */
  --font: -apple-system, BlinkMacSystemFont, 'Inter', 'Poppins', 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;

  /* HOW BOLD A BOLD IS.
     An inline <b> at 700 against body copy reads as shouting. 530 is
     unmistakably emphasis and stops there; 500 starts to disappear. --w-lab is
     a <b> being used as a small block label, which needs a little more to hold
     a line on its own. Use the tokens; do not type a number. */
  --w-em:  530;
  --w-lab: 600;

  /* THE TYPE SCALE. Seven steps and nothing below 13px.
     A stylesheet with twenty-five hand-typed font sizes is not a design, it is
     twenty-five decisions taken on twenty-five different days — and a wall of
     competing small text is what makes a page feel busy. If something wants a
     size that is not here, the honest fix is almost always the nearest step. */
  --fs-fine:  .8125rem;   /* legal, footnotes, timestamps — the floor       */
  --fs-sm:    .9rem;      /* nav, meta, captions, card sub-text             */
  --fs-lead:  clamp(1.08rem, 1rem + .34vw, 1.3rem);   /* intros, standfirsts */
  --fs-display: clamp(2.4rem, 1.8rem + 3vw, 3.4rem);  /* a price, a big stat */

  /* Headings have tokens of their own so one site can wear a different face
     without the body text moving. Admin → Look writes these; the stylesheet
     never needs editing for it. --heading-scale multiplies every heading size
     at once, so a face that runs small can be brought up in one number. */
  --heading-font:    var(--font);
  --heading-weight:  600;
  --heading-tracking: -.018em;
  --heading-scale:   1;

  /* THE AIR IN PAPER AIR: one number for how much room the page gets, and
     everything else multiplied by it. Air is the cheapest premium signal
     there is, and the clamps mean the extra room appears on a desktop and
     quietly goes away on a phone, where it would only mean more scrolling. */
  --density: 1;
  --sp-section: calc(clamp(64px, 7vw, 104px) * var(--density));
  --sp-block:   calc(clamp(28px, 3vw, 44px) * var(--density));
  --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;

  --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:        #171512;
  --paper-raised: #201d19;
  --paper-sunk:   #121110;
  --paper-edge:   #322d26;
  --paper-line:   #3d372e;

  --ink:          #f0ebe1;
  --ink-soft:     #ccc4b6;
  --ink-muted:    #a9a190;
  --ink-faint:    #968e7e;

  --accent:       #6aa5ff;
  --accent-hover: #8ebcff;
  --accent-soft:  #10203c;
  --accent-ink:   #b9d3ff;
  /* Ink on the accent, not white: #6aa5ff carries near-black at 8.9:1 and
     white at 2.3. See --on-accent above. */
  --on-accent:    #10131a;

  --green:        #6bbd8f;
  --green-soft:   #17281f;
  --amber:        #d9a24e;
  --amber-soft:   #2c2318;
  --red:          #e08a80;
  --red-soft:     #2e1c1a;

  --focus:        var(--ink);
  /* Lighter than its light-mode twin for the same reason: 3:1 against a dark
     field, not against a pale one. */
  --edge-ctl:     #7d776c;

  --grey-1:       #1c1a17;
  --grey-2:       #26231f;
  --grey-3:       #3a352d;
  --grey-ink:     #9a9287;

  --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. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --paper:        #171512;
    --paper-raised: #201d19;
    --paper-sunk:   #121110;
    --paper-edge:   #322d26;
    --paper-line:   #3d372e;
    --ink:          #f0ebe1;
    --ink-soft:     #ccc4b6;
    --ink-muted:    #a9a190;
    --ink-faint:    #968e7e;
    --accent:       #6aa5ff;
    --accent-hover: #8ebcff;
    --accent-soft:  #10203c;
    --accent-ink:   #b9d3ff;
    --on-accent:    #10131a;
    --green:        #6bbd8f;  --green-soft: #17281f;
    --amber:        #d9a24e;  --amber-soft: #2c2318;
    --red:          #e08a80;  --red-soft:   #2e1c1a;
    --focus:        var(--ink);
    --edge-ctl:     #7d776c;
    --grey-1: #1c1a17;  --grey-2: #26231f;  --grey-3: #3a352d;  --grey-ink: #9a9287;
    --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-family: var(--heading-font);
  font-weight: var(--heading-weight);
  line-height: 1.22;
  letter-spacing: var(--heading-tracking);
  color: var(--ink);
  text-wrap: balance;
}
/* A big heading wants tighter tracking and a tighter leading than a small one:
   at 3rem, 1.22 line-height opens a gap you can drive a bus through. These are
   the display sizes, so they get the display treatment. */
h1 { font-size: calc(clamp(2rem, 1.4rem + 2.6vw, 3.1rem) * var(--heading-scale)); font-weight: calc(var(--heading-weight) + 100); letter-spacing: calc(var(--heading-tracking) - .008em); line-height: 1.07; }
h2 { font-size: calc(clamp(1.6rem, 1.24rem + 1.6vw, 2.35rem) * var(--heading-scale)); letter-spacing: calc(var(--heading-tracking) - .004em); line-height: 1.12; }
h3 { font-size: calc(clamp(1.2rem, 1.08rem + .6vw, 1.5rem) * var(--heading-scale)); }
h4 { font-size: calc(1.1rem * var(--heading-scale)); }
h5, h6 { font-size: calc(1rem * var(--heading-scale)); }

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; }

/* Emphasis, not shouting. See --w-em. */
strong, b { font-weight: var(--w-em); }
small { font-size: var(--fs-fine); }

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: var(--on-accent); 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 that arrived with no size attribute is shown at its own size, up
   to the width of the column. Forcing 3/2 and cover did not reserve space
   usefully — the browser does that itself the moment the file's own
   dimensions arrive — it just cropped whatever was not landscape and blew
   small pictures up past their real size. max-width and height:auto come
   from the img rule near the top of this file. */
.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
   -------------------------------------------------------------------------- */
/* THE BUTTON. A capsule, 530 weight, and a press you can feel.

   ONE FILLED BUTTON PER SURFACE. .btn-primary is the thing somebody came to
   do; everything else on the screen is neutral and quiet. Two filled buttons
   beside each other is two answers to "what do I press", which is the same as
   none — and it spends the accent, which then means nothing anywhere else.

   Sentence case, always. Capitals belong to the action chips in .acts, never
   to a form submit: SAVE shouts and Save does not. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  padding: .7rem 1.35rem;
  font: inherit; font-weight: var(--w-em); font-size: .95rem; line-height: 1.2;
  letter-spacing: -.012em;
  border: 1px solid transparent; border-radius: var(--radius-pill);
  cursor: pointer; text-decoration: none; white-space: nowrap;
  transition: background .15s var(--ease), border-color .15s var(--ease),
              transform .12s var(--ease), box-shadow .15s var(--ease), opacity .14s var(--ease);
}
/* Tactile press. Scale rather than a nudge downwards: a button that moves down
   under the finger looks pressed; one that also shrinks feels pressed. */
.btn:active { transform: scale(.97); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .55; cursor: not-allowed; transform: none; }

/* The accent button takes its lift from a tinted shadow rather than a
   gradient: a gradient on a capsule this size reads as a button from 2014. */
.btn-primary { background: var(--accent); color: var(--on-accent);
  box-shadow: 0 2px 8px color-mix(in srgb, var(--accent) 16%, transparent),
              0 10px 30px -8px color-mix(in srgb, var(--accent) 16%, transparent); }
.btn-primary:hover { background: var(--accent-hover); color: var(--on-accent); }

.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); }

/* Ink on paper: the inverse of everything around it, which is what makes it
   the one thing on a pale band you can press without spending the accent. */
.btn-ink { background: var(--ink); color: var(--paper); }
.btn-ink:hover { background: var(--ink); color: var(--paper); opacity: .86; transform: translateY(-1px); }

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

.btn-whatsapp { background: #1f8a4c; color: #fff; }
.btn-whatsapp:hover { background: #1a7541; color: #fff; }

.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; }
/* For use on a photograph: glass rather than paper, so it belongs to the
   picture instead of sitting on top of it. */
.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);
}
.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);
  /* The boundary of a control, not a decorative hairline — see --edge-ctl.
     These are the things somebody has to aim at. */
  border: 1px solid var(--edge-ctl);
  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;
  /* Same reasoning as the fields: a tick box drawn in the card hairline is a
     box a low-vision visitor cannot find. */
  outline-color: var(--edge-ctl);
}
.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 the enquiry topics */
.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: var(--on-accent); }
.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: var(--on-accent); }
.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); }
/* A footer link is an icon and a label, so it should break as one thing. As
   plain inline the label wrapped to the next line and left the icon stranded
   on the line above — at 1024px, 768px and 480px on this site. The space in
   the markup between the two is a white-space-only text node, which a flex
   container drops, so the gap below is the only spacing. */
.site-footer a { color: var(--ink-soft); text-decoration: none;
  display: inline-flex; align-items: baseline; gap: .45em; }
.site-footer a svg { flex: none; align-self: center; }
.site-footer a:hover { color: var(--accent); }
/* Three things on one line: the organisation'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. Hero
   -------------------------------------------------------------------------- */
/* The banner itself is described in section 11, with the rest of the top of
   the site. What is left here is the two-column block the enquiry page uses,
   which shares the name but nothing else. */
.hero-grid { display: grid; gap: clamp(var(--space-5), 4vw, var(--space-7)); align-items: center; grid-template-columns: 1fr; }
@media (min-width: 900px) { .hero-grid { grid-template-columns: 1.05fr .95fr; } }

.banner-strip {
  background: var(--accent); color: var(--on-accent);
  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. The button set (rebuilt link manager)
   -------------------------------------------------------------------------- */
.link-groups { display: grid; gap: var(--space-6); }
.link-group-title {
  display: flex; align-items: center; gap: var(--space-3);
  font-size: 1.05rem; font-weight: 600; margin-bottom: var(--space-4);
  padding-left: var(--space-3); border-left: 4px solid var(--group-colour, var(--accent));
}
.link-row { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: var(--space-3); }
.link-button {
  display: flex; flex-direction: column; gap: .15rem;
  padding: var(--space-4);
  background: var(--paper-raised); color: var(--ink);
  border: 1px solid var(--paper-edge); border-top: 3px solid var(--group-colour, var(--accent));
  border-radius: var(--radius); text-decoration: none;
  box-shadow: var(--shadow-sm);
  transition: transform .18s var(--ease), box-shadow .18s var(--ease), border-color .18s var(--ease);
}
.link-button:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); color: var(--ink); }
.link-button .date { font-size: .8rem; font-weight: 600; color: var(--group-colour, var(--accent)); letter-spacing: .02em; }
.link-button .label { font-weight: 500; line-height: 1.35; color: inherit; margin: 0; }
.link-button .icon { margin-top: var(--space-2); color: var(--ink-faint); align-self: flex-end; }

/* --------------------------------------------------------------------------
   11. The enquiry widget — the rebuilt WhatsApp hero
   -------------------------------------------------------------------------- */
.enquiry {
  background: var(--paper-raised);
  border: 1px solid var(--paper-edge);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.enquiry-head {
  padding: var(--space-5);
  background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 70%, #1b4a5e));
  color: #fff;
}
.enquiry-head h2 { color: #fff; margin-bottom: var(--space-2); font-size: 1.35rem; }
.enquiry-head p { margin: 0; opacity: .92; font-size: .95rem; }
.enquiry-body { padding: var(--space-5); }

.enquiry-price {
  display: inline-flex; align-items: baseline; gap: .3rem;
  padding: .3rem .8rem; margin-bottom: var(--space-4);
  background: var(--green-soft); color: var(--green);
  border-radius: var(--radius-pill); font-weight: 600; font-size: .9rem;
}

.enquiry-step { display: none; }
.enquiry-step.is-active { display: block; animation: fade-up .35s var(--ease); }
@keyframes fade-up { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

.enquiry-progress { display: flex; gap: var(--space-2); margin-bottom: var(--space-5); }
.enquiry-progress i {
  flex: 1; height: 3px; border-radius: 2px; background: var(--paper-line); transition: background .3s var(--ease);
}
.enquiry-progress i.done { background: var(--accent); }

.enquiry-success { text-align: center; padding: var(--space-5) 0; }
.enquiry-success .tick {
  width: 56px; height: 56px; margin: 0 auto var(--space-4);
  border-radius: 50%; background: var(--green-soft); color: var(--green);
  display: grid; place-items: center;
}
/* The step that actually delivers the enquiry. It is given the weight of an
   instruction rather than of a spare link, because on a phone this tap is
   what puts the message in the organisation's inbox. */
.enquiry-send {
  margin: var(--space-5) 0 var(--space-4);
  padding: var(--space-4);
  background: var(--paper-sunk);
  border-radius: var(--radius);
}
.enquiry-send-label {
  margin: 0 0 var(--space-3);
  font-size: .78rem; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-faint);
}
.enquiry-wa-btn { display: inline-flex; align-items: center; gap: .5rem; }
@media (max-width: 520px) { .enquiry-wa-btn { display: flex; width: 100%; justify-content: center; } }
.enquiry-send-note {
  margin: var(--space-3) 0 0; font-size: .88rem; line-height: 1.5; color: var(--ink-soft);
}
.enquiry-blocked {
  display: flex; align-items: flex-start; gap: .45rem;
  margin: var(--space-3) 0 0; padding: var(--space-3);
  background: var(--paper); border-radius: var(--radius-sm);
  font-size: .86rem; line-height: 1.5; text-align: left; color: var(--ink-soft);
}
.enquiry-blocked .icon { flex: none; margin-top: 2px; color: var(--amber); }
/* Only when the browser blocked the tab: a slow, quiet ring, so the eye goes
   to the button without the page starting to flash at anybody. */
.enquiry-wa-btn.is-waiting { animation: wa-waiting 2.4s ease-in-out 3; }
@keyframes wa-waiting {
  0%, 100% { box-shadow: 0 0 0 0 rgba(31, 138, 76, 0); }
  50%      { box-shadow: 0 0 0 6px rgba(31, 138, 76, .18); }
}
@media (prefers-reduced-motion: reduce) { .enquiry-wa-btn.is-waiting { animation: none; } }

.enquiry-ref {
  display: inline-block; margin-top: var(--space-3);
  padding: .35rem .8rem; background: var(--paper-sunk);
  border-radius: var(--radius-sm); font-family: var(--font-mono); font-size: .9rem;
}

/* --------------------------------------------------------------------------
   12. Post and policy 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); }

.policy-group { margin-bottom: var(--space-6); }
.policy-item {
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-4);
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  border-radius: var(--radius); margin-bottom: var(--space-2);
  text-decoration: none; color: var(--ink);
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.policy-item:hover { border-color: var(--accent); box-shadow: var(--shadow); color: var(--ink); }
.policy-item .icon { color: var(--accent); flex: none; }
.policy-item .title { font-weight: 500; }
.policy-item .meta { margin-left: auto; font-size: .8rem; color: var(--ink-muted); white-space: nowrap; }

/* --------------------------------------------------------------------------
   13. 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: var(--on-accent); 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); }
}

/* --------------------------------------------------------------------------
   14. 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; }
}

/* --------------------------------------------------------------------------
   15. Print — it is paper, after all
   -------------------------------------------------------------------------- */
@media print {
  .site-header, .site-footer, .theme-toggle, .nav-toggle, .pagination, .enquiry, .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; }
}

/* ==========================================================================
   16. The organisation site proper — a Paper reading of the layout the organisation already
       has: a photographic banner with the crest on it, the menu underneath,
       the blog down the right, the coloured button groups, then the policies.
   ========================================================================== */

/* ---------- banner ---------- */
/* ---------- sections arriving as you reach them ---------- */
/* Eight pixels and a fade. Anything more and a page of ordinary organisation news
   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 ---------- */
/*
 * One photograph, one thing to do. The home page gives it room; every other
 * page gets a slim band of the same picture, because those pages arrive with
 * their own heading and a visitor who is already inside does not need selling
 * to a second time.
 */
.site-head { position: relative; }
.hero {
  position: relative;
  min-height: clamp(140px, 17vw, 220px);
  display: grid; align-items: end;
  background: var(--paper-sunk) center/cover no-repeat;
  overflow: hidden;
}
/* The banner photograph. A background cannot carry a srcset, so the choice is
   made here from the properties the page hands down: the original for anything
   that cannot read WebP, the large copy on a wide screen, the small one on a
   phone — which was otherwise downloading a 1600-pixel photograph to fill a
   strip 220 pixels tall. */
.hero { background-image: var(--banner); }
@supports (background-image: image-set(url("i.webp") type("image/webp"))) {
  .hero { background-image: image-set(var(--banner-lg, var(--banner)) type("image/webp")); }
  @media (max-width: 700px) {
    .hero { background-image: image-set(var(--banner-sm, var(--banner-lg, var(--banner))) type("image/webp")); }
  }
}
.site-head.is-home .hero {
  min-height: clamp(340px, 42vw, 560px);
}
/* The scrim: dark at the foot where the words sit, clearing towards the top
   so the photograph is still a photograph. */
.hero::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  /* Two washes: one down the picture, one in from the left where the words
     are. Either alone leaves a bright picture somewhere behind a sentence. */
  background:
    linear-gradient(to right, rgba(12, 18, 24, .74) 0%, rgba(12, 18, 24, .52) 34%, rgba(12, 18, 24, .12) 62%, rgba(12, 18, 24, 0) 80%),
    linear-gradient(to bottom, rgba(12, 18, 24, .30) 0%, rgba(12, 18, 24, .04) 30%, rgba(12, 18, 24, .48) 100%);
}
.site-head:not(.is-home) .hero::after {
  background: linear-gradient(to bottom, rgba(14, 20, 26, .30) 0%, rgba(14, 20, 26, .45) 100%);
}
.hero-inner {
  position: relative; z-index: 1;
  padding: clamp(var(--space-6), 6vw, var(--space-8)) var(--space-5);
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-3);
  color: #fff;
}
.hero-crest { display: block; margin-bottom: var(--space-2); }
.hero-crest img {
  width: clamp(84px, 9vw, 116px); height: auto;
  filter: drop-shadow(0 4px 14px rgba(0, 0, 0, .45));
}
.hero-title {
  margin: 0; color: #fff; max-width: 18ch; text-wrap: balance;
  font-size: clamp(2rem, 4.6vw, 3.4rem); line-height: 1.04; letter-spacing: -.025em;
  text-shadow: 0 2px 20px rgba(0, 0, 0, .45);
}
.hero-sub {
  margin: 0; max-width: 44ch; color: rgba(255, 255, 255, .96);
  font-size: clamp(1rem, 1.5vw, 1.2rem); line-height: 1.45; font-weight: 500;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .5), 0 2px 18px rgba(0, 0, 0, .55);
}
.hero-do { display: flex; flex-wrap: wrap; gap: var(--space-3); margin: var(--space-3) 0 0; }

/* ---------- menu bar, sitting under the banner ---------- */
/* ---------- the bar under the picture, 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);
}
.site-head.is-stuck .menubar { box-shadow: 0 6px 20px rgba(60, 48, 30, .10); }
.menubar .container { display: flex; align-items: center; gap: var(--space-3); min-height: 60px; }
/* The crest in the bar. On the home page it waits until the hero has gone
   by; everywhere else it is simply there. */
.bar-crest { display: flex; align-items: center; flex: 0 0 auto; text-decoration: none; color: var(--ink); font-weight: 600; }
/* The organisation's mark is white line art with nothing behind it, which vanishes on
   a pale bar. It gets its own disc of organisation blue 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 organisation'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; } }

.site-head.is-home .bar-crest {
  opacity: 0; transform: translateY(-4px); pointer-events: none;
  transition: opacity .22s var(--ease), transform .22s var(--ease);
}
.site-head.is-home.is-stuck .bar-crest { opacity: 1; transform: none; pointer-events: auto; }
.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; } }
/* The films and pictures on the home page, two across rather than three so
   each one is big enough to see. One per row once there is no room for two. */
.media-grid { display: grid; grid-template-columns: 1fr; gap: clamp(var(--space-4), 3vw, var(--space-6)); }
@media (min-width: 760px) { .media-grid { grid-template-columns: 1fr 1fr; } }

/* An item is the tile and, under it, whatever was written about it. The
   wording sits below rather than over the picture: text laid over a photograph
   is legible until somebody uploads a pale one, and then it is not. */
.media-item { margin: 0; display: flex; flex-direction: column; gap: var(--space-3); }
.media-caption { font-size: .92rem; color: var(--ink-soft); }
.media-caption p { margin: 0 0 var(--space-3); }
.media-caption p:last-child { margin-bottom: 0; }
.media-caption .btn { margin-top: var(--space-1); }

/* 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. */
.media-tile {
  position: relative; display: block; width: 100%; padding: 0;
  aspect-ratio: 16 / 9; border: 0; border-radius: var(--radius); overflow: hidden;
  /* With a still it shows the still; without one, the site's own accent
     rather than a grey rectangle — so no thumbnail still looks deliberate. */
  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);
}
button.media-tile { cursor: pointer; }
.media-tile::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(to bottom, rgba(12, 18, 24, .10) 0%, rgba(12, 18, 24, .55) 100%);
}
/* A picture with nothing written across it needs no scrim: it is only there so
   white lettering stays readable. */
.media-tile.is-picture:not(:has(.media-name))::after { background: none; }
button.media-tile:hover, button.media-tile:focus-visible { transform: translateY(-2px); box-shadow: var(--shadow-lg); }
button.media-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.media-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);
}
button.media-tile:hover .media-play { transform: scale(1.07); background: #fff; }
.media-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) {
  .media-tile, .media-tile:hover, .media-play, .media-tile:hover .media-play { transform: none; }
}
/* The affiliation badges, under the enquiry form and in the same column. The
   strip is one wide image (1581px across), so it is stretched to the width of
   the column rather than sitting at whatever size it happens to be. */
.awards-strip { margin-top: var(--space-5); }
.awards-strip p { margin: 0; }
.awards-strip img { display: block; width: 100%; max-width: 100%; height: auto; border-radius: var(--radius); }
/* A badge strip that came across without its size on it still holds its own
   height, so the writing underneath does not jump when the picture lands. */
.awards-strip img:not([width]) { aspect-ratio: 8 / 1; object-fit: contain; }
.awards-strip + .prose { margin-top: var(--space-6); }

/* ---------- the buttons and the organisation videos, side by side ---------- */
/* Neither of these two needs the whole page to itself, and both looked
   oversized with it. They share the width on a wide screen and stack, buttons
   first, once there is no longer room for the pair. */
.home-duo { display: grid; gap: clamp(var(--space-5), 4vw, var(--space-7)); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 1200px) {
  /* Three fifths to the buttons, two to the clips: the buttons are the part
     people come to press, and they are the part that needs the room. */
  .home-duo:not(.is-single) { grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); }
  /* Half the width fits fewer buttons across, so the minimum comes down to
     keep each one the size it is elsewhere rather than stretching two of them
     across the column. */
  .home-duo:not(.is-single) .btn-grid { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
  /* The clips stay two across in the column. Each one is a preview that goes
     full screen when it is played, so a pair that keeps the column beside the
     buttons rather than running far past them is the better trade. */
  .home-duo:not(.is-single) .media-grid { grid-template-columns: 1fr 1fr; }
}
.duo-part { min-width: 0; }
.duo-part > :first-child { margin-top: 0; }
.duo-part .btn-group:last-child { margin-bottom: 0; }
.duo-part .band-intro h2, .duo-part > h2 { margin-top: 0; }

.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); }

/* ---------- coloured button groups (the link manager, rebuilt) ---------- */
.btn-group { margin-bottom: var(--space-6); }
.btn-group-title {
  display: flex; align-items: center; gap: var(--space-3);
  font-size: 1.02rem; font-weight: 600; margin-bottom: var(--space-3);
  padding-left: var(--space-3); border-left: 4px solid var(--group-colour, var(--accent));
}
.btn-group-title .count { font-size: .78rem; font-weight: 500; color: var(--ink-muted); }
.btn-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(228px, 1fr)); gap: var(--space-3); }
/* The organisation's buttons.
   Flat colour reads as a coloured box; a little depth reads as something to
   press. The sheen is a hairline of light along the top edge and a whisper of
   shade at the foot — the same trick a printed button uses — and the shadow
   is tinted with the group's own colour rather than grey, so a red row casts
   a warm shadow and a blue one a cool shadow. It lifts a couple of pixels
   under the cursor and sits back down when pressed. Nothing moves far. */
.organisation-btn {
  display: flex; flex-direction: column; gap: .2rem;
  padding: var(--space-4);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .10), rgba(255, 255, 255, 0) 42%, rgba(0, 0, 0, .07)),
    var(--group-colour, var(--accent));
  color: var(--group-ink, #fff);
  /* No drawn edge — a dark outline round a coloured button is the oldest tell
     in web design. The shape comes from the colour, the sheen and the shadow.
     The border stays as transparent so the box measures the same as before. */
  border: 1px solid transparent;
  border-radius: 8px;
  text-decoration: none; text-align: center;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .16),
    0 1px 2px color-mix(in srgb, var(--group-colour, var(--accent)) 30%, transparent),
    0 3px 8px color-mix(in srgb, var(--group-colour, var(--accent)) 18%, transparent);
  transition: transform .18s var(--ease), box-shadow .18s var(--ease), filter .18s var(--ease);
  will-change: transform;
}
.organisation-btn:hover {
  transform: translateY(-2px);
  filter: brightness(1.04) saturate(1.02);
  color: var(--group-ink, #fff);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .20),
    0 2px 4px color-mix(in srgb, var(--group-colour, var(--accent)) 30%, transparent),
    0 10px 20px color-mix(in srgb, var(--group-colour, var(--accent)) 24%, transparent);
}
/* Pressed: back down onto the page, with the light gone from the top edge. */
.organisation-btn:active {
  transform: translateY(0) scale(.995);
  transition-duration: .06s;
  box-shadow:
    inset 0 2px 4px rgba(0, 0, 0, .16),
    0 1px 2px color-mix(in srgb, var(--group-colour, var(--accent)) 30%, transparent);
}
.organisation-btn:focus-visible {
  outline: 2px solid var(--group-colour, var(--accent));
  outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
  .organisation-btn, .organisation-btn:hover, .organisation-btn:active { transform: none; transition: box-shadow .18s var(--ease); }
}
/* The generic form `.label` sets a colour and a margin. A button's label
   carries the same class name, so both are restated here — otherwise the
   wording on a coloured button takes the form label's grey and is close to
   unreadable on the darker groups. */
.organisation-btn .label { font-weight: 700; line-height: 1.3; font-size: .97rem; color: inherit; margin: 0; }
.organisation-btn .desc { font-size: .8rem; opacity: .85; line-height: 1.35; color: inherit; margin: 0; }
/* A pale button needs a visible edge rather than a shadow alone, and its
   sheen has to come from shade rather than light or it disappears. */
/* A pale button has nothing to lift off the paper, so it gets the faintest
   ring of its own colour rather than a dark line — enough to hold its shape
   against a light background, not enough to read as an outline. */
.organisation-btn.is-pale {
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .26), rgba(255, 255, 255, 0) 48%, rgba(0, 0, 0, .09)),
    var(--group-colour, var(--accent));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .40),
    0 1px 2px color-mix(in srgb, var(--group-colour, var(--accent)) 50%, transparent),
    0 4px 10px color-mix(in srgb, var(--group-colour, var(--accent)) 32%, transparent);
}
.organisation-btn.is-pale:hover {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .44),
    0 2px 4px color-mix(in srgb, var(--group-colour, var(--accent)) 50%, transparent),
    0 10px 22px color-mix(in srgb, var(--group-colour, var(--accent)) 36%, transparent);
}

/* ---------- the policy grid ---------- */
.policy-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--space-4); }
.policy-col {
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  border-radius: var(--radius-lg); overflow: hidden; display: flex; flex-direction: column;
}
.policy-col-head {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-4); border-bottom: 1px solid var(--paper-edge);
  background: var(--paper-sunk);
}
.policy-col-head h3 { margin: 0; font-size: .98rem; }
.policy-col-head .count {
  margin-left: auto; min-width: 1.5rem; padding: 0 .4rem;
  background: var(--accent-soft); color: var(--accent-ink);
  border-radius: var(--radius-pill); font-size: .76rem; font-weight: 700; text-align: center; line-height: 1.5rem;
}
.policy-col-body { padding: var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); flex: 1; }
.policy-doc {
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: var(--space-3); border: 1px solid var(--paper-edge); border-radius: var(--radius);
  text-decoration: none; color: var(--ink); font-size: .9rem; line-height: 1.35;
  transition: border-color .15s var(--ease), background .15s var(--ease);
}
.policy-doc:hover { border-color: var(--accent); background: var(--paper-sunk); color: var(--ink); }
.policy-doc .icon { flex: none; color: var(--red); margin-top: .1rem; }
.policy-doc.is-link .icon { color: var(--accent); }
.policy-doc .lock { margin-left: auto; flex: none; color: var(--ink-faint); }
.policy-doc.is-locked { opacity: .82; }

/* ---------- the enquiry widget, in the shape the organisation knows ---------- */
.enquiry-wrap {
  background: var(--paper-raised);
  border: 1px solid var(--paper-edge);
  border-radius: var(--radius-lg); overflow: hidden;
  box-shadow: var(--shadow-lg), 0 0 0 1px color-mix(in srgb, var(--accent) 8%, transparent);
}

/* THE INVITATION STRIP. Rebuilt for Paper Air, and it needed rebuilding twice
   over.

   It was a three-stop gradient in three literal blues — #0046a6, #0a63d8,
   #2f83ee — typed into the stylesheet. Two things wrong with that on a
   starter. The first is plain: a site that chose green on the Look screen got
   a blue strip on its home page and no way to change it, which is exactly the
   thing this starter says it does not do. The second is Paper Air's fourth
   commandment — colour means something, one filled thing per surface, and a
   tone lives in a dot rather than a painted box. A painted block of accent
   with an accent button inside it spends the colour twice and says nothing
   with either.

   So: a quiet band, ink on paper, and ONE accent button — which is the thing
   somebody came to press. It is the same material as every other quiet
   surface on the site, which is what makes the button on it unmissable. */
.enquiry-cta {
  position: relative;
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4);
  padding: var(--space-5);
  background: var(--paper-sunk);
  color: var(--ink);
  border-bottom: 1px solid var(--paper-edge);
}
/* One bloom, near-white at the top, so the band reads as lit from above
   rather than tinted. Percentages, so it scales with the band. */
.enquiry-cta::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(110% 80% at 22% -10%,
              color-mix(in srgb, var(--paper-raised) 85%, transparent), transparent 68%);
}
.enquiry-cta > * { position: relative; }
.enquiry-said { flex: 1; min-width: 15rem; }
.enquiry-cta p { margin: 0; }
.enquiry-headline {
  font-family: var(--heading-font);
  font-weight: var(--heading-weight);
  font-size: clamp(1.06rem, 1.7vw, 1.28rem); line-height: 1.2;
  letter-spacing: var(--heading-tracking);
}
/* Not .enquiry-price — that name is already the green pill on the enquiry page. */
.cta-price {
  margin-top: .3rem !important; font-size: var(--fs-sm); font-weight: 500; color: var(--ink-muted);
}

.enquiry-status {
  display: flex; align-items: center; justify-content: center; gap: var(--space-2);
  padding: var(--space-3); font-size: .86rem; color: var(--grey-ink);
  background: var(--grey-1); border-bottom: 1px solid var(--paper-edge);
}
.enquiry-status strong { color: var(--ink-soft); }
.enquiry-status .dot {
  width: 9px; height: 9px; border-radius: 50%; background: var(--green);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--green) 22%, transparent);
  animation: pulse-dot 2.4s var(--ease) infinite;
}
@keyframes pulse-dot {
  0%, 100% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--green) 22%, transparent); }
  50%      { box-shadow: 0 0 0 6px color-mix(in srgb, var(--green) 8%, transparent); }
}

.enquiry-cols { display: grid; grid-template-columns: 1fr; }
@media (min-width: 820px) { .enquiry-cols { grid-template-columns: 1.05fr .95fr; } }
/* Everything on the right of the widget — the dates, then the quick topics —
   is one column, so the grid beside the conversation stays two wide however
   many panels end up in it. */
.side-col { display: flex; flex-direction: column; min-width: 0; }
.side-col > .topics + .topics { padding-top: 0; }
.side-col > .next-dates { border-bottom: 1px solid var(--paper-edge); }

/* ---------- the conversation, with its own scroll arrows ---------- */
.chat-pane {
  position: relative;
  background: var(--grey-1);
  border-bottom: 1px solid var(--paper-edge);
  /* The column beside it decides how tall this row is, and how tall that
     column is depends on how many dates are listed. The conversation fills
     whatever height it is given rather than stopping short of it. */
  display: flex; flex-direction: column; min-height: 0;
}
@media (min-width: 820px) { .chat-pane { border-bottom: 0; border-right: 1px solid var(--paper-edge); } }

/* Paper fading in at the top and bottom of the scroll, so a part-scrolled
   conversation looks cut off rather than simply ending. */
.chat-pane::before, .chat-pane::after {
  content: ''; position: absolute; left: 0; right: 0; height: 28px;
  pointer-events: none; z-index: 2; opacity: 0; transition: opacity .2s var(--ease);
}
.chat-pane::before { top: 0; background: linear-gradient(to bottom, var(--grey-1), transparent); }
.chat-pane::after { bottom: 0; background: linear-gradient(to top, var(--grey-1), transparent); }
.chat-pane[data-at-top="0"]::before,
.chat-pane[data-at-end="0"]::after { opacity: 1; }

.chat {
  display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-5) var(--space-5) var(--space-5) var(--space-4);
  flex: 1 1 auto; min-height: 0;
  max-height: 360px; overflow-y: auto; scroll-behavior: smooth;
  overscroll-behavior: contain;
  scrollbar-width: thin; scrollbar-color: var(--grey-3) transparent;
}
/* Side by side, the row is as tall as the taller column and the cap comes off:
   the conversation shows as much of itself as there is room for, rather than
   stopping at 360px and leaving the rest of the column blank. Stacked, the cap
   stays — there the conversation would otherwise run the length of the page. */
@media (min-width: 820px) { .chat { max-height: none; } }

.chat::-webkit-scrollbar { width: 6px; }
.chat::-webkit-scrollbar-track { background: transparent; }
.chat::-webkit-scrollbar-thumb { background: var(--grey-3); border-radius: var(--radius-pill); }
.chat:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }

.chat-arrows {
  position: absolute; right: var(--space-3); bottom: var(--space-3); z-index: 3;
  display: flex; flex-direction: column; gap: 6px;
}
.chat-arrow {
  width: 30px; height: 30px; display: grid; place-items: center;
  border-radius: 50%; cursor: pointer;
  background: var(--paper-raised); border: 1px solid var(--grey-3);
  color: var(--grey-ink); box-shadow: var(--shadow-sm);
  transition: background .15s var(--ease), color .15s var(--ease),
              border-color .15s var(--ease), opacity .15s var(--ease);
}
.chat-arrow:hover:not(:disabled) { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.chat-arrow:active:not(:disabled) { transform: scale(.92); }
.chat-arrow:disabled { opacity: .3; cursor: default; }
/* The arrows are driven by script, and are pointless when the conversation
   fits, so they appear only once it is known there is something to scroll. */
.chat-arrows { display: none; }
.chat-pane[data-scrollable="1"] .chat-arrows { display: flex; }

.bubble {
  display: flex; gap: var(--space-3); align-items: flex-start;
  align-self: flex-start; max-width: 94%;
  animation: bubble-in .4s var(--ease) both;
}
.bubble .who {
  flex: none; width: 28px; height: 28px; margin-top: 2px;
  display: grid; place-items: center; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
}
.bubble .said {
  padding: var(--space-3) var(--space-4);
  background: var(--paper-raised); border: 1px solid var(--grey-2);
  border-radius: 4px var(--radius-lg) var(--radius-lg) var(--radius-lg);
  font-size: .92rem; line-height: 1.55; color: var(--ink-soft);
  box-shadow: var(--shadow-sm);
}
.bubble .said strong { color: var(--ink); }
.bubble .when { display: block; margin-top: .35rem; font-size: .7rem; color: var(--ink-faint); text-align: right; }
@keyframes bubble-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.bubble:nth-child(2) { animation-delay: .25s; }
.bubble:nth-child(3) { animation-delay: .5s; }
.bubble:nth-child(4) { animation-delay: .75s; }

/* ---------- the quick topics, on the right ---------- */
.topics { padding: var(--space-5) var(--space-4); }
.topics h3 {
  display: flex; align-items: center; gap: .4rem;
  font-size: .74rem; letter-spacing: .11em; text-transform: uppercase;
  color: var(--ink-muted); margin-bottom: var(--space-2);
}
.topics > p { font-size: .85rem; color: var(--ink-muted); margin-bottom: var(--space-4); }
.topic-list { display: flex; flex-direction: column; gap: var(--space-2); }
/* ---------- when the next sessions are ---------- */
/* Two places show the same list: a tickable version in the widget's right-hand
   column, and a fuller one on the enquiry page. They share the wording classes
   so a change to one does not quietly leave the other behind. */
.next-dates .topic-list { gap: var(--space-2); }
/* Written to out-rank .topic, which is a single pill-shaped line and sits
   later in this file — these rows are three lines tall and need square-ish
   corners and a tick that lines up with the first of them. */
.topic.date-topic { align-items: flex-start; border-radius: var(--radius); padding: .65rem .9rem; }
.topic.date-topic .box { margin-top: 1px; }
.date-said { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.date-when { font-weight: 600; display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.date-where { font-size: .84rem; color: var(--ink-muted); font-weight: 400; }
.date-note  { font-size: .82rem; color: var(--ink-muted); font-weight: 400; }
.date-soon {
  font-size: .68rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  background: var(--accent-soft); color: var(--accent-ink);
  padding: .12rem .45rem; border-radius: var(--radius-pill);
}
.date-soon.is-full { background: var(--grey-2); color: var(--ink-muted); }
.topic.is-full { opacity: .62; cursor: default; }
.topic.is-full:hover, .topic.is-full:focus-within { transform: none; border-color: var(--grey-2); background: var(--grey-1); }

/* The list on the enquiry page, where there is room to set it out properly. */
.date-list { margin-top: var(--space-6); }
.date-list h2 { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-3); }
.date-intro { color: var(--ink-muted); max-width: 52ch; margin-bottom: var(--space-4); }
.dates { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-3); }
.dates .date {
  display: flex; align-items: flex-start; gap: var(--space-4);
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  border-radius: var(--radius-lg); padding: var(--space-4);
  box-shadow: var(--shadow-sm);
}
.dates .date.is-full { opacity: .7; }
.date-box {
  flex: none; width: 54px; text-align: center; line-height: 1.05;
  background: var(--accent); color: var(--on-accent); border-radius: var(--radius);
  padding: .45rem 0 .5rem;
}
.date-day { display: block; font-size: 1.5rem; font-weight: 700; }
.date-month { display: block; font-size: .7rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; opacity: .9; }
.date-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.date-head { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }

.topic {
  display: flex; align-items: center; gap: var(--space-3);
  padding: .7rem 1rem; cursor: pointer;
  background: var(--grey-1); border: 1px solid var(--grey-2);
  border-radius: var(--radius-pill); font-size: .93rem; font-weight: 500;
  transition: background .15s var(--ease), border-color .15s var(--ease),
              color .15s var(--ease), transform .1s var(--ease); user-select: none;
}
.topic:hover { border-color: var(--accent); background: var(--paper-raised); transform: translateX(2px); }
.topic input { position: absolute; opacity: 0; width: 0; height: 0; }
.topic .box {
  flex: none; width: 20px; height: 20px; border-radius: 5px;
  border: 2px solid var(--grey-3); display: grid; place-items: center;
  transition: all .15s var(--ease);
}
.topic .box .icon { opacity: 0; color: #fff; }
.topic:has(input:checked) { background: var(--accent); border-color: var(--accent); color: var(--on-accent); transform: none; }
.topic:has(input:checked) .box { background: #fff; border-color: #fff; }
.topic:has(input:checked) .box .icon { opacity: 1; color: var(--accent); }
.topic:has(input:focus-visible) { outline: 2px solid var(--focus); outline-offset: 2px; }
.topic:has(input:disabled) { opacity: .5; cursor: not-allowed; }

.enquiry-entry { padding: var(--space-5) var(--space-4); border-top: 1px solid var(--paper-edge); background: var(--grey-1); }
.name-gate {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3);
  padding: var(--space-3); margin-bottom: var(--space-3);
  border: 2px solid var(--amber); border-radius: var(--radius); background: var(--amber-soft);
}
.name-gate label { font-weight: 600; font-size: .9rem; color: var(--ink); white-space: nowrap; margin: 0; }
.name-gate input { flex: 1; min-width: 9rem; }
.name-gate.is-done { border-color: var(--green); background: var(--green-soft); }
.name-hint { font-size: .82rem; color: var(--amber); margin: 0 0 var(--space-3); }

.say { display: flex; gap: var(--space-2); align-items: center; transition: opacity .15s var(--ease); }
/* Waiting on a name. Dimmed on purpose, so a box that will not take a word
   looks like one, rather than looking broken. */
.say.is-waiting { opacity: .55; }
.say.is-waiting input, .say.is-waiting .send { cursor: not-allowed; }
.say input { flex: 1; border-radius: var(--radius-pill); }
/* WhatsApp's own green, and one of the two places in this stylesheet where a
   literal colour is right: it is somebody else's brand, people recognise it,
   and repainting it in the site's accent would make the one button on the page
   whose colour is already understood look like something else. See also
   .btn-whatsapp. */
.send {
  flex: none; width: 44px; height: 44px; border-radius: 50%; border: 0;
  background: #1f8a4c; color: #fff; display: grid; place-items: center; cursor: pointer;
  transition: background .15s var(--ease), transform .1s var(--ease);
}
.send:hover { background: #1a7541; }
.send:active { transform: scale(.94); }
.send:disabled { opacity: .5; cursor: not-allowed; }

.enquiry-alt { padding: var(--space-4); text-align: center; font-size: .88rem; color: var(--grey-ink); background: var(--paper-raised); border-top: 1px solid var(--paper-edge); }
.enquiry-wa-note {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4); background: var(--green-soft); color: var(--green);
  font-size: .88rem; border-top: 1px solid var(--paper-edge);
}
.enquiry-wa-note span:first-of-type { flex: 1; min-width: 14rem; }
.enquiry-wa-note .wa-get { display: flex; gap: var(--space-2); margin-left: auto; }

/* ---------- 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; }

/* ---------- partner logos ---------- */
/* ---------- partners and sponsors, along the foot of every page ---------- */
/* 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; }

/* ---------- the organisation's people: leaders, team ---------- */
/* 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;
  /* Square, because every headshot the organisation uploads is square — 282x282 and
     up. A 4/3 frame cut a quarter off the top and bottom of each face. The
     ratio is kept rather than dropped so the cards stay a uniform height,
     and cover with the position below only comes into play if somebody ever
     uploads a landscape photo. */
  aspect-ratio: 1 / 1; 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); }

/* ---------- partners and sponsors, on their own page ---------- */
/* The footer keeps its quiet strip; this is the same list with room to
   breathe. Every logo sits in a box of the same height with the name under
   it, so a wide banner and a square badge line up as a grid rather than
   stepping up and down the page. */
/* A page whose wording introduces a grid keeps the wording at a readable
   width but lets the grid have the whole column — otherwise nine logos sit in
   a narrow strip with half the page empty beside them. */
.prose:has(.partner-cards) { max-width: none; }
.prose:has(.partner-cards) > p { max-width: var(--measure); }
.partner-cards {
  list-style: none; margin: var(--space-6) 0; padding: 0;
  display: grid; gap: var(--space-4);
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
}
.partner-card {
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
  transition: transform .16s var(--ease), box-shadow .16s var(--ease);
}
.partner-card a { display: block; text-decoration: none; color: inherit; height: 100%; }
.partner-card:has(a):hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }
/* The logo box. Its height is set per card from the shape of the logo in it:
   a round crest at the same height as a wordmark reads as far bigger, because
   the wordmark is a thin band of ink and the crest is a solid block of it. */
.partner-logo {
  display: flex; align-items: center; justify-content: center;
  height: 120px; padding: var(--space-5) var(--space-5) var(--space-3);
}
.partner-logo img {
  max-width: 100%; max-height: var(--logo-h, 100%);
  width: auto; height: auto; object-fit: contain;
}
.partner-name {
  display: block; padding: 0 var(--space-4) var(--space-4);
  text-align: center; font-size: .85rem; font-weight: 600; color: var(--ink-soft);
}

.partners-strip { margin-top: var(--space-6); padding-top: var(--space-5); border-top: 1px solid var(--paper-edge); }
.partners-title {
  margin: 0 0 var(--space-4); text-align: center;
  font-size: .72rem; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-faint);
}
.partners {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: clamp(var(--space-4), 3.5vw, var(--space-6));
}
.partners li { display: flex; }
.partners a { display: flex; }
.partners img {
  max-height: var(--logo-h, 46px); max-width: 150px; width: auto; object-fit: contain; border-radius: 0;
  /* The logos arrive in a dozen different colourways. Draining most of the
     colour out settles them into one quiet row, and the full colour comes
     back on hover so a sponsor is never permanently greyed out. */
  filter: grayscale(1); opacity: .6;
  transition: filter .2s var(--ease), opacity .2s var(--ease);
}
.partners img:hover, .partners a:focus-visible img { filter: none; opacity: 1; }
:root[data-theme="dark"] .partners img { filter: grayscale(1) brightness(1.6); opacity: .55; }
:root[data-theme="dark"] .partners img:hover { filter: brightness(1.05); opacity: 1; }
@media (max-width: 640px) { .partners img { max-height: calc(var(--logo-h, 46px) * .74); } }

/* ---------- what's on ---------- */
/* A date and what happens on it, side by side where there is room and stacked
   where there is not. The date column is fixed so the titles line up. */
.event-list { list-style: none; padding: 0; margin: 0; }
.event-row {
  display: flex; flex-wrap: wrap; gap: var(--space-4);
  padding: var(--space-5) 0; border-top: 1px solid var(--paper-line);
}
.event-row:last-child { border-bottom: 1px solid var(--paper-line); }
.event-when { flex: 0 0 11rem; display: flex; flex-direction: column; gap: .15rem; }
.event-what { flex: 1 1 16rem; min-width: 0; }
.event-what h2 { font-size: 1.1rem; margin: 0 0 var(--space-2); }
.event-what p { margin: 0 0 var(--space-2); }
.event-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3);
  font-size: .88rem; color: var(--ink-muted); }
.event-meta span { display: inline-flex; align-items: center; gap: .35em; }

/* ---------------------------------------------------------------------------
   The member area: the list of lessons, and one lesson.

   A locked lesson is shown rather than hidden, so the list has two states and
   both have to look deliberate — the locked one dimmed and unclickable, not
   broken. The number down the left is what makes it read as a course.
   --------------------------------------------------------------------------- */
.member-head { margin-bottom: var(--space-6); }
.member-head h1 { margin-bottom: var(--space-2); }
.member-foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3);
  margin-top: var(--space-7); padding-top: var(--space-5);
  border-top: 1px solid var(--paper-line);
}

.lesson-list { list-style: none; padding: 0; margin: 0; counter-reset: lesson; }
.lesson-row {
  display: flex; gap: var(--space-4); align-items: flex-start;
  padding: var(--space-5) 0; border-top: 1px solid var(--paper-line);
}
.lesson-row:last-child { border-bottom: 1px solid var(--paper-line); }
.lesson-num {
  flex: 0 0 2.25rem; height: 2.25rem;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%; background: var(--paper-sunk); color: var(--ink-muted);
  font-size: .9rem; font-weight: 600; font-variant-numeric: tabular-nums;
}
.lesson-what { flex: 1 1 auto; min-width: 0; }
.lesson-what h2 { font-size: 1.1rem; margin: 0 0 var(--space-2); }
.lesson-what h2 a { color: inherit; text-decoration: none; }
.lesson-what h2 a:hover { color: var(--accent); }
.lesson-what p { margin: 0 0 var(--space-2); }
.lesson-meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3);
  font-size: .88rem; color: var(--ink-muted);
}
.lesson-meta span { display: inline-flex; align-items: center; gap: .35em; }
.lesson-row.is-locked .lesson-what h2 { color: var(--ink-muted); }
.lesson-row.is-locked .lesson-num { background: transparent; border: 1px dashed var(--paper-edge); }

.lesson-foot {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--space-4); margin-top: var(--space-7);
  padding-top: var(--space-5); border-top: 1px solid var(--paper-line);
}
.lesson-nav { display: flex; flex-wrap: wrap; gap: var(--space-4); font-size: .92rem; }
.lesson-nav a { display: inline-flex; align-items: center; gap: .35em; }

/* A 16:9 box that keeps its shape on a phone. */
.video-frame {
  position: relative; aspect-ratio: 16 / 9; max-width: 100%;
  margin-block: var(--space-5); border-radius: var(--radius-lg); overflow: hidden;
  background: var(--paper-sunk);
}
.video-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

@media (max-width: 32rem) {
  .lesson-row { gap: var(--space-3); }
  .lesson-num { flex-basis: 1.9rem; height: 1.9rem; font-size: .82rem; }
}

/* ---------------------------------------------------------------------------
   Things for sale.

   Each offer is a self-contained card with its own form: the price, what it
   is, and the button, without a step in between. A shop that makes somebody
   click through to a second page before they can see the price loses them on
   the first page.
   --------------------------------------------------------------------------- */
.offer-grid {
  display: grid; gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
  margin-top: var(--space-6);
}
.offer {
  position: relative;
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  border-radius: var(--radius-lg); padding: var(--space-5);
  display: flex; flex-direction: column; gap: var(--space-3);
}
.offer h2 { font-size: 1.2rem; margin: 0; }
.offer-badge {
  position: absolute; top: var(--space-4); right: var(--space-4);
  font-size: .72rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  padding: .25rem .55rem; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent-ink);
}
.offer-img {
  width: 100%; aspect-ratio: 16 / 9; object-fit: cover;
  border-radius: var(--radius); margin: 0;
}
.offer-price { font-size: 1.5rem; font-weight: 700; margin: 0; color: var(--ink); }
.offer-summary { margin: 0; color: var(--ink-soft); }
.offer-body { margin: 0; font-size: .95rem; }
/* The form sits at the bottom whatever length the description is, so a row of
   offers has its buttons on one line. */
.offer .buy-form { margin-top: auto; padding-top: var(--space-4); border-top: 1px solid var(--paper-line); }

.buy-form .row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.buy-form .field { margin-bottom: var(--space-3); }
.buy-price { font-weight: 700; opacity: .85; margin-left: .2em; }
.buy-note { display: flex; align-items: flex-start; gap: .4em; margin-top: var(--space-3); }
.buy-note svg { flex: 0 0 auto; margin-top: .18em; }

@media (max-width: 32rem) {
  .buy-form .row-2 { grid-template-columns: 1fr; }
}

/* ===========================================================================
   Page sections (blocks)

   A page built from sections is a stack of full-width bands, each bringing its
   own container. That is the point of them: a wall of logos or a coloured
   call-to-action wants the whole width, which a single column of prose can
   never give it.

   Spacing is owned by the stack rather than by each section, so two sections
   of different kinds sitting next to each other are always the same distance
   apart — the thing that goes wrong first when every block sets its own
   margins.
   =========================================================================== */
.block-stack > .block { padding-block: clamp(var(--space-6), 5vw, var(--space-8)); }
.block-stack > .block:first-child { padding-top: var(--space-5); }
/* Alternating grounds would fight the page's own sections, so a band is tinted
   only when it is asking for something. */
.block-stack > .block + .block { border-top: 1px solid var(--paper-line); }
.block-stack > .block-cta + .block,
.block-stack > .block + .block-cta { border-top: 0; }
.block > .container > h2 { margin-top: 0; margin-bottom: var(--space-4); }
.block > .container > .lead { margin-bottom: var(--space-5); }
.prose-wide { max-width: none; }

/* A page whose own header is followed straight away by a section does not need
   the header's bottom margin as well as the stack's top padding. */
.section.has-blocks { padding-bottom: 0; }

/* ---- picture and words ---- */
.media-text {
  display: grid; gap: clamp(var(--space-5), 4vw, var(--space-7));
  align-items: center; grid-template-columns: 1fr;
}
@media (min-width: 52rem) {
  .media-text { grid-template-columns: 1fr 1fr; }
  /* The picture is first in the markup so it reads first on a phone, where a
     photograph above the words is the right order. On a wide screen it can be
     moved without changing that. */
  .block-media-text.is-right .media-text-figure { order: 2; }
}
.media-text-figure img {
  width: 100%; height: auto; border-radius: var(--radius-lg);
  box-shadow: var(--shadow); margin: 0;
}
.media-text-words > :first-child { margin-top: 0; }
.media-text-words h2 { margin-bottom: var(--space-3); }

/* ---- quote ---- */
.pull-quote { margin: 0; }
/* The global blockquote is the inset one used inside prose — tinted, with a
   rule down the left. A pull quote is not that, so everything it inherits is
   put back before anything is added. */
.pull-quote blockquote {
  margin: 0; padding: 0; border: 0; background: none; border-radius: 0;
  font-size: clamp(1.25rem, 1.1rem + .8vw, 1.7rem);
  line-height: 1.4; color: var(--ink); font-weight: 500;
}
.pull-quote blockquote p { margin: 0; }
.pull-quote blockquote p::before { content: '\201C'; color: var(--accent); }
.pull-quote blockquote p::after  { content: '\201D'; color: var(--accent); }
.pull-quote figcaption {
  display: flex; align-items: center; gap: var(--space-3);
  margin-top: var(--space-5); font-size: .95rem;
}
.pull-quote figcaption > span { display: flex; flex-direction: column; }
.pull-quote-face img {
  width: 3rem; height: 3rem; border-radius: 50%; object-fit: cover; margin: 0;
  box-shadow: var(--shadow-sm);
}

/* ---- wall of logos ---- */
.logo-cards {
  list-style: none; padding: 0; margin: 0; display: grid;
  gap: clamp(var(--space-4), 3vw, var(--space-5));
  grid-template-columns: repeat(auto-fill, minmax(min(15rem, 100%), 1fr));
}
.logo-card {
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  border-radius: var(--radius-lg); padding: var(--space-5);
  display: flex; flex-direction: column; gap: var(--space-3); text-align: center;
}
/* A logo box of a fixed height with the mark centred inside it: the only way a
   row of logos looks deliberate when they arrive as wildly different shapes,
   which they always do. */
/* The box every mark is centred in. Its height comes from the block, adjusted
   for the shape of each logo — see Images::markScale(). The fallback is there
   for a logo whose size could not be read. */
.logo-card-mark {
  display: grid; place-items: center; height: var(--logo-h, 5rem);
}
.logo-card-mark img {
  max-height: var(--logo-h, 5rem); max-width: 100%; width: auto; height: auto;
  object-fit: contain; margin: 0; box-shadow: none;
}
.logo-card-name { font-size: 1rem; margin: 0; }
.logo-card-name a { color: inherit; text-decoration: none; }
.logo-card-name a:hover { color: var(--accent); text-decoration: underline; }
.logo-card-note { margin: 0; font-size: .9rem; color: var(--ink-soft); }

.logo-strip {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-wrap: wrap; align-items: center;
  gap: clamp(var(--space-5), 4vw, var(--space-7));
}
.logo-strip img {
  max-height: var(--logo-h, 3rem); width: auto; margin: 0; box-shadow: none;
  opacity: .78; transition: opacity .18s var(--ease);
}
.logo-strip a:hover img { opacity: 1; }

/* ---- grid of cards ---- */
.block-card-grid {
  list-style: none; padding: 0; margin: 0; display: grid;
  gap: clamp(var(--space-4), 3vw, var(--space-5));
  grid-template-columns: repeat(auto-fill, minmax(min(17rem, 100%), 1fr));
}
@media (min-width: 60rem) {
  .block-card-grid { grid-template-columns: repeat(var(--cols, 3), 1fr); }
}
.block-card {
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  border-radius: var(--radius-lg); overflow: hidden;
  display: flex; flex-direction: column;
}
.block-card-img img {
  width: 100%; aspect-ratio: 16 / 10; object-fit: cover; margin: 0;
  box-shadow: none; border-radius: 0;
}
.block-card h3 { font-size: 1.05rem; margin: var(--space-4) var(--space-4) 0; }
.block-card p { margin: var(--space-2) var(--space-4) 0; color: var(--ink-soft); font-size: .94rem; }
.block-card-link { margin-top: auto; padding: var(--space-4); font-size: .92rem; }
.block-card-link a { display: inline-flex; align-items: center; gap: .35em; }

/* ---- pictures ---- */
.gallery-grid {
  list-style: none; padding: 0; margin: 0; display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fill, minmax(min(14rem, 100%), 1fr));
}
.gallery-grid figure { margin: 0; }
.gallery-grid img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: var(--radius); margin: 0;
}
.gallery-grid figcaption { font-size: .85rem; color: var(--ink-muted); margin-top: var(--space-2); }

/* ---- numbered steps ---- */
.step-list {
  list-style: none; padding: 0; margin: 0; counter-reset: step;
  display: grid; gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
}
/* The number is a flex item rather than an absolutely positioned one. It used
   to sit on top of the heading whenever the heading wrapped, because absolute
   positioning takes the badge out of the flow and nothing reserves its height
   reliably across font sizes. */
.step-list > li {
  counter-increment: step;
  display: grid; grid-template-columns: 2.25rem 1fr; gap: var(--space-3);
  align-items: start;
}
.step-list > li::before {
  content: counter(step);
  width: 2.25rem; height: 2.25rem; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--accent); color: var(--on-accent);
  font-weight: 700; font-size: .95rem; font-variant-numeric: tabular-nums;
}
/* Both the heading and the text belong in the second column. Without saying
   so, the text flows into the next grid cell — which is the 2.25rem badge
   column, and gives you one word per line. */
.step-list > li > * { grid-column: 2; }
.step-list h3 { font-size: 1.05rem; margin: .3rem 0 var(--space-2); }
.step-list p { margin: 0; color: var(--ink-soft); }

/* ---- questions and answers ---- */
.faq-list { border-top: 1px solid var(--paper-line); }
.faq-item { border-bottom: 1px solid var(--paper-line); }
.faq-item > summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
  padding: var(--space-4) 0; cursor: pointer; font-weight: 600;
  list-style: none;
}
.faq-item > summary::-webkit-details-marker { display: none; }
.faq-item > summary:hover { color: var(--accent); }
.faq-item > summary svg { flex: 0 0 auto; color: var(--ink-muted); transition: transform .18s var(--ease); }
.faq-item[open] > summary svg { transform: rotate(180deg); }
.faq-answer { padding-bottom: var(--space-4); color: var(--ink-soft); max-width: 68ch; }
.faq-answer p { margin: 0; }

/* ---- numbers ---- */
.stat-row {
  list-style: none; padding: 0; margin: 0; display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(9rem, 100%), 1fr));
  text-align: center;
}
.stat-value {
  display: block; font-size: clamp(1.9rem, 1.4rem + 2vw, 3rem);
  font-weight: 700; line-height: 1.05; color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.stat-label { display: block; margin-top: var(--space-2); color: var(--ink-soft); font-size: .92rem; }

/* ---- call to action ---- */
.cta-panel {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--space-5); padding: clamp(var(--space-5), 4vw, var(--space-7));
  border-radius: var(--radius-lg);
}
.cta-panel h2 { margin: 0 0 var(--space-2); }
.cta-panel p { margin: 0; }
.cta-panel > div { flex: 1 1 22rem; }
.cta-buttons { display: flex; flex-wrap: wrap; gap: var(--space-3); }
/* A painted panel is the one place Paper Air's "colour means something" rule
   is deliberately set aside: this is the last word on a page, it carries one
   sentence and one button, and there is no second thing on it for the colour
   to compete with. It is a room, not a control. One per page — the moment
   there are two, both stop meaning anything.

   The gradient is built from the site's own accent rather than typed in, so a
   site that chose green gets a green panel. */
.cta-panel.is-accent {
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-ink) 100%);
  color: #fff;
}
.cta-panel.is-accent h2, .cta-panel.is-accent p { color: #fff; }
/* Ink, taken from the site's own text colour rather than a literal charcoal:
   a site with a warm near-black and a site with a cool one should not both
   get somebody else's #14181d. */
.cta-panel.is-dark { background: var(--ink); color: var(--paper); }
.cta-panel.is-dark h2, .cta-panel.is-dark p { color: var(--paper); }
.cta-panel.is-dark .btn-on-colour { background: var(--paper); color: var(--ink); }
.cta-panel.is-quiet { background: var(--paper-sunk); border: 1px solid var(--paper-edge); }
/* A solid white button reads on both the accent and the dark panel, where the
   site's own primary colour would disappear into the background. */
.btn-on-colour { background: #fff; color: var(--accent-ink); }
.btn-on-colour:hover { background: #fff; color: var(--accent); box-shadow: var(--shadow); }

/* ---- a row of buttons ---- */
.button-row { display: flex; flex-wrap: wrap; gap: var(--space-3); margin: 0; }

/* ---- video or map ---- */
.embed-frame {
  position: relative; aspect-ratio: 16 / 9; max-width: 100%;
  border-radius: var(--radius-lg); overflow: hidden; background: var(--paper-sunk);
}
.embed-frame.is-map { aspect-ratio: 16 / 10; }
.embed-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.embed-caption { font-size: .88rem; color: var(--ink-muted); margin-top: var(--space-3); }

/* A logo is usually dark ink on nothing, drawn to sit on white paper. On a
   dark page that makes it invisible — and a client cannot fix it, because the
   file is whatever their funder sent them. So in dark mode every logo gets a
   pale plate to sit on, which is what a printed page would have given it. */
:root[data-theme="dark"] .logo-card-mark,
:root[data-theme="dark"] .logo-strip img {
  background: #fff; border-radius: var(--radius); padding: var(--space-3);
}
:root[data-theme="dark"] .logo-strip img { padding: var(--space-2); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .logo-card-mark,
  :root:not([data-theme="light"]) .logo-strip img {
    background: #fff; border-radius: var(--radius); padding: var(--space-3);
  }
  :root:not([data-theme="light"]) .logo-strip img { padding: var(--space-2); }
}

/* ==========================================================================
   PAPER AIR — THE SHARED UTILITIES

   Four reusable pieces, so every control surface conforms without copying
   recipes around. Wearing the class is always preferred to copying the spec:
   one component, one recipe.

   .acts   — an ACTION ROW. Dresses its .btn children as menu-voice pills and
             hides their icons. It styles only the buttons, never the
             container, so it composes with whatever layout the row already
             has. Colour still comes from the .btn variant underneath, so
             hierarchy survives the costume change.
   .tray   — a segmented setting tray: a quiet inset trough, flat segments,
             and ONE raised active pill.
   .glass  — a surface that floats over content: translucent where the browser
             supports it, a solid sunk panel where it does not.
   .studio — the presentation register for a flagship message: the quiet
             dot-tag, the headline, the hairline before the action, and one
             ink button.
   ========================================================================== */

/* --- .acts — the action row, and the menu voice --------------------------
   Commandments 1 and 2. The icons go because a word in this voice scans
   faster than a picture that has to be decoded, and because eight little
   glyphs in a row is eight things competing with the one that matters. */
.acts .btn, .acts .btn-sm {
  font: var(--w-lab) .719rem/1 var(--font);
  letter-spacing: .5px;
  text-transform: uppercase;
  padding: .625rem .9375rem;
  border-radius: var(--radius-pill);
  transition: transform .15s var(--ease), box-shadow .15s var(--ease),
              border-color .14s var(--ease), background .14s var(--ease),
              color .14s var(--ease), opacity .14s var(--ease);
}
.acts .btn .icon, .acts .btn svg { display: none; }
.acts .btn:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-sm), 0 6px 16px -10px rgba(10, 11, 12, .28);
}
.acts .btn:active { transform: scale(.95); }
/* A row of chips wraps rather than scrolls; a scrolling action row hides the
   action at the end of it. */
.acts { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }

/* --- .tray — the segmented setting tray ---------------------------------- */
.tray {
  display: inline-flex; gap: 3px;
  background: var(--paper-sunk); padding: 4px;
  border-radius: var(--r-in);
  border: 1px solid var(--paper-edge);
  box-shadow: inset 0 1px 3px rgba(10, 11, 12, .06);
}
.tray > button, .tray > a {
  display: inline-flex; align-items: center; justify-content: center;
  border: none; background: transparent; color: var(--ink-muted);
  font: var(--w-lab) var(--fs-sm)/1 var(--font);
  padding: .44rem .8rem; border-radius: var(--radius-sm);
  cursor: pointer; text-decoration: none;
  transition: color .14s var(--ease), box-shadow .14s var(--ease);
}
.tray > button:hover, .tray > a:hover { color: var(--ink); }
/* One raised pill, and only one. The trough is flat so the raised one is
   unmistakable — which is the whole job of a tray. */
.tray > .on, .tray > [aria-selected="true"] {
  background: var(--paper-raised); color: var(--ink);
  box-shadow: 0 1px 2px rgba(10, 11, 12, .10),
              0 6px 16px -10px rgba(10, 11, 12, .28),
              inset 0 0 0 1px var(--paper-edge);
}

/* --- .glass — a bar that floats over content ----------------------------- */
.glass {
  background: var(--paper-sunk);
  border: 1px solid var(--paper-edge);
  border-radius: var(--radius-xl);
  box-shadow: inset 0 1px 3px rgba(10, 11, 12, .06);
}
/* The fallback above is the rule, not the exception: a solid tray is a
   perfectly good bar, and this only ever adds to it. */
@supports ((backdrop-filter: blur(4px)) or (-webkit-backdrop-filter: blur(4px))) {
  .glass {
    background: color-mix(in srgb, var(--paper-raised) 62%, transparent);
    -webkit-backdrop-filter: blur(18px) saturate(1.7);
    backdrop-filter: blur(18px) saturate(1.7);
    border-color: color-mix(in srgb, var(--paper-raised) 70%, transparent);
    box-shadow: 0 1px 1px rgba(10, 11, 12, .05),
                0 12px 32px -14px rgba(10, 11, 12, .28),
                inset 0 1px 0 color-mix(in srgb, var(--paper-raised) 80%, transparent);
  }
}

/* --- .studio — the presentation register ---------------------------------
   For the one flagship message on a page: what this organisation is for, the
   thing being launched, the invitation at the foot. What used to be done here
   with gradients and glows is done with SPACE and TYPE SIZE, which is what
   actually reads as considered.

   NOT A SECOND HOME PAGE. One sentence, one button, one fact. The moment it
   grows a second column it stops being a flagship message and starts being
   another thing to read past. */
.studio {
  position: relative; isolation: isolate; overflow: hidden;
  background: var(--paper-sunk);
  border-radius: var(--radius-lg);
  padding: var(--space-6) var(--space-6) var(--space-5);
  /* An inset hairline rather than a border: no layout cost, and it holds the
     edge on a pale page where the fill alone would not separate it. */
  box-shadow: inset 0 0 0 1px var(--paper-edge);
}
/* One bloom, not two washes, and near-white at the top so the panel reads as
   lit from above rather than tinted. Percentages, so it scales with the panel. */
.studio::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(110% 80% at 22% -10%,
              color-mix(in srgb, var(--paper-raised) 85%, transparent), transparent 68%);
}
/* The quiet dot-tag. Small capitals are the tell of a tool's interface rather
   than a brochure's — and the tone lives in the DOT, never in a painted box
   and never in the word. Commandment 4. */
.studio-tag {
  display: inline-flex; align-items: center; gap: .44rem;
  font: 700 .66rem/1 var(--font-mono);
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-muted); margin-bottom: var(--space-4);
}
.studio-tag::before {
  content: ""; width: 5px; height: 5px; border-radius: 50%;
  background: currentColor; flex: none;
}
.studio-tag.is-accent { color: var(--accent-ink); }
.studio-tag.is-green  { color: var(--green); }
.studio-tag.is-amber  { color: var(--amber); }

.studio-h {
  font-size: calc(clamp(1.4rem, 1.1rem + 1.4vw, 1.9rem) * var(--heading-scale));
  font-weight: var(--heading-weight); letter-spacing: -.036em;
  line-height: 1.14; margin: 0 0 var(--space-3);
}
.studio-p { color: var(--ink-soft); max-width: 58ch; margin: 0; }
.studio-p b { color: var(--ink); font-weight: var(--w-em); }

/* The hairline before the action underlines the SENTENCE, not the page —
   which is why it fades out rather than running the full width. */
.studio-rule {
  height: 1px; border: 0; margin: var(--space-5) 0 var(--space-4);
  background: linear-gradient(90deg, var(--paper-line), transparent 70%);
}
.studio-acts { display: flex; gap: var(--space-3); flex-wrap: wrap; align-items: center; }
.studio-note { font-size: var(--fs-fine); color: var(--ink-muted); }

/* --- tactile press, and stilling it -------------------------------------
   Every transform in Paper Air is a nicety. Somebody who has asked their
   machine for less movement gets none of them, and loses nothing but the
   movement: the hover and press still change colour and shadow. */
@media (prefers-reduced-motion: reduce) {
  .acts .btn, .acts .btn:hover, .acts .btn:active,
  .btn:active, .btn-ink:hover,
  .card-link:hover, a.card:hover { transform: none; }
}

/* ==========================================================================
   NOTICES, THE WHATSAPP BUTTON AND THE LEGAL LINE — v1.16.0
   Harvested from shoutwebsites.com and rebuilt in Paper Air: no painted
   boxes, one accent, tone in a 5px dot, and every movement stoppable.
   ========================================================================== */

/* --- the announcement bar ------------------------------------------------
   Ink on paper, not a coloured strip: it sits above every page, and a bar in
   the accent colour would be the loudest thing on every one of them. */
.nbar {
  display: flex; align-items: center; gap: var(--space-2);
  background: var(--ink); color: var(--paper);
  font-size: var(--fs-sm); line-height: 1.4;
  padding: .55rem var(--space-3) .55rem var(--space-5);
}
.nbar[hidden] { display: none; }
.nbar-track { flex: 1; min-width: 0; overflow: hidden; }
.nbar-one { margin: 0; text-align: center; }
.nbar-link { color: inherit; font-weight: var(--w-lab); text-decoration: underline;
  text-underline-offset: .2em; text-decoration-color: color-mix(in srgb, currentColor 45%, transparent); }
.nbar-link:hover { color: inherit; text-decoration-color: currentColor; }

/* Two copies of the run side by side, moved left by exactly one copy: the
   seam is invisible and the loop never jumps. The script sets the duration
   from the run's own width, so three short lines do not race past and ten
   long ones do not crawl: the reading speed stays the same either way. */
.nbar.is-scrolling .nbar-track {
  display: flex;
  mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
}
.nbar-run {
  display: flex; gap: 3rem; margin: 0; padding: 0 3rem 0 0; list-style: none;
  flex: none; white-space: nowrap;
  animation: nbar-scroll 38s linear infinite;
}
.nbar-run li { margin: 0; }
.nbar-run li::before { content: ""; display: inline-block; width: 5px; height: 5px; border-radius: 50%;
  background: currentColor; opacity: .5; margin-right: 1rem; vertical-align: middle; }
@keyframes nbar-scroll { to { transform: translateX(-100%); } }
/* Stoppable three ways (WCAG 2.2.2): under the pointer, on keyboard focus,
   and by the button. */
.nbar:hover .nbar-run, .nbar:focus-within .nbar-run, .nbar.is-paused .nbar-run { animation-play-state: paused; }
/* And not moving at all for anybody who has asked for less motion — the
   run wraps into ordinary lines instead, with the copy hidden. */
@media (prefers-reduced-motion: reduce) {
  .nbar-run { animation: none; white-space: normal; flex-wrap: wrap; gap: .25rem 2rem; padding: 0; }
  .nbar-run[aria-hidden="true"] { display: none; }
  .nbar.is-scrolling .nbar-track { mask-image: none; }
}
.nbar-btn {
  flex: none; display: grid; place-items: center; width: 30px; height: 30px;
  border: 0; border-radius: var(--radius-pill); cursor: pointer;
  background: transparent; color: inherit; opacity: .75;
}
.nbar-btn:hover { opacity: 1; background: color-mix(in srgb, currentColor 12%, transparent); }
.nbar-btn svg { fill: currentColor; }
.nbar-btn .icon { fill: none; }
.nbar-btn[aria-pressed="true"] svg rect:first-child { transform: none; }

/* --- the what's-new panel ------------------------------------------------ */
.npanel { position: fixed; left: var(--space-4); bottom: var(--space-4); z-index: 60; }
/* The tab is a menu-voice pill: 600 at 11.5px, uppercase, tracked. */
.npanel-tab {
  display: inline-flex; align-items: center; gap: .5rem;
  font: var(--w-lab) .719rem/1 var(--font); letter-spacing: .5px; text-transform: uppercase;
  padding: .7rem 1rem; border-radius: var(--radius-pill); cursor: pointer;
  color: var(--ink); background: var(--paper-raised); border: 1px solid var(--paper-edge);
  box-shadow: 0 1px 2px rgba(10,11,12,.10), 0 6px 16px -10px rgba(10,11,12,.28);
  transition: transform .15s var(--ease), box-shadow .15s var(--ease);
}
.npanel-tab:hover { transform: translateY(-1px); }
.npanel-tab:active { transform: scale(.95); }
.npanel-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-faint); }
.npanel.is-new .npanel-dot { background: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }
.npanel-count { font-variant-numeric: tabular-nums; color: var(--ink-muted); }
.npanel.is-open .npanel-tab { visibility: hidden; }

/* The box is the frosted surface. Solid where blur is not supported, which is
   a perfectly good panel on its own. */
.npanel-box {
  position: absolute; left: 0; bottom: 0; width: min(360px, calc(100vw - 2 * var(--space-4)));
  max-height: min(70vh, 560px); overflow: auto;
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  border-radius: var(--radius-xl); box-shadow: var(--shadow-lg);
}
@supports ((backdrop-filter: blur(4px)) or (-webkit-backdrop-filter: blur(4px))) {
  .npanel-box {
    background: color-mix(in srgb, var(--paper-raised) 86%, transparent);
    -webkit-backdrop-filter: blur(24px) saturate(1.7); backdrop-filter: blur(24px) saturate(1.7);
  }
}
.npanel-box[hidden] { display: none; }
.npanel.is-open .npanel-box { animation: npanel-in .22s var(--ease); }
@keyframes npanel-in { from { opacity: 0; transform: translateY(8px) scale(.98); } }
@media (prefers-reduced-motion: reduce) { .npanel.is-open .npanel-box { animation: none; } .npanel-tab:hover, .npanel-tab:active { transform: none; } }
.npanel-head { display: flex; align-items: center; justify-content: space-between;
  padding: var(--space-4) var(--space-4) var(--space-2) var(--space-5); position: sticky; top: 0; }
.npanel-head h2 { font-size: 1.05rem; margin: 0; }
.npanel-head h2:focus { outline: none; }
.npanel-close { display: grid; place-items: center; width: 32px; height: 32px; border: 0; cursor: pointer;
  border-radius: var(--radius-pill); background: transparent; color: var(--ink-muted); }
.npanel-close:hover { background: var(--paper-sunk); color: var(--ink); }
.npanel-list { list-style: none; margin: 0; padding: 0 var(--space-5) var(--space-5); }
.npanel-item { padding: var(--space-3) 0 var(--space-3) var(--space-4); margin: 0; position: relative;
  border-top: 1px solid var(--paper-edge); }
.npanel-item:first-child { border-top: 0; }
/* The tone lives in the dot and nowhere else. Commandment 4. */
.npanel-item::before { content: ""; position: absolute; left: 0; top: calc(var(--space-3) + .5em);
  width: 5px; height: 5px; border-radius: 50%; background: var(--ink-faint); }
.npanel-item.tone-accent::before { background: var(--accent); }
.npanel-item.tone-green::before  { background: var(--green); }
.npanel-item.tone-amber::before  { background: var(--amber); }
.npanel-item strong { display: block; font-weight: var(--w-lab); line-height: 1.35; }
.npanel-item p { margin: .25rem 0 0; font-size: var(--fs-sm); color: var(--ink-soft); }
.npanel-item a { display: inline-block; margin-top: .35rem; font-size: var(--fs-sm); font-weight: var(--w-lab); }

/* --- the floating WhatsApp button ----------------------------------------
   WhatsApp's own green: somebody else's brand, recognised on sight, and one
   of the two places a literal colour is right (see .send). */
.wa-fab {
  position: fixed; right: var(--space-4); bottom: var(--space-4); z-index: 60;
  width: 56px; height: 56px; border-radius: 50%; display: grid; place-items: center;
  background: #1f8a4c; color: #fff;
  box-shadow: 0 2px 8px rgba(10,11,12,.18), 0 10px 26px -8px rgba(31,138,76,.5);
  transition: transform .15s var(--ease), box-shadow .15s var(--ease);
}
.wa-fab:hover { color: #fff; transform: translateY(-2px); }
.wa-fab:active { transform: scale(.95); }
@media (prefers-reduced-motion: reduce) { .wa-fab:hover, .wa-fab:active { transform: none; } }
/* On a phone both floating things share the bottom edge; keep them apart. */
@media (max-width: 520px) {
  .npanel { left: var(--space-3); bottom: var(--space-3); }
  .wa-fab { right: var(--space-3); bottom: var(--space-3); width: 52px; height: 52px; }
}

/* --- the proof row under the home page tagline --------------------------- */
.hero-proof {
  display: flex; flex-wrap: wrap; gap: .35rem 1.25rem;
  list-style: none; margin: 0; padding: 0;
  font-size: var(--fs-sm); font-weight: var(--w-em); color: rgba(255,255,255,.94);
  text-shadow: 0 1px 2px rgba(0, 0, 0, .5), 0 2px 14px rgba(0, 0, 0, .5);
}
.hero-proof li { margin: 0; display: inline-flex; align-items: center; gap: .5rem; }
.hero-proof li::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; opacity: .7; }

/* --- the legal line in the footer ---------------------------------------- */
.footer-legal { font-size: var(--fs-fine); color: var(--ink-muted); margin: var(--space-6) 0 0;
  padding-top: var(--space-4); border-top: 1px solid var(--paper-edge); line-height: 1.6; }

/* --- reviews ------------------------------------------------------------- */
.rv-grid { list-style: none; margin: var(--space-5) 0 0; padding: 0;
  display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.rv-card { margin: 0; display: flex; flex-direction: column; gap: var(--space-3);
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  border-radius: var(--radius-lg); padding: var(--space-5); }
.rv-card blockquote { margin: 0; padding: 0; background: none; border: 0; color: var(--ink); }
.rv-card blockquote p { margin: 0; line-height: 1.6; }
/* Stars in ink, not gold: they are information, and the page's one colour
   belongs to the thing somebody came to do. */
.rv-stars { display: inline-flex; gap: 2px; }
.rv-stars svg { fill: var(--ink); }
.rv-stars svg.off { fill: var(--paper-line); }
.rv-who { margin: auto 0 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: .15rem .6rem;
  font-size: var(--fs-sm); color: var(--ink-muted); }
.rv-who strong { color: var(--ink); font-weight: var(--w-lab); }
.rv-source::before { content: "·"; margin-right: .6rem; }
.rv-more { margin: var(--space-5) 0 0; }

/* --- comparison / price table ------------------------------------------- */
.cmp-grid { display: grid; gap: var(--space-4); margin-top: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); align-items: stretch; }
.cmp-card { position: relative; display: flex; flex-direction: column;
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  border-radius: var(--radius-lg); padding: var(--space-5); }
/* The picked one says "this one" with an edge, not a painted box. */
.cmp-card.is-featured { border-color: var(--ink); box-shadow: 0 0 0 1px var(--ink), var(--shadow); }
.cmp-badge { position: absolute; top: calc(-1 * .75rem); left: var(--space-5);
  font: var(--w-lab) .7rem/1 var(--font); letter-spacing: .5px; text-transform: uppercase;
  padding: .4rem .7rem; border-radius: var(--radius-pill); background: var(--ink); color: var(--paper); }
.cmp-card h3 { margin: 0 0 var(--space-2); font-size: 1.1rem; }
.cmp-price { margin: 0; font-family: var(--heading-font); font-size: var(--fs-display);
  font-weight: var(--heading-weight); letter-spacing: -.035em; line-height: 1; }
.cmp-note { margin: .4rem 0 0; font-size: var(--fs-sm); color: var(--ink-muted); }
.cmp-list { list-style: none; margin: var(--space-4) 0 0; padding: var(--space-4) 0 0;
  border-top: 1px solid var(--paper-edge); display: grid; gap: .55rem; }
.cmp-list li { margin: 0; padding-left: 1.5rem; position: relative; font-size: var(--fs-sm); line-height: 1.45; }
.cmp-list li::before { position: absolute; left: 0; top: 0; font-weight: 700; }
.cmp-list li.is-yes::before { content: "✓"; color: var(--green); }
.cmp-list li.is-no { color: var(--ink-faint); text-decoration: line-through; text-decoration-color: color-mix(in srgb, currentColor 50%, transparent); }
.cmp-list li.is-no::before { content: "–"; text-decoration: none; }
.cmp-do { margin: auto 0 0; padding-top: var(--space-5); }
.cmp-foot { margin: var(--space-4) 0 0; font-size: var(--fs-fine); color: var(--ink-muted); }
