/* M22: the eight public stylesheets in cascade order, built by scripts/build_css.py; do not edit. */

/* Self-hosted webfonts (no third-party requests).
   Petrona = headings · Work Sans variable 400 to 600 = body & UI.
   Subsets: latin + latin-ext (full French diacritics incl. œ Œ €). */

/* Petrona Bold: latin. The file is Petrona's 700 cut, but the descriptor
   accepts 600 as well, because Petrona runs lighter than the Fraunces it
   replaced and every heading rule in this project asks for 600. Declaring the
   range means both numbers land on this file, with no synthetic bolding. */
@font-face {
  font-family: 'Petrona';
  font-style: normal;
  font-weight: 600 700;
  font-display: swap;
  src: url("../fonts/petrona-700-latin.93bdf470acd9.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* Petrona Bold: latin-ext */
@font-face {
  font-family: 'Petrona';
  font-style: normal;
  font-weight: 600 700;
  font-display: swap;
  src: url("../fonts/petrona-700-latin-ext.347106fb1c0c.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Work Sans 400 to 600 (variable): latin */
@font-face {
  font-family: 'Work Sans';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("../fonts/worksans-latin.4890688e6436.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* Work Sans 400 to 600 (variable): latin-ext */
@font-face {
  font-family: 'Work Sans';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("../fonts/worksans-latin-ext.1f8c41030121.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@layer reset, tokens, base, layout, components, utilities;

@layer reset {
  *, *::before, *::after { box-sizing: border-box; }
  * { margin: 0; }
  /* The browser centers a modal <dialog> in the viewport with automatic
     margins. The blanket margin reset above outranks that default and would
     leave every dialog pinned in the top corner, so the centering is put back. */
  dialog { margin: auto; }
  html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scrollbar-gutter: stable; }
  body { min-height: 100svh; line-height: 1.5; -webkit-font-smoothing: antialiased; }
  img, picture, video, canvas, svg { display: block; max-width: 100%; height: auto; }
  iframe { max-width: 100%; }
  pre { max-width: 100%; overflow-x: auto; }
  input, button, textarea, select { font: inherit; color: inherit; }
  p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }
  ul[role="list"], ol[role="list"] { list-style: none; padding: 0; }
  :focus-visible { outline: 2px solid var(--color-focus, currentColor); outline-offset: 2px; box-shadow: 0 0 0 4px var(--color-focus-halo, transparent); }  /* M22: a halo keeps the ring readable on any ground */
  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
      animation-duration: .01ms !important; animation-iteration-count: 1 !important;
      transition-duration: .01ms !important; scroll-behavior: auto !important;
    }
  }
}

/* Design tokens: generated from project/brand.md Part 2 (the SSOT).
   Single committed light look: warm parchment japandi; the ink footer is the
   dark surface. All text pairings validated WCAG 2.2 AA. */
@layer tokens {
  :root {
    color-scheme: light;

    /* colour */
    --color-bg: #F2EDE3;             /* warm parchment */
    --color-surface: #E8E0D0;        /* sand */
    --color-paper: #FFFCF7;          /* M38: the cards' fill on the events page (the admin's paper, M37) */
    --color-border: #D8CDB9;         /* sand, deepened for hairlines */
    --color-text: #1F1A16;           /* warm charcoal, deepened for readability: 14.78:1 on parchment (was #2B2521, 12.95:1) */
    --color-text-muted: #4F463C;     /* clay grey, deepened to the admin's measured value (7.92:1 on parchment, 7.04:1 on sand, 9.02:1 on paper; was #6C6155 at 5.17:1) */
    --color-accent: #A23E2A;         /* brick terracotta: sparingly */
    --color-accent-contrast: #F7F2E8;/* cream on accent */
    --color-ink: #211C18;            /* footer / dark sections */
    --color-cream: #F7F2E8;          /* text + logo on ink */
    --color-ochre: #B9854D;          /* decorative only, never body text */
    --color-ochre-deep: #8F5F2C;     /* M47: the ochre as text, 5.34:1 on the paper and 4.69:1 on the parchment */
    --color-danger: #8F2F1D;
    --color-success: #3D5A3A;
    --color-control-border: #8F8270;  /* M22: control boundaries at 3.22:1 on parchment (the admin's value); --color-border stays for decorative hairlines */
    --color-focus-halo: var(--color-bg);
    --color-focus: #A23E2A;
    /* M16: the two public event categories (text and dot colour; the chip text
       is the signal, the colour is secondary). Plum 7.56:1 and teal 6.17:1 on
       the parchment, 6.72:1 and 5.48:1 on the sand. */
    --color-cat-danse: #6B3A5B;
    --color-cat-connect: #2F5F5E;

    /* fluid type: ratio 1.25, body 1rem→1.125rem */
    --fs--1: clamp(0.9rem, 0.87rem + 0.15vw, 1rem);   /* the small type carries most of a page's facts, so it starts a step larger */
    --fs-0:  clamp(1rem, 0.96rem + 0.20vw, 1.125rem);
    --fs-1:  clamp(1.25rem, 1.19rem + 0.30vw, 1.41rem);
    --fs-2:  clamp(1.56rem, 1.45rem + 0.55vw, 1.76rem);
    --fs-3:  clamp(1.95rem, 1.74rem + 0.95vw, 2.34rem);
    --fs-4:  clamp(2.4rem, 2.05rem + 1.6vw, 3rem);
    --fs-5: clamp(2.0625rem, 0.75rem + 3.125vw, 3.5rem);  /* M32: About section headings and the mission statement */
    --fs-display: clamp(2.8125rem, 1rem + 5.5vw, 5.5rem);  /* M32: the About title */

    /* spacing: airy japandi rhythm */
    --space-2xs: .25rem; --space-xs: .5rem; --space-sm: .75rem;
    --space-md: 1rem; --space-lg: 1.5rem; --space-xl: 2.5rem;
    --space-2xl: 4rem; --space-3xl: 6rem;
    --space-fluid: clamp(2rem, 1.2rem + 4vw, 5rem);
    --space-section: clamp(3.5rem, 1.5rem + 6.25vw, 7.5rem);  /* M32: the About page's rhythm; M75: 56 to 120 px, down from 72 to 160 */

    /* families */
    --font-heading: 'Petrona', Georgia, 'Times New Roman', serif;
    --font-body: 'Work Sans', system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;

    /* shape & depth */
    --radius-sm: 6px; --radius-md: 12px; --radius-lg: 20px; --radius-pill: 999px;
    --shadow-2: 0 6px 24px rgb(33 28 24 / .10);
    --border: 1px solid var(--color-border);

    /* layout */
    --container: 80rem;
    --container-narrow: 44rem;
    --gutter: clamp(1.25rem, 0.5rem + 3vw, 5rem);
    --header-h: 56px;

    /* z-index */
    --z-base: 0; --z-sticky: 100; --z-overlay: 800; --z-modal: 900; --z-toast: 1000;

    /* motion */
    --dur-fast: 120ms; --dur-mid: 220ms; --dur-slow: 360ms; --dur-reveal: 600ms;
    --ease: cubic-bezier(.2, 0, .2, 1);
  }
}

@layer base {
  html { scroll-padding-block-start: calc(var(--header-h) + var(--space-sm)); }
  body {
    background: var(--color-bg);
    color: var(--color-text);
    font-family: var(--font-body);
    font-size: var(--fs-0);
    /* Work Sans is a variable face from 400 to 600. At 400 its stems are thin
       enough on the parchment that dark text still reads grey, so the page
       sets its normal weight a half step up. */
    font-weight: 450;
    line-height: 1.6;
    display: flex;
    flex-direction: column;
  }
  main { flex: 1; }

  h1, h2, h3 {
    font-family: var(--font-heading);
    font-weight: 600;
    line-height: 1.15;
    letter-spacing: -0.01em;
    text-wrap: balance;
  }
  h1 { font-size: var(--fs-4); }
  h2 { font-size: var(--fs-2); }
  h3 { font-size: var(--fs-1); }
  p { text-wrap: pretty; max-inline-size: 70ch; }

  a { color: var(--color-accent); text-underline-offset: .15em; }
  a:hover { text-decoration-thickness: 2px; }

  ::selection { background: var(--color-accent); color: var(--color-accent-contrast); }
}

@layer layout {
  .container {
    width: 100%;
    max-inline-size: var(--container);
    margin-inline: auto;
    padding-inline: var(--gutter);
  }
  .container--narrow { max-inline-size: var(--container-narrow); }

  .section { padding-block: var(--space-fluid); }

  /* header */
  /* full-bleed bar; the contents sit in the same container as the page and the footer */
  .site-header {
    position: sticky;
    inset-block-start: 0;
    z-index: var(--z-sticky);
    background: var(--color-bg);
    border-block-end: var(--border);
  }
  .site-header__inner {
    width: 100%;
    max-inline-size: var(--container);
    margin-inline: auto;
    padding-inline: var(--gutter);
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    min-block-size: var(--header-h);
  }
  @supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .site-header {
      background: color-mix(in srgb, var(--color-bg) 80%, transparent);
      -webkit-backdrop-filter: blur(16px) saturate(160%);
      backdrop-filter: blur(16px) saturate(160%);
    }
  }
  @media (min-width: 480px) {
    .site-header__inner { gap: var(--space-md); }
  }

  /* footer: ink surface, cream text + cream logo. M18: one row from 640 px, half the height.
     After M39.2: the row starts at 900 px. M18's 640 fitted a row of two blocks; the newsletter
     column M28 (D5) put between them needs about 850 px before the three fit side by side
     (the brand and the legal links do not shrink, the newsletter block stops at its field's
     14 rem), so between 640 and 830 px the legal links ran past the window. */
  .site-footer {
    background: var(--color-ink);
    color: var(--color-cream);
    padding-block: var(--space-xl);
    margin-block-start: var(--space-3xl);
  }
  .site-footer__inner {
    width: 100%;
    max-inline-size: var(--container);
    margin-inline: auto;
    padding-inline: var(--gutter);
    display: flex;
    flex-direction: column;
    gap: var(--space-lg);
  }
  .site-footer a { color: var(--color-cream); }
  .site-footer .logo-mark { inline-size: 2rem; block-size: auto; color: var(--color-cream); }
  .site-footer__brand { display: flex; align-items: center; gap: var(--space-sm); }
  .site-footer__name { font-family: var(--font-heading); font-weight: 600; font-size: var(--fs-1); margin: 0; }
  /* M28 (D5, D5.1): the newsletter block, the social icons under it */
  .site-footer__news { display: grid; gap: var(--space-sm); justify-items: start; }
  /* 2026-09-13 review: the lead reads as the block's title, same size as the brand name */
  .site-footer__lead { font-family: var(--font-heading); font-weight: 600; font-size: var(--fs-1); line-height: 1.25; letter-spacing: -0.01em; text-wrap: balance; margin: 0; }
  .footer-signup { display: flex; flex-wrap: wrap; gap: var(--space-xs); align-items: center; }
  .footer-signup__field {
    min-inline-size: 14rem;
    flex: 1 1 14rem;
    padding: var(--space-2xs) var(--space-sm);
    min-block-size: 44px;
    border: 1px solid rgb(247 242 232 / .45);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--color-cream);
    font: inherit;
  }
  .footer-signup__field::placeholder { color: rgb(247 242 232 / .55); }
  .footer-signup__field:focus-visible { outline: 2px solid var(--color-cream); outline-offset: 2px; }
  .site-footer__interests { font-size: var(--fs--1); margin: 0; }
  .site-footer__interests a { font-weight: 400; }
  /* 2026-09-13 review: air around the icon row; the first icon's glyph sits flush
     with the content edge (the 44px tap target is 8px wider than the 28px glyph) */
  .site-footer .social-row { padding-block: 1.5rem .875rem; }
  .site-footer .social-row li:first-child .social-link--icon { margin-inline-start: -8px; }
  .site-footer__heading {
    font-family: var(--font-body);
    font-size: var(--fs--1);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .08em;
    margin-block-end: var(--space-xs);
  }
  .site-footer__links { display: flex; flex-wrap: wrap; gap: var(--space-md); }
  .site-footer__note {
    padding-inline: var(--gutter);  /* 2026-09-13 review: align with the container gutter */
    max-inline-size: var(--container);
    margin-inline: auto;
    margin-block-start: var(--space-md);
    padding-block-start: var(--space-sm);
    border-block-start: 1px solid rgb(247 242 232 / .2);
    font-size: var(--fs--1);
  }
  @media (min-width: 900px) {
    /* M28 (D5): three columns hold the row: brand, newsletter, legal */
    .site-footer__inner { flex-direction: row; align-items: start; gap: var(--space-xl); }
    .site-footer__brand { flex: 0 0 auto; align-items: start; }
    .site-footer__news { flex: 1 1 22rem; }
    .site-footer__inner > .site-footer__nav { flex: 0 0 auto; margin-inline-start: auto; }
    .site-footer__heading { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  }

  /* simple flowing prose pages */
  .prose { display: grid; gap: var(--space-md); }
  .prose h2 { margin-block-start: var(--space-lg); }
  /* M22: the description's markup (events/markup.py) */
  .prose h3 { margin-block-start: var(--space-md); }
  .prose ul { padding-inline-start: 1.25rem; display: grid; gap: var(--space-2xs); }
}

/* M47: the one card both sites use. The console links it beside admin.css and the
   public bundle builds it in (scripts/build_css.py). Everything here is neutral:
   the palette is the eight custom properties at the top of .toasts, and each site
   declares its own skin (the console's grey in admin.css, the loft's parchment as
   .toasts.toasts--brand in components.css). The script is js/toast.js.
   Layered on purpose: an unlayered declaration beats every layered one whatever the
   specificity, so a layered neutral block loses to the console's unlayered skin and
   can be beaten inside the layer by the public one. Both are what we want. */
@layer components {
  .toasts {
    --toast-bg: #FFFFFF;
    --toast-fg: #52525B;
    --toast-line: #E4E4E7;
    --toast-radius: 12px;
    --toast-shadow: 0 4px 12px rgb(0 0 0 / .08);
    --toast-clearance: 0px;       /* set by the script from the page's bottom bar */

    position: fixed;
    z-index: var(--toast-z, 50);  /* over the console's phone drawer (39) and save bar (30) */
    right: 1rem;
    bottom: calc(1rem + var(--toast-clearance));
    display: flex;
    flex-direction: column-reverse;  /* the newest card sits nearest the corner */
    gap: .5rem;
    width: min(24rem, calc(100vw - 2rem));
    pointer-events: none;
  }
  .toast-card {
    pointer-events: auto;
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: start;
    column-gap: .625rem;
    padding: .75rem .875rem;
    background: var(--toast-bg);
    color: var(--toast-fg);
    border: 1px solid var(--toast-tone-line, var(--toast-line));
    border-radius: var(--toast-radius);
    box-shadow: var(--toast-shadow);
    animation: toast-in 300ms cubic-bezier(.2, 0, .2, 1) both;
  }
  .toast-card--success { --toast-tone: #15803D; --toast-tone-line: #C6E6CE; }
  .toast-card--info    { --toast-tone: #1D4ED8; --toast-tone-line: #C9D8F2; }
  .toast-card--warning { --toast-tone: #B45309; --toast-tone-line: #EEDCB5; }
  .toast-card--error   { --toast-tone: #B91C1C; --toast-tone-line: #F0C9C4; }
  .toast-card__icon { grid-row: 1 / span 2; width: 1.125rem; height: 1.125rem; margin-top: .0625rem; color: var(--toast-tone); flex: 0 0 auto; }
  .toast-card__title { grid-column: 2; margin: 0; font-size: .875rem; font-weight: 600; line-height: 1.35; color: var(--toast-tone); }
  .toast-card__text { grid-column: 2; font-size: .875rem; font-weight: 400; line-height: 1.4; margin: 0; }
  .toast-card__title + .toast-card__text { margin-top: .125rem; }
  .toast-card__undo { grid-column: 2; justify-self: start; margin-top: .375rem; padding: 0; border: 0; background: none; font: inherit; font-size: .875rem; font-weight: 600; color: var(--toast-undo-color, inherit); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
  .toast-card__undo:hover { color: var(--toast-tone); }
  .toast-card__close { grid-column: 3; grid-row: 1; position: relative; width: 1.375rem; height: 1.375rem; padding: 0; border: 0; border-radius: 4px; background: none; color: var(--toast-close-color, #71717A); font-size: 1rem; line-height: 1; cursor: pointer; }
  .toast-card__close:hover { background: var(--toast-close-hover-bg, #F4F4F5); color: var(--toast-close-hover-color, #18181B); }
  .toast-card__undo:focus-visible, .toast-card__close:focus-visible { outline: 2px solid var(--toast-focus, var(--toast-tone)); outline-offset: 2px; }
  .toast-card--leaving { animation: toast-out 200ms cubic-bezier(.2, 0, .2, 1) both; }

  @keyframes toast-in { from { opacity: 0; transform: translateY(50px) scale(.95); } to { opacity: 1; transform: none; } }
  @keyframes toast-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(20px); } }
  @media (prefers-reduced-motion: reduce) {
    .toast-card, .toast-card--leaving { animation: none; }
  }
  @media (max-width: 42.5rem) {
    .toasts { left: .75rem; right: .75rem; bottom: calc(.75rem + var(--toast-clearance)); width: auto; }
  }
}

@layer components {
  /* brand lockup */
  .brand {
    display: inline-flex;
    align-items: center;
    gap: var(--space-sm);
    color: var(--color-text);
    text-decoration: none;
  }
  .brand .logo-mark { inline-size: 1.5rem; block-size: auto; color: var(--color-text); }
  .brand__name { font-family: var(--font-heading); font-weight: 600; font-size: var(--fs-0); white-space: nowrap; }
  @media (min-width: 480px) {
    .brand__name { font-size: var(--fs-1); }
  }

  /* nav: hamburger disclosure on small screens (full-height overlay panel),
     inline row from 768px (js forces the disclosure open) */
  .nav-disclosure > summary {
    list-style: none;
    cursor: pointer;
    inline-size: 44px;
    min-block-size: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-sm);
  }
  .nav-disclosure > summary::-webkit-details-marker { display: none; }
  .nav-icon { display: block; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
  .nav-icon line {
    /* M28 (D9): fill-box makes transform-origin: center each line's own centre,
       not the SVG's, which is what Safari needs to draw a straight X. */
    transform-box: fill-box;
    transform-origin: center;
    transition: transform var(--dur-mid) var(--ease), opacity var(--dur-fast) var(--ease);
  }
  /* open state: the three lines morph into an X (the universal close) */
  .nav-disclosure[open] .nav-icon__top { transform: translateY(6px) rotate(45deg); }
  .nav-disclosure[open] .nav-icon__mid { opacity: 0; }
  .nav-disclosure[open] .nav-icon__bot { transform: translateY(-6px) rotate(-45deg); }
  /* absolute (not fixed): the header's backdrop-filter makes it the containing
     block for fixed descendants, which would clip the panel to the header.
     M22: the panel holds the link list and a foot (the next evening, the social links). */
  .nav-panel {
    position: absolute;
    inset-inline: 0;
    inset-block-start: var(--header-h);
    block-size: calc(100svh - var(--header-h));
    z-index: var(--z-overlay);
    overflow-y: auto;
    display: grid;
    align-content: start;
    gap: var(--space-xl);
    padding: var(--space-xl) var(--gutter) max(var(--space-xl), env(safe-area-inset-bottom));
    background: var(--color-bg);
  }
  .nav-panel > ul { display: grid; gap: var(--space-xs); }
  .nav-panel > ul a {
    display: flex;
    align-items: center;
    min-block-size: 48px;
    color: var(--color-text);
    text-decoration: none;
    font-family: var(--font-heading);
    font-size: var(--fs-2);
    font-weight: 600;
  }
  .nav-panel > ul a:hover { color: var(--color-accent); }
  .nav-panel > ul a[aria-current="page"] {
    color: var(--color-accent);
    text-decoration: underline;
    text-underline-offset: .3em;
  }
  .nav-foot { display: grid; gap: var(--space-md); border-block-start: var(--border); padding-block-start: var(--space-lg); }
  .nav-foot__label { font-size: var(--fs--1); font-weight: 600; text-transform: uppercase; letter-spacing: .08em; color: var(--color-text-muted); }
  body.panel-open { overflow: hidden; }
  /* M28 (D9): the panel slides and fades in, its links cascading behind it, and
     the close reverses it (js/nav.js holds the disclosure open for the closing
     animation). Reduced motion gets a panel that is simply there. */
  @media (max-width: 767px) and (prefers-reduced-motion: no-preference) {
    .nav-disclosure[open] .nav-panel { animation: nav-panel-in var(--dur-mid) var(--ease) both; }
    .nav-disclosure[open] .nav-panel > ul > li,
    .nav-disclosure[open] .nav-panel .nav-foot { animation: nav-item-in var(--dur-mid) var(--ease) both; }
    .nav-disclosure[open] .nav-panel > ul > li:nth-child(1) { animation-delay: 60ms; }
    .nav-disclosure[open] .nav-panel > ul > li:nth-child(2) { animation-delay: 100ms; }
    .nav-disclosure[open] .nav-panel > ul > li:nth-child(3) { animation-delay: 140ms; }
    .nav-disclosure[open] .nav-panel > ul > li:nth-child(4) { animation-delay: 180ms; }
    .nav-disclosure[open] .nav-panel > ul > li:nth-child(5) { animation-delay: 220ms; }
    .nav-disclosure[open] .nav-panel .nav-foot { animation-delay: 260ms; }
    .nav-disclosure.is-closing .nav-panel { animation: nav-panel-out var(--dur-fast) var(--ease) both; }
    .nav-disclosure.is-closing .nav-panel > ul > li,
    .nav-disclosure.is-closing .nav-panel .nav-foot { animation: nav-item-out var(--dur-fast) var(--ease) both; animation-delay: 0s; }
  }
  @keyframes nav-panel-in { from { opacity: 0; transform: translateY(-1rem); } to { opacity: 1; transform: none; } }
  @keyframes nav-panel-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(-1rem); } }
  @keyframes nav-item-in { from { opacity: 0; transform: translateY(.75rem); } to { opacity: 1; transform: none; } }
  @keyframes nav-item-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(.5rem); } }
  @media (min-width: 768px) {
    .nav-disclosure > summary { display: none; }
    .nav-panel {
      position: static;
      block-size: auto;
      display: block;
      background: none;
      padding: 0;
      overflow: visible;
    }
    .nav-panel > ul { display: flex; gap: var(--space-lg); }
    .nav-panel > ul a {
      min-block-size: 44px;
      font-family: var(--font-body);
      font-size: var(--fs-0);
      font-weight: 500;
    }
    .nav-foot { display: none; }
  }

  /* language toggle: two letters (M7); since M22 a plain link (shareable, opens in a new tab), left of the hamburger */
  .lang-switch {
    margin-inline-start: auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: 1px solid var(--color-control-border);
    border-radius: var(--radius-pill);
    min-block-size: 44px;
    min-inline-size: 44px;
    padding-inline: var(--space-sm);
    color: var(--color-text);
    text-decoration: none;
    font-size: var(--fs--1);
    font-weight: 600;
    letter-spacing: .04em;
  }
  @media (min-width: 768px) {
    .site-nav { order: 1; margin-inline-start: auto; }
    .lang-switch { order: 2; margin-inline-start: 0; }
  }
  .lang-switch:hover { border-color: var(--color-accent); color: var(--color-accent); }

  /* buttons */
  .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-xs);
    min-block-size: 44px;
    padding: var(--space-xs) var(--space-lg);
    border: 0;
    border-radius: var(--radius-pill);
    background: var(--color-accent);
    color: var(--color-accent-contrast);
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    transition: background var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
  }
  .btn:hover { background: color-mix(in oklab, var(--color-accent), #000 12%); }
  .btn:active { transform: translateY(1px); }
  .btn--ghost {
    background: transparent;
    color: var(--color-accent);
    box-shadow: inset 0 0 0 1px currentColor;
  }
  .btn--ghost:hover { background: color-mix(in srgb, var(--color-accent) 10%, transparent); }
  .btn--small { font-size: var(--fs--1); padding-inline: var(--space-md); }
  .btn--large { font-size: var(--fs-1); min-block-size: 56px; padding: var(--space-sm) var(--space-xl); }  /* M32: the About page's closing action */

  /* hero */
  /* viewport-tall with the copy at the foot: 60svh, then 86svh from 900 px. The height
     holds while the window narrows and steps once, instead of drifting with the width. */
  .hero {
    position: relative;
    min-block-size: 60svh;
    display: flex;
    align-items: flex-end;
    padding-block: var(--space-2xl) var(--space-xl);
    isolation: isolate;
    overflow: clip;
    background: var(--color-ink);
  }
  @media (min-width: 900px) {
    .hero { min-block-size: 86svh; padding-block-end: var(--space-2xl); }
  }
  .hero__image { position: absolute; inset: 0; z-index: -2; width: 100%; height: 100%; object-fit: cover; }
  .hero::before { content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(180deg, color-mix(in oklab, var(--color-ink), transparent 15%), color-mix(in oklab, var(--color-ink), transparent 45%)); }
  .hero .logo-mark { inline-size: clamp(3.5rem, 2.5rem + 5vw, 6rem); color: var(--color-cream); margin-block-end: var(--space-lg); }
  .hero h1 { max-inline-size: 22ch; color: var(--color-cream); }
  .hero__actions { display: flex; flex-wrap: wrap; gap: var(--space-md); margin-block-start: var(--space-xl); }
  .hero__actions .btn--ghost { color: var(--color-cream); }
  /* M22: the focus ring on the two dark grounds: cream ring (15:1 on ink), ink halo keeps it off the picture */
  .hero, .site-footer { --color-focus: var(--color-cream); --color-focus-halo: var(--color-ink); }
  /* M30, generalised in M32: the point of a picture kept in view on every screen (SiteImage.image_focus_x/y, in steps of 5) */
  .focus { object-position: var(--fx, 50%) var(--fy, 50%); }
  .focus--x0 { --fx: 0%; }
  .focus--x5 { --fx: 5%; }
  .focus--x10 { --fx: 10%; }
  .focus--x15 { --fx: 15%; }
  .focus--x20 { --fx: 20%; }
  .focus--x25 { --fx: 25%; }
  .focus--x30 { --fx: 30%; }
  .focus--x35 { --fx: 35%; }
  .focus--x40 { --fx: 40%; }
  .focus--x45 { --fx: 45%; }
  .focus--x50 { --fx: 50%; }
  .focus--x55 { --fx: 55%; }
  .focus--x60 { --fx: 60%; }
  .focus--x65 { --fx: 65%; }
  .focus--x70 { --fx: 70%; }
  .focus--x75 { --fx: 75%; }
  .focus--x80 { --fx: 80%; }
  .focus--x85 { --fx: 85%; }
  .focus--x90 { --fx: 90%; }
  .focus--x95 { --fx: 95%; }
  .focus--x100 { --fx: 100%; }
  .focus--y0 { --fy: 0%; }
  .focus--y5 { --fy: 5%; }
  .focus--y10 { --fy: 10%; }
  .focus--y15 { --fy: 15%; }
  .focus--y20 { --fy: 20%; }
  .focus--y25 { --fy: 25%; }
  .focus--y30 { --fy: 30%; }
  .focus--y35 { --fy: 35%; }
  .focus--y40 { --fy: 40%; }
  .focus--y45 { --fy: 45%; }
  .focus--y50 { --fy: 50%; }
  .focus--y55 { --fy: 55%; }
  .focus--y60 { --fy: 60%; }
  .focus--y65 { --fy: 65%; }
  .focus--y70 { --fy: 70%; }
  .focus--y75 { --fy: 75%; }
  .focus--y80 { --fy: 80%; }
  .focus--y85 { --fy: 85%; }
  .focus--y90 { --fy: 90%; }
  .focus--y95 { --fy: 95%; }
  .focus--y100 { --fy: 100%; }
  /* M18: the admin-managed hero images crossfade (js/hero.js toggles is-active) */
  .hero__images { position: absolute; inset: 0; z-index: -2; }
  .hero__images .hero__image { opacity: 0; transition: opacity 1.5s ease; }
  .hero__images .hero__image.is-active { opacity: 1; }
  @media (prefers-reduced-motion: reduce) {
    .hero__images .hero__image { transition: none; }
  }

  /* M18: the Instagram strip on the home page, photos only */
  .insta-grid { display: grid; gap: var(--space-md); grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); }
  .insta-grid img { inline-size: 100%; aspect-ratio: 1; object-fit: cover; border-radius: var(--radius-lg); display: block; }

  /* M22: the home page's « Ce qui se passe ici » and the two kinds of evening */
  .lede { font-size: var(--fs-1); max-inline-size: 40ch; }
  .home-more { display: flex; justify-content: flex-end; }

  /* ---------- M32: the About page as an editorial spread ---------- */
  /* Same words, re-set on a twelve-column grid from 900 px: a typographic
     opening, the group photo at the feature width, the mission as a poster,
     the values in three columns, a full-bleed band, two portraits
     and one button. Square corners on every picture here (D15.1). The two
     placements whose frame changes with the screen wear the .focus classes
     (the point kept in view); the values and the portraits are cut at 4:5.
     Full bleed comes from a section with no side padding, never from a viewport width
     (reset.css keeps the scrollbar gutter stable).
     2026-09-12: « Le lieu » (the group photo and its two paragraphs) is gone
     for good, by the User's own choice; the classes it alone used go with it. */
  .about .section { padding-block: 0; }
  .about > .section + .section { margin-block-start: var(--space-section); }
  /* M75.1: the mission band sits flush under the opening photo, the picture and the
     statement as one unit; the gap resumes under the band. Only when the photo is
     there: a browser without :has keeps the gap, which is the older look, not a break. */
  .about > .about-hero:has(.about-hero__media) + .about-mission { margin-block-start: 0; }
  /* Reviewed design (2026-09-12): the opening is the copy in the page container
     with the « En-tête » picture full width beneath it. The copy carries
     .container in the markup, so its width and gutter are the page's, the
     header's and the footer's. */
  .about-hero__copy { padding-block-start: var(--space-xl); display: grid; gap: var(--space-lg); justify-items: start; }
  .about-more { display: inline-flex; align-items: center; gap: var(--space-md); font-size: var(--fs--1); font-weight: 600; text-transform: uppercase; letter-spacing: .12em; text-decoration: none; color: inherit; margin-block-start: var(--space-md); }
  .about-more:hover .about-more__arrow { transform: translateY(0.25rem); }
  .about-more__arrow { transition: transform .3s ease; }
  .about-hero__media { margin-block-start: var(--space-xl); }
  .about-title { font-size: var(--fs-display); line-height: 1.02; letter-spacing: -0.02em; }
  .about-intro { font-size: var(--fs-1); max-inline-size: 36rem; display: grid; gap: var(--space-md); }
  .about-intro p { max-inline-size: none; }
  .about-heading { font-size: var(--fs-5); margin-block-end: var(--space-xl); }
  /* The mission band (reviewed design, 2026-09-12): sand across the whole window,
     square corners and no rule, with the heading and the statement in the page
     container, so the colour reaches both window edges while the words keep the
     page's left and right edges. The section wins its own padding back from
     .about .section, which zeroes it; the double class matches that specificity. */
  .about .about-mission { background: var(--color-surface); padding-block: clamp(3rem, 2rem + 3vw, 4rem); }  /* M75: 48 to 64 px, down from 96, so the band sits as one block among the others and the mission reads close to the photo above and the values below */
  .about-mission__inner { display: grid; gap: var(--space-lg); align-items: start; }
  .about-mission__title { font-family: var(--font-heading); font-weight: 700; font-size: var(--fs-5); line-height: 1.05; letter-spacing: -0.02em; }
  .about-mission__text { font-family: var(--font-body); font-size: var(--fs-1); display: grid; gap: var(--space-md); }
  .about-mission__text p { max-inline-size: none; }
  .about-photo { display: block; inline-size: 100%; object-fit: cover; border-radius: 0; }
  .about-photo--header { aspect-ratio: 4 / 3; }
  .about-photo--wide { aspect-ratio: 3 / 2; }
  .about-photo--portrait { aspect-ratio: 4 / 5; }
  .about-bleed { width: 100%; }
  .values, .hosts { display: grid; gap: var(--space-2xl) var(--space-lg); }
  /* M75: the title hangs 12 px under its picture and the paragraph 8 px under the title,
     so on a phone each caption reads as the picture's own and not the next one's */
  .value, .host { display: grid; gap: var(--space-xs); align-content: start; }
  .value h3, .host h3 { font-size: var(--fs-2); margin-block-start: var(--space-2xs); }
  .host__photo--empty { display: grid; place-items: center; background: var(--color-surface); color: var(--color-text-muted); }
  .host__photo--empty .logo-mark { inline-size: 3rem; block-size: auto; }
  .about-close { text-align: center; }
  @media (min-width: 900px) {
    .about-hero__copy { padding-block: var(--space-2xl) 0; }
    /* the mission band's two columns: the heading on the left of the container,
       the statement from the halfway line to the container's right edge */
    .about-mission__inner { grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--space-lg); }
    .about-mission__title { grid-column: 1 / span 5; }
    .about-mission__text { grid-column: 7 / span 6; }
    /* the opening picture: wide rather than tall on a big screen, and capped so a
       1920 px window does not turn it into a full page of photograph */
    .about-photo--header { aspect-ratio: 21 / 9; max-block-size: 72svh; }
    .about-photo--wide { aspect-ratio: 21 / 9; }
    .values { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .hosts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }

  /* M39.1: the contact page as the mockup draws it (ideas/local-design/contact/index.html): one
     two-column section from 700 px, the display title, the address as one accent line with
     an arrow, the two networks named beside their icons at the column's foot, and the picture
     in its arch, a fixed height per width with the point kept in view (the .focus classes) */
  .contact { display: grid; gap: 2.125rem; align-items: stretch; }
  .contact__info { display: flex; flex-direction: column; align-items: flex-start; }
  .contact__title { font-size: 4.375rem; line-height: 1.08; letter-spacing: -.055em; margin-block-end: 1.875rem; }
  .contact__intro { display: grid; gap: var(--space-md); margin-block-end: var(--space-lg); }
  .contact__email { display: inline-flex; align-items: center; gap: 1.375rem; max-inline-size: 100%; color: var(--color-accent); font-size: 1.4375rem; letter-spacing: -.04em; text-decoration: none; padding-block-end: .9375rem; border-block-end: 1px solid var(--color-accent); overflow-wrap: anywhere; }
  .contact__email:hover { text-decoration: none; }
  .contact__arrow { flex: 0 0 auto; transition: transform var(--dur-mid) var(--ease); }
  .contact__email:hover .contact__arrow { transform: translate(4px, -4px); }
  .social-row--named { padding-block-start: 1.6875rem; gap: 2rem; }
  .social-link--named { display: inline-flex; align-items: center; gap: .75rem; min-block-size: 44px; color: inherit; font-size: var(--fs--1); text-decoration: none; }
  .social-link--named .icon { inline-size: 1.5rem; block-size: 1.5rem; margin-inline-end: 0; color: var(--color-accent); }
  .social-link--named:hover { text-decoration: underline; text-underline-offset: .3em; }
  .contact__photo { margin: 0; block-size: 22.5rem; overflow: hidden; border-radius: 8.75rem 8.75rem 4px 4px; background: var(--color-surface); }
  .contact__photo img { display: block; inline-size: 100%; block-size: 100%; object-fit: cover; }
  .contact__photo--empty { display: grid; place-items: center; inline-size: 100%; block-size: 100%; color: var(--color-text-muted); }
  .contact__photo--empty .logo-mark { inline-size: 4rem; block-size: auto; }
  @media (min-width: 700px) {
    .contact { grid-template-columns: 1.04fr 1fr; column-gap: 6%; }
    .contact__info { padding-block: 1.875rem .75rem; }
    .contact__title { font-size: clamp(4.0625rem, 7.5vw, 6.75rem); margin-block-end: 3.3125rem; }
    .contact__email { font-size: clamp(1.1875rem, 2.15vw, 1.8125rem); gap: .9375rem; }
    .social-row--named { margin-block-start: auto; padding-block-start: 5rem; gap: 1.375rem; }
    .contact__photo { block-size: 27.5rem; border-radius: 10rem 10rem 4px 4px; }
  }
  @media (min-width: 900px) {
    .contact { column-gap: 8%; }
    .contact__email { gap: 1.625rem; }
    .social-row--named { gap: 2rem; }
    .contact__photo { block-size: 31rem; }
  }
  @media (min-width: 1500px) {
    .contact__info { padding-block-start: 2.8125rem; }
    .contact__photo { block-size: 35.625rem; }
  }
  @media (prefers-reduced-motion: reduce) {
    .contact__arrow { transition: none; }
    .contact__email:hover .contact__arrow { transform: none; }
  }

  /* M18: the one « Légal » page */
  .legal-toc ul { display: flex; flex-wrap: wrap; gap: var(--space-md); }
  .legal-section { scroll-margin-block-start: var(--space-xl); display: grid; gap: var(--space-md); }  /* M22: the bodies are not .prose, so the gap lives here */
  .legal-section h2, .legal-section h3 { margin-block-start: var(--space-lg); }
  .legal-section + .legal-section { margin-block-start: var(--space-2xl); padding-block-start: var(--space-xl); border-block-start: 1px solid color-mix(in oklab, var(--color-ink), transparent 85%); }

  /* event rows (M7): a month-grouped list, never a grid; the whole row is the link */
  .event-month { margin-block-start: var(--space-lg); font-size: var(--fs-1); }
  /* M23: a reading measure for the row. The category chip is aligned to the
     row's right edge, so the row's width is what sets how far it sits from the
     text: 40 rem keeps it near without cramping a long title (the User's call). */
  .event-list { display: grid; max-inline-size: 40rem; }
  .event-row { border-block-end: var(--border); }
  .event-row__link {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    padding-block: var(--space-md);
    color: var(--color-text);
    text-decoration: none;
    border-radius: var(--radius-sm);
    transition: color var(--dur-fast) var(--ease);
  }
  .event-row__link:hover .event-row__title,
  .event-row__link:focus-visible .event-row__title { color: var(--color-accent); }
  .event-row__link:hover { color: var(--color-accent); }
  .event-row__img {
    flex: 0 0 auto;
    inline-size: 7rem;   /* M30: the 16:9 thumbnail rendition (480 by 270) */
    block-size: 3.9375rem;
    object-fit: cover;
    border-radius: var(--radius-md);
    background: var(--color-surface);
  }
  .event-row__img--empty {
    display: grid;
    place-items: center;
    border: var(--border);
    color: var(--color-text-muted);
  }
  .event-row__img--empty .logo-mark { inline-size: 1.75rem; block-size: auto; }
  /* M23: flex: 1 so the text column fills the row whatever the title's length,
     which is what puts every category chip in the same place down the list */
  .event-row__text { flex: 1; display: grid; gap: var(--space-2xs); min-inline-size: 0; }
  .event-row__when { color: var(--color-text); font-weight: 500; font-size: var(--fs--1); }
  /* M23: base.css balances headings, which centres a wrapped title well short
     of the column and leaves the right-aligned chip stranded past it; a row
     title fills its line instead, so the text wraps where the chip sits */
  .event-row__title { font-size: var(--fs-1); color: var(--color-text); text-wrap: pretty; margin-block-start: -.2rem; transition: color var(--dur-fast) var(--ease); }
  /* 2026-09-13 review: on phones the row reads better with a square-ish thumbnail
     matching the four text lines beside it */
  @media (max-width: 767px) {
    .event-row__img { block-size: 7.25rem; }
  }
  @media (min-width: 768px) {
    .event-row__img { inline-size: 9rem; block-size: 5.0625rem; }
  }
  /* M22: the « En bref » line and the meta line (price, category, places) */
  .event-row__summary { color: var(--color-text); line-height: 1.3; }
  .event-row__meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2xs) var(--space-sm); color: var(--color-text-muted); font-size: var(--fs--1); }
  .event-row__price { color: var(--color-text); font-weight: 500; }
  .event-row__host { color: var(--color-text); font-weight: 500; }  /* M30: « Par <organisateur> » */
  /* M23: the category chip flush right, the same column down the whole list */
  .event-row__cat { margin-inline-start: auto; }

  /* M26: a series shows once a month; its dates sit under the row as square
     buttons, each its own evening. The event page uses the same button. */
  .event-row__dates,
  .event-series__dates { display: flex; flex-wrap: wrap; gap: var(--space-2xs); padding-block-end: var(--space-md); }
  .event-row__dates { padding-inline-start: 7.6rem; margin-block-start: calc(-1 * var(--space-sm)); }
  .event-series { margin-block-start: var(--space-md); }
  .event-series__label { color: var(--color-text-muted); font-size: var(--fs--1); margin-block-end: var(--space-2xs); }
  .event-date {
    display: grid;
    justify-items: center;
    align-content: center;
    gap: 1px;
    min-inline-size: 3.25rem;
    min-block-size: 3.25rem;
    padding: var(--space-2xs);
    border: 1px solid var(--color-control-border);
    border-radius: var(--radius-sm);
    color: var(--color-text);
    text-decoration: none;
    transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
  }
  .event-date:hover, .event-date:focus-visible { color: var(--color-accent); border-color: var(--color-accent); }
  .event-date__wd, .event-date__mo { font-size: var(--fs--1); color: var(--color-text-muted); line-height: 1.1; }
  .event-date__day { font-size: var(--fs-1); font-weight: 500; line-height: 1.1; }
  .event-date__state { font-size: var(--fs--1); color: var(--color-text-muted); line-height: 1.1; }
  /* M28 rider: the date being read is the marked one, on the event page as in
     the list's rows. The border carries it, so it reads without colour alone. */
  .event-date--now { background: var(--color-surface); font-weight: 500; border-color: var(--color-text); }
  .event-date--now .event-date__wd, .event-date--now .event-date__mo { color: var(--color-text); }
  @media (max-width: 767px) {
    .event-row__dates { padding-inline-start: 0; }
  }
  /* ---------- M38: the events page in the staff list's shape ---------- */
  /* The staff list (admin.css, M36 and M37) mapped onto the public tokens: its
     paper is --color-paper, its hairline --color-border, its soft fill
     --color-surface, its quiet ink --color-text-muted. */
  .event-tools { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-xs) var(--space-sm); }
  .event-tools__search { flex: 1 1 14rem; min-inline-size: 0; }
  .event-tools__select { flex: 0 1 14rem; max-inline-size: 14rem; }  /* the recipe sets width: 100%; the flex basis sizes it here */
  .event-tools__clear { font-size: var(--fs--1); }
  @media (max-width: 440px) { .event-tools__select { flex: 1 1 100%; max-inline-size: none; } }
  /* M58: the live search hides what does not match, and these two boxes each
     set a display of their own, which outranks the browser's own [hidden] rule
     (the M25 lesson from the staff side). */
  .event-list[hidden], .event-tabs ~ .event-month[hidden] { display: none; }
  .event-tabs { display: flex; flex-wrap: wrap; gap: 0 var(--space-lg); border-block-end: 1px solid var(--color-border); }
  .event-tabs__tab { display: inline-flex; align-items: center; gap: var(--space-2xs); min-block-size: 44px; padding-block: var(--space-sm); border-block-end: 2px solid transparent; margin-block-end: -1px; color: var(--color-text-muted); font-size: var(--fs--1); font-weight: 500; text-decoration: none; }
  .event-tabs__tab:hover { color: var(--color-text); }
  .event-tabs__tab[aria-current="page"] { color: var(--color-accent); border-block-end-color: var(--color-accent); }
  .event-tabs__count { padding: .1rem .35rem; border-radius: var(--radius-sm); background: var(--color-surface); color: var(--color-text); font-size: .7rem; font-weight: 500; line-height: 1.3; }
  @media (max-width: 440px) { .event-tabs { gap: 0 var(--space-md); } }
  /* M59: the events list when nothing answers the filters. It takes the place
     of the cards, in the cards' own paper, so an empty tab reads as an answer
     rather than a blank page. Never animated: the as-you-type search shows and
     hides it on every keystroke. */
  .event-empty { display: grid; justify-items: center; gap: var(--space-2xs); margin-block-start: var(--space-lg); padding: var(--space-2xl) var(--space-lg); border: var(--border); border-radius: var(--radius-md); background: var(--color-paper); text-align: center; }
  .event-empty__mark { display: block; margin-block-end: var(--space-md); color: var(--color-ochre); opacity: .5; }
  .event-empty__mark .logo-mark { inline-size: 1.75rem; block-size: auto; }
  .event-empty__title { margin: 0; font-family: var(--font-heading); font-size: var(--fs-1); font-weight: 500; line-height: 1.25; text-wrap: balance; }
  .event-empty__text { max-inline-size: 38ch; margin: 0; color: var(--color-text-muted); font-size: var(--fs--1); line-height: 1.7; text-wrap: pretty; }
  .event-empty__action { margin-block-start: var(--space-lg); }
  @media (max-width: 440px) { .event-empty { padding: var(--space-xl) var(--space-md); } }
  .event-list--cards { max-inline-size: none; gap: var(--space-sm); }
  .event-tabs ~ .event-month { display: flex; align-items: center; gap: var(--space-sm); margin-block-start: var(--space-lg); font-family: var(--font-body); font-size: var(--fs--1); font-weight: 500; color: var(--color-text-muted); }
  .event-tabs ~ .event-month::after { content: ""; flex: 1; block-size: 1px; background: var(--color-border); }
  .event-tabs + .event-month { margin-block-start: var(--space-xs); }
  .event-row--card { border-block-end: 0; padding: var(--space-md); background: var(--color-paper); border: var(--border); border-radius: var(--radius-md); }
  .event-row--card .event-row__link { padding-block: 0; }
  .event-row__date { flex: 0 0 auto; display: grid; justify-items: center; padding-inline-end: var(--space-sm); border-inline-end: 1px solid var(--color-border); text-align: center; line-height: 1.15; font-size: .65rem; letter-spacing: .08em; text-transform: uppercase; color: var(--color-text); }
  .event-row__date-day { display: block; font-family: var(--font-heading); font-weight: 600; font-size: var(--fs-2); letter-spacing: 0; text-transform: none; line-height: 1.1; }
  .event-row--card .event-row__dates { padding-inline-start: calc(7rem + 3.125rem + 2 * var(--space-md)); padding-block-end: 0; margin-block-start: var(--space-xs); }
  @media (min-width: 768px) {
    .event-row--card { padding: var(--space-lg) var(--space-xl); }
    .event-row--card .event-row__img { inline-size: 10rem; block-size: 5.625rem; }
    .event-row__date { padding-inline-end: var(--space-md); }
    .event-row--card .event-row__dates { padding-inline-start: calc(10rem + 3.125rem + 2 * var(--space-md)); }
  }
  @media (max-width: 440px) {
    .event-row--card { padding: var(--space-sm); }
    .event-row--card .event-row__dates { padding-inline-start: 0; }
  }
  .chip--soon { color: var(--color-accent); }
  .chip {
    display: inline-block;
    justify-self: start;
    padding: 0 var(--space-sm);
    border-radius: var(--radius-pill);
    border: 1px solid currentColor;
    font-size: var(--fs--1);
    font-weight: 600;
    letter-spacing: .02em;
  }
  .chip--soldout { color: var(--color-accent); }
  .chip--cancelled { color: var(--color-text-muted); text-decoration: line-through; }
  .registration-list__address { color: var(--color-text-muted); font-size: var(--fs--1); }

  /* inline social icons (M7): drawn in currentColor, sized to the text line */
  .icon { inline-size: 1em; block-size: 1em; vertical-align: -.125em; margin-inline-end: .4em; }
  .social-link { white-space: nowrap; }

  /* icon-only social links (M10): one row, each a 44 px tap target */
  .social-row { display: flex; flex-wrap: wrap; gap: var(--space-xs); align-items: center; }
  .social-link--icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 44px;
    min-block-size: 44px;
  }
  .social-link--icon .icon { inline-size: 1.75rem; block-size: 1.75rem; margin-inline-end: 0; vertical-align: middle; }

  .event-meta { display: grid; gap: var(--space-2xs); color: var(--color-text-muted); }
  .event-meta__when { color: var(--color-text); }

  /* forms */
  .field { display: grid; gap: var(--space-2xs); }
  .field label { font-weight: 600; }
  .field :where(input:not([type="checkbox"], [type="radio"]), textarea, select), .event-tools :where(input, select) {
    min-block-size: 44px;
    padding-inline: var(--space-md);
    border: 1px solid var(--color-control-border);  /* M22: 3.22:1, WCAG 1.4.11 */
    border-radius: var(--radius-sm);
    background: #FFFDF8;
    appearance: none;
    width: 100%;
    font-size: max(1rem, var(--fs-0));
  }
  .field :where(input, textarea):focus-visible, .event-tools :where(input, select):focus-visible { border-color: var(--color-accent); }
  /* M58: the month select draws its own chevron. The recipe just above sets
     appearance: none, which takes the browser's arrow away, and the User read
     the bare box as a label rather than a menu. Two small gradients make the V,
     so there is no image file and no extra element; the box keeps room for it
     at the end. This rule sits after the recipe on purpose: the recipe's
     background shorthand would wipe an image set before it. */
  .event-tools__select {
    padding-inline-end: calc(var(--space-md) + 1.25rem);
    background-image:
      linear-gradient(45deg, transparent 50%, currentColor 50%),
      linear-gradient(135deg, currentColor 50%, transparent 50%);
    /* whole pixels, the two halves one pixel over each other: at fractional
       sizes the browser rounds them apart and the V shows a seam */
    background-position: right calc(var(--space-md) + 6px) top 50%, right var(--space-md) top 50%;
    background-size: 7px 7px;
    background-repeat: no-repeat;
  }
  .field [aria-invalid="true"] { border-color: var(--color-danger); }
  .field--choice {
    grid-template-columns: auto 1fr;
    align-items: center;
    column-gap: var(--space-sm);
  }
  .field--choice input { inline-size: 1.25rem; block-size: 1.25rem; accent-color: var(--color-accent); }
  .field--choice label { font-weight: 500; }
  .field--choice .field__help, .field--choice .field__error { grid-column: 2; }
  .field__error { color: var(--color-danger); font-size: var(--fs--1); }
  .field__help { color: var(--color-text-muted); font-size: var(--fs--1); }
  /* interest lists (M6): a compact vertical checkbox list, 44 px rows */
  .field--choices { border: 0; padding: 0; margin: 0; min-inline-size: 0; gap: 0; }
  .field--choices legend { font-weight: 600; padding: 0; margin-block-end: var(--space-2xs); }
  .choice {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: var(--space-sm);
    align-items: center;
    min-block-size: 44px;
    font-weight: 500;
    cursor: pointer;
  }
  .choice input { inline-size: 1.25rem; block-size: 1.25rem; accent-color: var(--color-accent); }
  .choice small { grid-column: 2; color: var(--color-text-muted); font-size: var(--fs--1); }
  .form__error { color: var(--color-danger); }
  .form-row { display: flex; flex-wrap: wrap; gap: var(--space-sm); align-items: end; }
  .form-row .field { flex: 1 1 16rem; }
  .form-row .field--choices { flex-basis: 100%; }
  .form-stack { display: grid; gap: var(--space-lg); }
  .form-actions { display: flex; flex-wrap: wrap; gap: var(--space-sm); align-items: center; }
  .form-actions:empty { display: none; }
  .form-note { color: var(--color-text-muted); font-size: var(--fs--1); }
  .btn--danger { background: var(--color-danger); }
  .btn--danger:hover { background: color-mix(in oklab, var(--color-danger), #000 12%); }

  /* inline status / alerts (django messages, allauth notes, form-level errors) */
  .messages { margin-block-start: var(--space-lg); display: grid; gap: var(--space-sm); }
  /* M47: with js/toast.js running, the strip is replaced by the cards */
  html.js .messages { display: none; }
  .alert {
    background: var(--color-surface);
    border: var(--border);
    border-inline-start: 4px solid var(--color-success);
    border-radius: var(--radius-sm);
    padding: var(--space-sm) var(--space-md);
    max-inline-size: none;
  }
  .alert--error { border-inline-start-color: var(--color-danger); }
  .alert--error p { max-inline-size: none; }
  .alert--warning { border-inline-start-color: var(--color-ochre-deep); }
  .badge {
    display: inline-block;
    margin-inline-start: var(--space-xs);
    padding: 0 var(--space-xs);
    border-radius: var(--radius-pill);
    background: var(--color-surface);
    border: var(--border);
    font-size: var(--fs--1);
    font-weight: 500;
  }

  /* M44: the event page in the mock's shape (project/milestone-contexts/M44-brief.md, section A).
     The DOM order is the phone order; from 900 px the areas put the panel on the right, pinned
     under the sticky header. The photo is the thumb's window (16:9) at the story's width. */
  .event-back { font-size: var(--fs--1); color: var(--color-text-muted); margin-block-end: var(--space-lg); }
  .event-back a { display: inline-flex; align-items: center; gap: var(--space-xs); min-block-size: 32px; text-decoration: none; }
  .event-back a:hover { color: var(--color-accent); }
  .event-head { display: grid; gap: var(--space-sm); margin-block-end: var(--space-xl); }
  .event-head h1 { font-size: clamp(2.3rem, 1.6rem + 3vw, 3.75rem); letter-spacing: -.03em; line-height: 1.1; text-wrap: balance; max-inline-size: 18ch; }
  .event-kind { margin: 0; }
  .event-kind .chip--cat { display: inline-flex; align-items: center; gap: var(--space-xs); padding: 0; border: 0; font-size: var(--fs--1); font-weight: 600; letter-spacing: .02em; }
  .event-kind .chip--cat::before { content: ""; inline-size: 6px; block-size: 6px; border-radius: 50%; background: currentColor; }
  .event-layout { display: grid; gap: var(--space-lg); align-items: start; }
  .event-poster { margin: 0; overflow: hidden; border-radius: var(--radius-md); background: var(--color-surface); }
  .event-poster img { display: block; inline-size: 100%; block-size: auto; aspect-ratio: 16 / 9; object-fit: cover; object-position: center; }
  .event-booking { display: grid; gap: var(--space-md); }
  .booking { display: grid; gap: var(--space-md); padding: var(--space-lg); background: var(--color-paper); border: var(--border); border-radius: var(--radius-md); box-shadow: 0 7px 20px rgb(66 51 32 / .03); }
  .booking .event-meta { gap: var(--space-md); color: var(--color-text-muted); }
  .booking__when { display: flex; align-items: center; gap: var(--space-md); }
  .date-tile { flex: 0 0 auto; inline-size: 4rem; display: grid; text-align: center; border: var(--border); border-radius: var(--radius-sm); overflow: hidden; padding-block-end: var(--space-xs); margin: 0; line-height: 1.2; color: var(--color-text); }
  .date-tile__mo { background: var(--color-surface); font-size: .65rem; letter-spacing: .1em; text-transform: uppercase; padding-block: 3px; }
  .date-tile__day { font-family: var(--font-heading); font-weight: 600; font-size: var(--fs-3); line-height: 1.2; margin-block-start: var(--space-2xs); }
  .date-tile__wd { font-size: .55rem; letter-spacing: .07em; text-transform: uppercase; margin-block-start: 3px; }
  .booking__dates { display: grid; gap: var(--space-2xs); }
  .booking__date { color: var(--color-text); font-weight: 500; }
  .booking__hours { color: var(--color-text); font-size: var(--fs--1); }
  .booking .registration { padding-block: 0; border-block: 0; }
  .booking .btn { inline-size: 100%; border-radius: var(--radius-sm); justify-content: space-between; padding-inline: var(--space-lg); }
  .booking .btn::after { content: "↗"; font-size: 1.1em; }
  .booking .btn--ghost::after { content: none; }

  /* M61: the panel redrawn from ideas/event-contribution. The venue sits in the date
     block, the run's dates fold away, the picker is full-width rows, and one summary
     line states what is about to be charged. */
  .booking__place, .booking .event-host { color: var(--color-text-muted); font-weight: 400; font-size: var(--fs--1); }
  .booking__note { color: var(--color-text-muted); font-size: var(--fs--1); }

  .booking__dates-list { container-type: inline-size; margin-block: var(--space-md); padding-block-end: var(--space-md); border-block-end: var(--border); }
  .booking__dates-list > summary { display: flex; align-items: center; gap: var(--space-xs); min-block-size: 44px; cursor: pointer; list-style: none; font-size: var(--fs--1); font-weight: 500; }
  .booking__dates-list > summary::-webkit-details-marker { display: none; }
  .booking__dates-list > summary::before { content: ""; inline-size: 7px; block-size: 7px; flex: 0 0 auto; border-inline-end: 1.5px solid currentColor; border-block-end: 1.5px solid currentColor; transform: rotate(-45deg); transition: transform var(--dur-fast) var(--ease); }
  .booking__dates-list[open] > summary::before { transform: rotate(45deg) translate(-1px, -1px); }
  .booking__dates-count { margin-inline-start: auto; color: var(--color-text-muted); font-weight: 400; }
  .booking__months { display: grid; padding-block-start: var(--space-xs); }
  .booking__month { display: grid; grid-template-columns: 4.75rem minmax(0, 1fr); align-items: center; gap: var(--space-sm); padding-block: var(--space-xs); border-block-start: var(--border); }
  .booking__month:first-child { border-block-start: 0; }
  .booking__month-label { color: var(--color-text-muted); font-size: .65rem; font-weight: 600; letter-spacing: .045em; text-transform: uppercase; white-space: nowrap; }
  .booking__month-dates { display: grid; grid-template-columns: repeat(5, 44px); justify-content: start; gap: var(--space-2xs); }
  .booking__month .event-date { min-inline-size: 0; inline-size: 44px; min-block-size: 44px; padding: var(--space-2xs) 2px; border-color: transparent; background: var(--color-surface); }
  .booking__month .event-date__mo { display: none; }
  .booking__month .event-date__wd { font-size: .55rem; letter-spacing: .04em; text-transform: uppercase; }
  .booking__month .event-date__day { font-size: var(--fs-0); font-variant-numeric: tabular-nums; }
  .booking__month .event-date__state { font-size: .55rem; letter-spacing: .03em; text-transform: uppercase; }
  .booking__month .event-date--now { background: var(--color-paper); border-color: var(--color-text); box-shadow: inset 0 0 0 1px var(--color-text); }
  .booking__month .event-date--full { color: var(--color-text-muted); }
  .booking__month .event-date--full .event-date__day { text-decoration: line-through; }
  @container (max-width: 320px) {
    .booking__month { grid-template-columns: minmax(0, 1fr); gap: var(--space-2xs); }
  }

  .tiers { --tiers-ink: #695037; --tiers-tint: #F0E5D5; --tiers-hover: #F9F1E5; --tiers-rest: #D7CBBC; --tiers-lift: #C7B59F; --tiers-gap: .625rem; border: 0; padding: 0; margin: 0; min-inline-size: 0; display: grid; }  /* M83: the colours of ideas/contribution-clickable.html, kept local to the picker */
  .tiers__legend { font-family: var(--font-heading); font-size: var(--fs-2); font-weight: 700; line-height: 1.2; letter-spacing: -.02em; padding: 0; }
  .tiers__intro { color: var(--color-text-muted); font-size: var(--fs--1); line-height: 1.6; margin-block: var(--space-xs) var(--space-md); }
  .tiers__choices { display: grid; gap: var(--tiers-gap); }
  .tiers__legend + .tiers__choices { margin-block-start: var(--space-md); }  /* M81.2: a contribution evening has no intro line, so the heading keeps the same gap the intro gave */
  .tiers__option, .tiers__open { position: relative; display: grid; cursor: pointer; min-inline-size: 0; -webkit-tap-highlight-color: transparent; }
  .tiers__open { margin-block-start: var(--tiers-gap); }
  .tiers input[type="radio"] { position: absolute; inline-size: 1px; block-size: 1px; opacity: 0; }
  .tiers__row { display: grid; grid-template-columns: 21px auto minmax(0, 1fr); align-items: center; gap: var(--space-sm); min-block-size: 5rem; padding: .875rem; background: var(--color-paper); border: 1px solid var(--color-control-border); border-radius: var(--radius-sm); box-shadow: 0 3px 0 var(--tiers-rest), 0 4px 8px rgb(66 51 32 / .035); transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease); }
  .tiers--ticket .tiers__row { grid-template-columns: 21px minmax(0, 1fr) auto; }
  .tiers__open .tiers__row { grid-template-columns: 21px minmax(0, 110px) minmax(0, 1fr); }
  .tiers__radio { inline-size: 21px; block-size: 21px; border: 1.5px solid var(--color-control-border); border-radius: 50%; background: var(--color-paper); display: grid; place-items: center; }
  .tiers__radio::after { content: ""; inline-size: 9px; block-size: 9px; border-radius: 50%; background: var(--tiers-ink); transform: scale(0); transition: transform var(--dur-fast) var(--ease); }
  @media (hover: hover) {
    .tiers__option:hover .tiers__row, .tiers__open:hover .tiers__row { background: var(--tiers-hover); border-color: var(--tiers-ink); transform: translateY(-1px); box-shadow: 0 4px 0 var(--tiers-lift), 0 6px 12px rgb(66 51 32 / .05); }
  }
  .tiers__option:active .tiers__row, .tiers__open:active .tiers__row { transform: translateY(2px); box-shadow: 0 1px 0 var(--tiers-lift); }
  .tiers input:checked + .tiers__row { background: var(--tiers-tint); border-color: var(--tiers-ink); box-shadow: inset 0 0 0 1px var(--tiers-ink), 0 1px 0 var(--tiers-lift); transform: translateY(2px); }
  .tiers input:checked + .tiers__row .tiers__radio { border-color: var(--tiers-ink); }
  .tiers input:checked + .tiers__row .tiers__radio::after { transform: scale(1); }
  .tiers input:focus-visible + .tiers__row { outline: 2px solid var(--color-text); outline-offset: 5px; }
  .tiers__amount { font-size: var(--fs-2); font-weight: 500; line-height: 1.2; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
  .tiers__name { font-weight: 500; }
  .tiers--contribution .tiers__row > .tiers__name, .tiers__open .tiers__name { font-size: var(--fs--1); font-weight: 400; line-height: 1.4; text-align: end; }
  .tiers--ticket .tiers__row > .tiers__name { display: grid; gap: var(--space-2xs); }
  .tiers--ticket .tiers__row > .tiers__name small { font-size: var(--fs--1); font-weight: 400; line-height: 1.4; color: var(--color-text-muted); }
  .tiers__option--full { cursor: not-allowed; }
  .tiers__option--full .tiers__row, .tiers__option--full:hover .tiers__row, .tiers__option--full:active .tiers__row { background: var(--color-surface); border-color: var(--color-control-border); color: var(--color-text-muted); box-shadow: none; transform: none; }
  .tiers__option--full .tiers__amount { text-decoration: line-through; font-size: var(--fs-1); }
  .tiers__option--full .tiers__row > .tiers__name small { display: inline-block; border: 1px solid var(--color-control-border); border-radius: 3px; padding: 1px 6px; }
  .tiers__field { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: baseline; font-size: var(--fs-2); font-weight: 500; line-height: 1.2; letter-spacing: -.02em; font-variant-numeric: tabular-nums; cursor: text; }
  .tiers__field input { inline-size: 4ch; max-inline-size: 100%; min-inline-size: 4ch; justify-self: start; padding: 0; border: 0; border-radius: 0; box-shadow: 0 1px 0 var(--color-control-border); background: transparent; color: inherit; font: inherit; letter-spacing: inherit; outline: none; }  /* M85: 4ch keeps the underline visible when the box is empty */
  .tiers__field input:focus { box-shadow: 0 2px 0 var(--tiers-ink); }
  @supports (field-sizing: content) { .tiers__field input { field-sizing: content; inline-size: auto; } }
  .tiers__help { font-size: var(--fs--1); line-height: 1.6; color: var(--color-text-muted); margin-block-start: var(--space-xs); }
  @media (prefers-reduced-motion: reduce) { .tiers__row, .tiers__radio::after { transition: none; } }

  .booking__form { display: grid; }
  .booking__summary { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-sm); font-size: var(--fs--1); margin-block-start: var(--space-md); padding-block-start: var(--space-md); border-block-start: var(--border); }
  .booking__summary strong { font-size: var(--fs-1); font-weight: 500; font-variant-numeric: tabular-nums; }
  .booking__summary small { font-size: .7rem; font-weight: 400; color: var(--color-text-muted); }
  .booking__form .btn { margin-block-start: var(--space-sm); }
  .booking__next { color: var(--color-text-muted); font-size: .8rem; line-height: 1.5; margin-block-start: var(--space-xs); }
  .booking .registration .form-note:first-of-type { margin-block-start: var(--space-md); padding-block-start: var(--space-md); border-block-start: var(--border); }
  /* M65: the dialog card shared by the registration dialog (booking_form.html) and the account
     page's cancellation dialog (profile.css). The panel's paper, its hairline, the large radius,
     a deep soft shadow, the footer's ink at half strength and a faint blur behind it. Under 600px
     it becomes a sheet at the foot of the screen with only its top corners rounded, rising in the
     mid duration; it does not move for someone who asked for less motion. The button and the
     beats never scroll: three beats fit a 390px phone with room to spare. */
  .dialog-card { inline-size: min(26rem, calc(100vw - 2rem)); max-block-size: calc(100svh - 3rem); overflow-y: auto; margin: auto; padding: 2rem 2rem 1.6rem; border: var(--border); border-radius: var(--radius-lg); background: var(--color-paper); color: var(--color-text); box-shadow: 0 24px 60px rgb(33 28 24 / .22), var(--shadow-2); }
  .dialog-card::backdrop { background: rgb(33 28 24 / .52); backdrop-filter: blur(2px); }
  .dialog-card[open] { animation: dialog-rise var(--dur-mid) var(--ease); }
  .dialog-card[open]::backdrop { animation: dialog-fade var(--dur-mid) var(--ease); }
  @keyframes dialog-rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
  @keyframes dialog-fade { from { opacity: 0; } to { opacity: 1; } }
  @media (max-width: 600px) {
    .dialog-card { inline-size: 100vw; max-inline-size: none; margin: auto 0 0; border-inline: 0; border-block-end: 0; border-radius: var(--radius-lg) var(--radius-lg) 0 0; padding: 1.6rem 1.35rem calc(1.2rem + env(safe-area-inset-bottom)); }
    @keyframes dialog-rise { from { opacity: 1; transform: translateY(100%); } to { transform: none; } }
  }
  @media (prefers-reduced-motion: reduce) { .dialog-card[open], .dialog-card[open]::backdrop { animation: none; } }
  /* the registration dialog's three beats (draft D2 and D3; the prototype ideas/register-consent) */
  .consent-card { max-inline-size: 26rem; margin-inline: auto; padding: 2rem 2rem 1.6rem; border: var(--border); border-radius: var(--radius-lg); background: var(--color-paper); box-shadow: var(--shadow-2); }  /* the plain page's card: the same paper without the dialog chrome */
  .consent-dialog__eyebrow { margin: 0 0 var(--space-sm); font-size: .72rem; font-weight: 500; letter-spacing: .12em; text-transform: uppercase; color: var(--color-text-muted); }
  .consent-dialog__title { margin: 0 0 var(--space-2xs); font-size: var(--fs-2); }
  .consent-dialog__when { margin: 0 0 var(--space-lg); font-size: var(--fs--1); color: var(--color-text-muted); }
  .consent-dialog__amount { display: grid; grid-template-columns: 1fr auto; gap: var(--space-2xs) var(--space-md); align-items: baseline; padding: var(--space-md) 0; border-block: var(--border); }
  .consent-dialog__label { font-size: var(--fs--1); }
  .consent-dialog__figure { font-size: var(--fs-1); font-weight: 500; font-variant-numeric: tabular-nums; text-align: end; }
  .consent-dialog__figure small { margin-inline-start: .2em; font-size: .7rem; font-weight: 400; color: var(--color-text-muted); }
  .consent-dialog__note { grid-column: 1 / -1; margin: 0; font-size: .8rem; color: var(--color-text-muted); }
  .consent-dialog__policy { margin: var(--space-lg) 0; font-size: var(--fs--1); line-height: 1.6; color: var(--color-text-muted); }
  .consent-dialog__policy a { color: var(--color-accent); text-decoration: underline; text-underline-offset: 3px; white-space: nowrap; }
  .consent-dialog .btn { inline-size: 100%; min-block-size: 48px; margin-block-start: 0; border-radius: var(--radius-pill); justify-content: center; }  /* undoes .booking .btn's square corners, spread and arrow for the dialog's one button */
  .consent-dialog .btn::after { content: none; }
  .consent-dialog__later { display: block; inline-size: 100%; margin-block-start: var(--space-sm); padding: .55rem; background: none; border: 0; font: inherit; font-size: var(--fs--1); color: var(--color-text-muted); cursor: pointer; text-align: center; text-decoration: underline; text-underline-offset: 3px; text-decoration-color: color-mix(in srgb, currentColor 45%, transparent); }
  .consent-dialog__later:hover { color: var(--color-text); }
  .consent-dialog__later:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; border-radius: var(--radius-sm); }
  .event-body { min-inline-size: 0; }
  .event-section { padding-block-start: var(--space-xl); }
  .event-section h2, .event-highlight__title { font-size: var(--fs-2); letter-spacing: -.03em; margin-block-end: var(--space-md); }
  .event-highlight { display: flex; gap: var(--space-md); margin-block-start: var(--space-xl); padding: var(--space-lg); background: var(--color-surface); border-radius: var(--radius-sm); }
  .event-highlight__mark { font-size: 1.9rem; line-height: 1; color: var(--color-success); }
  .event-highlight__inner { display: grid; gap: var(--space-xs); min-inline-size: 0; }
  .event-highlight__title { font-size: var(--fs-1); margin-block-end: var(--space-2xs); }
  .event-highlight__body { font-size: var(--fs--1); color: var(--color-text-muted); line-height: 1.8; display: grid; gap: var(--space-xs); }
  .event-schedule__rows { margin: 0; display: grid; }
  .event-schedule__row { display: grid; grid-template-columns: 8rem 1fr; gap: var(--space-md); padding-block: var(--space-md); border-block-start: var(--border); }
  .event-schedule__row dt { color: var(--color-accent); font-size: var(--fs--1); font-variant-numeric: tabular-nums; }
  .event-schedule__row dd { margin: 0; display: grid; gap: var(--space-2xs); font-size: var(--fs--1); }
  .event-schedule__row dd strong { font-weight: 500; font-size: var(--fs-0); }
  .event-schedule__row dd span { color: var(--color-text-muted); }
  /* M45: a text table, two columns of equal weight (project/milestone-contexts/M45-brief.md, section C4) */
  .event-table__rows { margin: 0; display: grid; }
  .event-table__row { display: grid; grid-template-columns: minmax(6rem, .7fr) minmax(0, 1fr); gap: var(--space-md); padding-block: var(--space-md); border-block-start: var(--border); }
  .event-table__row dt, .event-table__row dd strong { color: var(--color-text); font-weight: 500; font-size: var(--fs-0); line-height: 1.5; }
  .event-table__row dd { margin: 0; display: grid; gap: var(--space-2xs); font-size: var(--fs--1); }
  .event-table__row dd span { color: var(--color-text-muted); }
  /* M48: a photo, a silent loop and a video inside the story. Each fills the
     story column and keeps its own shape: a story photo has no fixed frame, so
     there is no crop, no focus point and no zoom. The caption is the small
     muted type the page already uses for its notes. */
  .event-media { display: grid; gap: var(--space-md); }
  .event-figure { margin: 0; display: grid; gap: var(--space-sm); }
  .event-figure img { display: block; inline-size: 100%; block-size: auto; border-radius: var(--radius-md); background: var(--color-surface); }
  .event-figure figcaption, .event-figure__caption { font-size: var(--fs--1); color: var(--color-text-muted); line-height: 1.7; margin: 0; }
  .event-loop, .event-video, .event-video__player { inline-size: 100%; block-size: auto; display: block; border-radius: var(--radius-md); background: var(--color-surface); }
  .event-video { position: relative; overflow: hidden; }
  .event-video__button { display: block; inline-size: 100%; padding: 0; border: 0; background: var(--color-surface); cursor: pointer; border-radius: var(--radius-md); overflow: hidden; }
  .event-video__still { display: block; inline-size: 100%; block-size: auto; }
  .event-video__mark { position: absolute; inset-block-start: 50%; inset-inline-start: 50%; translate: -50% -50%; inline-size: 4rem; block-size: 4rem; display: grid; place-items: center; border-radius: 50%; background: var(--color-ink); color: var(--color-cream); font-size: 1.25rem; padding-inline-start: .2rem; }
  .event-video__player { aspect-ratio: auto; }
  .event-video--playing { background: var(--color-ink); }
  /* M48.1: with the sticky phone bar gone, this is the phone's second offer of the action, at the foot of the story */
  .event-end { margin-block-start: var(--space-xl); padding-block-start: var(--space-lg); border-block-start: var(--border); }
  .event-end .btn { inline-size: 100%; border-radius: var(--radius-sm); }
  .event-end form { display: contents; }
  @media (min-width: 900px) {
    .event-layout { grid-template-columns: minmax(0, 1.8fr) minmax(19rem, 1fr); grid-template-areas: "poster booking" "body booking"; gap: var(--space-xl); column-gap: clamp(var(--space-xl), 4vw, 3.5rem); }
    .event-layout:not(.event-layout--poster) { grid-template-areas: "body booking"; }
    .event-poster { grid-area: poster; }
    .event-booking { grid-area: booking; position: sticky; inset-block-start: calc(var(--header-h) + var(--space-md)); }
    .event-body { grid-area: body; }
    .event-end { display: none; }
  }
  @media (min-width: 900px) and (max-height: 700px) { .event-booking { position: static; } }
  @media (max-width: 480px) { .event-schedule__row { grid-template-columns: 7rem 1fr; gap: var(--space-sm); } .event-table__row { grid-template-columns: minmax(4.5rem, .7fr) 1fr; gap: var(--space-sm); } .event-highlight { padding: var(--space-md); gap: var(--space-sm); } }
  .event-summary { font-size: var(--fs-1); color: var(--color-text-muted); }
  .event-places { color: var(--color-accent); font-weight: 600; }
  /* the registration state as a card (the .alert pattern), success for confirmed, accent for a hold */
  .state { background: var(--color-surface); border: var(--border); border-inline-start: 4px solid var(--color-text-muted); border-radius: var(--radius-sm); padding: var(--space-sm) var(--space-md); font-weight: 500; max-inline-size: none; }
  .state--success { border-inline-start-color: var(--color-success); }
  .state--accent { border-inline-start-color: var(--color-accent); }
  .registration__actions { display: flex; flex-wrap: wrap; gap: var(--space-sm); }
  /* M28 (D7): the contribution call to action, just above the button */
  .registration__contribution { color: var(--color-text-muted); }
  /* the confirmed member's ticket */
  .ticket { background: var(--color-surface); border: var(--border); border-inline-start: 4px solid var(--color-success); border-radius: var(--radius-md); padding: var(--space-lg); display: grid; gap: var(--space-xs); }
  .ticket__title { font-size: var(--fs-1); }
  .ticket__code { font-family: var(--font-heading); font-size: var(--fs-2); }
  /* account page: three stacked cards (M10) */
  .account-card {
    background: var(--color-surface);
    border: var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-lg);
    display: grid;
    gap: var(--space-md);
  }
  .account-card > h2 { font-size: var(--fs-1); }
  .account-card__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-sm);
  }
  .account-card__head h2 { font-size: var(--fs-1); }
  .account-card__security {
    border-block-start: var(--border);
    padding-block-start: var(--space-md);
  }

  /* account: identity + attendance history */
  .identity { display: grid; gap: var(--space-xs); }
  .identity__row { display: grid; gap: var(--space-2xs); }
  .identity dt { font-weight: 600; }
  .identity dd a { margin-inline-start: var(--space-xs); }
  .attendance-list { display: grid; }
  .attendance-list li {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: var(--space-xs) var(--space-md);
    padding-block: var(--space-sm);
    border-block-end: var(--border);
  }
  .attendance-list time { color: var(--color-text-muted); font-size: var(--fs--1); }
  /* M28 (D8): the thumbnail and the link on a past evening, the event_row shape */
  .attendance-list__item { display: block; }
  .attendance-list__link {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    color: var(--color-text);
    text-decoration: none;
  }
  a.attendance-list__link:hover .attendance-list__title { color: var(--color-accent); }
  .attendance-list__img {
    flex: 0 0 auto;
    inline-size: 5rem;   /* M30: the 16:9 thumbnail rendition */
    block-size: 2.8125rem;
    object-fit: cover;
    border-radius: var(--radius-md);
    background: var(--color-surface);
  }
  .attendance-list__img--empty { display: grid; place-items: center; border: var(--border); color: var(--color-text-muted); }
  .attendance-list__img--empty .logo-mark { inline-size: 1.5rem; block-size: auto; }
  .attendance-list__text { display: flex; flex: 1; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: var(--space-2xs) var(--space-md); min-inline-size: 0; }
  .attendance-list__title { font-weight: 500; transition: color var(--dur-fast) var(--ease); }

  /* registration (M8): the button block on the event page, the list on the account page */
  .event-price { color: var(--color-text); font-weight: 600; }
  .event-policies { font-size: .8rem; line-height: 1.6; color: var(--color-text-muted); }
  .event-policies a { color: inherit; text-decoration: underline; text-underline-offset: 3px; text-decoration-color: color-mix(in srgb, currentColor 45%, transparent); }
  .event-policies a:hover { color: var(--color-accent); }
  .registration { display: grid; gap: var(--space-sm); padding-block: var(--space-md); border-block: var(--border); }
  .registration form { display: contents; }
  .registration-list { display: grid; }
  .registration-list__item { display: grid; gap: var(--space-xs); padding-block: var(--space-md); border-block-end: var(--border); }
  .registration-list__head { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-xs) var(--space-md); }
  .registration-list__head time { color: var(--color-text-muted); font-size: var(--fs--1); }
  .registration-list__status { color: var(--color-text-muted); font-size: var(--fs--1); }

  /* M12: the « add to your calendar » links under a confirmed ticket */
  .calendar-links { font-size: var(--fs--1); }

  /* holding page (parked domain) */
  .holding {
    min-block-size: 100svh;
    display: grid;
    align-content: center;
    justify-items: center;
    text-align: center;
    gap: var(--space-md);
    padding: var(--space-fluid) var(--gutter);
  }
  .holding .logo-mark { inline-size: clamp(3.5rem, 2.5rem + 5vw, 6rem); color: var(--color-accent); }
  .holding__status { font-family: var(--font-heading); font-size: var(--fs-1); }
  .holding p { max-inline-size: 40ch; color: var(--color-text-muted); }

  /* M76: the staging preview password form, on the holding page's layout */
  .preview-form {
    display: grid;
    gap: var(--space-sm);
    inline-size: 100%;
    max-inline-size: 22rem;
    margin-inline: auto;
    text-align: start;
  }
  .preview-form label { color: var(--color-text-muted); }
  .preview-form__error { color: var(--color-danger); }

  /* status blocks (confirmation pages) */
  .status-card {
    background: var(--color-surface);
    border: var(--border);
    border-radius: var(--radius-lg);
    padding: var(--space-xl);
    display: grid;
    gap: var(--space-md);
    justify-items: start;
  }
  /* M16: the public category, a text chip in its own colour on the rows and
     the event page; the colour follows the category, the text is the signal */
  .chip--cat { font-weight: 600; }
  .chip--cat-danse { color: var(--color-cat-danse); }
  .chip--cat-connect { color: var(--color-cat-connect); }
  h1 .chip--cat { vertical-align: middle; font-size: var(--fs--1); }

  /* ---------- M29: the scroll reveal (D1, D2) ---------- */
  /* js/reveal.js arms only the blocks below the first screen; no script,
     no arming, nothing ever hidden. is-in must come after is-armed here:
     equal specificity, source order decides the settled state. */
  @media (prefers-reduced-motion: no-preference) {
    [data-reveal].is-armed,
    [data-reveal-stagger].is-armed > * { opacity: 0; transform: translateY(16px); }
    [data-reveal].is-in,
    [data-reveal-stagger].is-in > * {
      opacity: 1; transform: none;
      transition: opacity var(--dur-reveal) var(--ease), transform var(--dur-reveal) var(--ease);
    }
    [data-reveal-stagger].is-in > :nth-child(2) { transition-delay: 60ms; }
    [data-reveal-stagger].is-in > :nth-child(3) { transition-delay: 120ms; }
    [data-reveal-stagger].is-in > :nth-child(4) { transition-delay: 180ms; }
    [data-reveal-stagger].is-in > :nth-child(5) { transition-delay: 240ms; }
    [data-reveal-stagger].is-in > :nth-child(n+6) { transition-delay: 300ms; }
  }

  /* ---------- M29: photos zoom slightly under a real pointer (D3) ---------- */
  @media (hover: hover) and (pointer: fine) {
    .insta-grid li { border-radius: var(--radius-lg); overflow: hidden; }
    .insta-grid img { transition: transform var(--dur-slow) var(--ease); }
    .insta-grid li:hover img { transform: scale(1.03); }
    img.event-row__img { transition: transform var(--dur-slow) var(--ease); }
    .event-row__link:hover img.event-row__img { transform: scale(1.03); }
  }

  /* M47: the public site's skin for the shared card (css/toast.css). The card is
     paper on the parchment, in the site's own body face, and the terracotta is the
     focus ring. Measured on the card's own fill #FFFCF7: the title tones are
     success #3D5A3A 7.54:1, error #8F2F1D 7.92:1, info #2B2521 14.77:1 and warning
     #8F5F2C 5.34:1 (the plain --color-ochre measures 3.14:1 and tokens.css marks it
     decorative only, so the card uses the deepened token); the body #6C6155 is
     5.90:1 and the close glyph reads at the same value. The icon is a graphic and
     needs only 3:1. The region takes .toasts.toasts--brand so the skin beats the
     neutral defaults on specificity rather than on file order. */
  .toasts.toasts--brand {
    --toast-bg: var(--color-paper);
    --toast-fg: var(--color-text-muted);
    --toast-line: var(--color-border);
    --toast-radius: var(--radius-md);
    --toast-shadow: var(--shadow-2);
    --toast-z: var(--z-toast);
    --toast-focus: var(--color-focus);
    --toast-undo-color: var(--color-text);
    --toast-close-color: var(--color-text-muted);
    --toast-close-hover-bg: var(--color-surface);
    --toast-close-hover-color: var(--color-text);
  }
  .toasts--brand .toast-card--success { --toast-tone: var(--color-success); --toast-tone-line: #C6D3C3; }
  .toasts--brand .toast-card--info { --toast-tone: var(--color-text); --toast-tone-line: var(--color-border); }
  .toasts--brand .toast-card--warning { --toast-tone: var(--color-ochre-deep); --toast-tone-line: #E3D2B8; }
  .toasts--brand .toast-card--error { --toast-tone: var(--color-danger); --toast-tone-line: #E8CCC5; }
  /* the one control a visitor has to dismiss an error on a phone: a 44 px target
     from the box, the glyph unchanged (the logged rule tap-target-never-from-line-height) */
  @media (max-width: 42.5rem) {
    .toasts--brand .toast-card__close::after { content: ""; position: absolute; inset: 50% auto auto 50%; width: 44px; height: 44px; transform: translate(-50%, -50%); }
  }
}

@layer utilities {
  .sr-only:not(:focus):not(:focus-within) {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  .skip-link {
    position: absolute;
    inset-block-start: var(--space-xs);
    inset-inline-start: var(--space-xs);
    z-index: var(--z-toast);
    background: var(--color-ink);
    color: var(--color-cream);
    padding: var(--space-sm) var(--space-md);
    border-radius: var(--radius-sm);
    translate: 0 -300%;
  }
  .skip-link:focus { translate: 0 0; }

  .muted { color: var(--color-text-muted); }
  .flow > * + * { margin-block-start: var(--space-md); }
}
