:root{
  --ink:#101014;
  --coal:#1a1a20;
  --flame:#f5841f;
  --flame-dark:#c9660a;
  --ember:#ffc073;
  --paper:#faf9f6;
  --card:#ffffff;
  --line:#e7e4dd;
  --muted:#5c5c63;
  --ok:#1f8a4c;
  --warn:#b3261e;
  --text:#101014;
  --body2:#3c3c42;
  --field:#ffffff;
  --radius:14px;
  --shadow:0 1px 2px rgba(16,16,20,.05),0 6px 20px rgba(16,16,20,.06);
  /* one lean for the whole site. --slant-deg is the real source of truth: a skew transform
     holds the angle exactly, whatever height the element ends up. --slant-ratio is its
     tangent, only for the few places that need a px offset against a KNOWN height (the
     44px nav bar, the --hero-strip-h photo strip) -- a px offset on an auto-height element would
     silently change angle every time the content changed. */
  --slant-deg:20deg;
  --slant-ratio:.364;
  /* homepage hero card: shared by the real card and the framing editor's replica of it */
  --hero-card-h:220px;--hero-card-h-compact:146px;--hero-card-gap:14px;
  /* the homepage photo strip's height on computers (phones set their own below), and the widest a
     slide in it gets. The framing editor's computer replica is drawn at exactly this size
     (HERO_REPLICAS in members.js) -- keep in step. */
  --hero-strip-h:520px;--hero-slide-w:1100px;
  /* The bevel used by the cards that can't afford a full parallelogram (Club Calendar rows,
     Open Meets). --cut is the horizontal run of the corner cut, --rise its vertical run, and
     --rise = --cut / --slant-ratio, so the cut edge sits at exactly --slant-deg NO MATTER how
     tall the card grows. That is what a fixed "lean the whole card" offset could not do: the
     same px lean on a 200px card and a 460px card reads as two different angles. */
  --cut:34px;
  --rise:93px;
  /* Same bevel, panel scale: for the accordions, which are ~52px closed and can be several
     hundred open. --cut-sm / --rise-sm keep the same --rise = --cut / --slant-ratio identity,
     so the corner runs at exactly --slant-deg at BOTH of those heights -- it just takes a
     shorter run than the full-card --cut, which on a 52px closed bar would eat the whole
     right-hand edge and clip the +/- toggle. */
  --cut-sm:16px;
  --rise-sm:44px;
}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}*{transition:none!important;animation:none!important}}
body{font-family:'Montserrat',system-ui,sans-serif;background:var(--paper);color:var(--text);line-height:1.55;font-size:16px;
  -webkit-text-size-adjust:100%;text-size-adjust:100%}
img{max-width:100%}
a{color:var(--flame-dark)}
.container{max-width:1120px;margin:0 auto;padding:0 20px}
.display{font-family:'Montserrat',sans-serif;font-weight:800;line-height:1.06;letter-spacing:-.015em}
#heroTitle.alt-text{font-family:inherit;font-weight:500;letter-spacing:normal;text-transform:none;font-size:1.05rem;line-height:1.5}
.eyebrow{font-family:'Montserrat',sans-serif;font-weight:600;text-transform:uppercase;letter-spacing:.14em;font-size:.85rem;color:var(--flame-dark)}
.lane-rope{height:6px;width:120px;border-radius:3px;margin:14px 0 0;
  background:repeating-linear-gradient(90deg,var(--flame) 0 16px,transparent 16px 22px,var(--ink) 22px 38px,transparent 38px 44px)}
.lane-rope.on-dark{background:repeating-linear-gradient(90deg,var(--ink) 0 16px,transparent 16px 22px,#fff 22px 38px,transparent 38px 44px)}
.lane-rope.full{width:100%}

/* ---------- header ---------- */
header.site{position:sticky;top:0;z-index:50;background:#fff;color:var(--ink);border-bottom:3px solid var(--flame);box-shadow:0 1px 0 var(--line)}
.nav-wrap{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:8px 20px;max-width:1120px;margin:0 auto}
.brand{display:flex;align-items:center;gap:14px;color:var(--ink);text-decoration:none}
.brand img{width:112px;height:112px;flex:0 0 auto;object-fit:contain}
.brand .name{display:flex;flex-direction:column;gap:2px;font-family:'Montserrat',sans-serif;font-weight:800;font-size:1.12rem;line-height:1.05;letter-spacing:-.01em;white-space:nowrap}
.brand .name .line-one{display:block}
.brand .name .line-two{display:block;font-weight:700;font-size:.66rem;letter-spacing:.2em;color:var(--flame-dark);text-transform:uppercase}
nav.main{display:flex;align-items:stretch}
nav.main a{position:relative;color:var(--ink);text-decoration:none;font-weight:600;font-size:.85rem;line-height:1;text-align:center;white-space:nowrap;display:flex;align-items:center}
.nav-dropdown{position:relative}
.nav-dropdown-toggle{position:relative;font:inherit;color:var(--ink);font-weight:600;font-size:.85rem;line-height:1;background:none;border:none;cursor:pointer;display:flex;align-items:center;gap:5px;white-space:nowrap}
.nav-dropdown .caret{font-size:.75em;opacity:.75;transition:transform .15s}
.nav-dropdown.open .caret{transform:rotate(180deg)}
.nav-dropdown-menu{display:none;position:absolute;top:calc(100% + 10px);left:0;min-width:230px;background:#fff;border:1.5px solid var(--line);border-radius:12px;box-shadow:0 16px 32px rgba(16,16,20,.16);padding:8px;flex-direction:column;gap:2px;z-index:60}
.nav-dropdown.open .nav-dropdown-menu{display:flex}
.nav-dropdown-menu a{position:relative;display:flex;align-items:center;gap:10px;color:var(--ink);text-decoration:none;font-size:.85rem;font-weight:600;white-space:nowrap;border-radius:8px}
.nav-cta{display:flex;gap:8px;align-items:center}

/* ---------- desktop nav: slanted highlight + diagonal dividers ---------- */
@media(min-width:1024px){
  nav.main{height:44px;gap:16px}
  nav.main a{z-index:0;padding:0 18px}
  /* the toggle button lives one level deeper than the plain links (nested for the
     dropdown wrapper), so the wrapper itself needs to stretch it to match their height */
  .nav-dropdown{display:flex;align-items:stretch}
  nav.main a::before,.nav-dropdown-toggle::before{
    content:"";position:absolute;inset:0;z-index:-1;
    clip-path:polygon(16px 0,100% 0,calc(100% - 16px) 100%,0 100%);
    background:var(--flame);
    opacity:0;transform:translateX(-8px);transition:opacity .2s ease,transform .2s ease;
  }
  /* hover and the current page both use the solid banner orange (.hero), so the bar, the
     Join Us button and the banner all read as the same colour */
  nav.main a:hover:not(.active,.cta)::before{opacity:1;transform:translateX(0)}
  nav.main a:hover:not(.active,.cta){color:#fff;text-shadow:0 1px 3px rgba(0,0,0,.3)}
  nav.main a.active{color:#fff;text-shadow:0 1px 3px rgba(0,0,0,.3)}
  nav.main a.active::before{opacity:1;transform:translateX(0)}
  /* diagonal divider, drawn in the 16px gap after every plain link except the one right
     before Join Us (the cta already has its own margin, no divider needed there) */
  nav.main>a:not(.cta):not(:has(+.cta))::after,.nav-dropdown::after{
    content:"";position:absolute;top:5px;bottom:5px;right:-9px;width:2px;
    background:var(--flame);opacity:.7;transform:skewX(-20deg);pointer-events:none;
  }

  .nav-dropdown-toggle{z-index:0;padding:0 18px}
  .nav-dropdown-toggle:hover:not(.active)::before{opacity:1;transform:translateX(0)}
  .nav-dropdown-toggle:hover:not(.active){color:#fff;text-shadow:0 1px 3px rgba(0,0,0,.3)}
  .nav-dropdown.open .nav-dropdown-toggle,.nav-dropdown-toggle.active{color:#fff;text-shadow:0 1px 3px rgba(0,0,0,.3)}
  .nav-dropdown.open .nav-dropdown-toggle::before,.nav-dropdown-toggle.active::before{opacity:1;transform:translateX(0)}

  /* Each row is its own panel, always visible at rest -- skewX (not a px clip-path) so the lean
     is exactly --slant-deg whatever the row's height turns out to be, same as the flame tick and
     every other variable-height element on the page; a fixed-px clip-path only lands on the true
     angle at the one height it was tuned for (which is what made the corner cut read off against
     the tick). The menu itself clips to its rounded corners so a row's skewed corners can't poke
     past the panel edge. The highlighted fill is the exact gradient the Club Info toggle and
     every other nav link use, so hovering/opening a row reads as the same highlight, not a
     different colour. */
  /* Rows sit just under the 44px nav bar and carry the bar's own .85rem label. skewX holds the
     angle at exactly --slant-deg whatever the height, but the horizontal RUN of that diagonal is
     height * --slant-ratio -- so at ~38px a row's wedge runs ~14px against the Club Info
     button's 16px, near enough to read as the same cut, and the side padding clears it. */
  .nav-dropdown-menu{min-width:300px;background:transparent;border:none;border-radius:0;box-shadow:none;padding:0;gap:4px;overflow:visible}
  /* nav.main-prefixed for the same reason as the ::before rules below: plain
     `.nav-dropdown-menu a` loses to `nav.main a{padding:0 18px}` above, which silently flattened
     every row to its line-height. */
  nav.main .nav-dropdown-menu a{overflow:visible;padding:11px 26px;font-size:.85rem;line-height:1.2;gap:14px}
  /* Prefixed with nav.main so these outrank the `nav.main a::before` bar-link highlight above,
     which rests at opacity:0 and is revealed on hover. Unprefixed, that rule won on specificity
     and every row's panel stayed invisible -- the menu read as see-through, with whatever sat
     behind the header (the partners ticker) showing through the rows. */
  nav.main .nav-dropdown-menu a::before{
    content:"";position:absolute;inset:0;z-index:-1;opacity:1;clip-path:none;
    background:#f3f1ec;border:1.5px solid var(--line);box-shadow:0 6px 14px rgba(16,16,20,.14);
    transform:skewX(calc(-1 * var(--slant-deg)));
    transition:background .18s,border-color .18s,box-shadow .18s;
  }
  .nav-dropdown-menu a::after{
    content:"";order:-1;flex:0 0 auto;width:4px;height:18px;
    background:var(--flame);opacity:.6;transform:skewX(calc(-1 * var(--slant-deg)));transition:opacity .18s,background .18s;
  }
  /* transform has to be restated here: `nav.main a:hover::before` above is a more specific
     match than the resting rule, so without it a hovered row picked up that rule's
     translateX (which replaced the skew, squaring the row off).
     The fill is the same solid banner orange the bar links and Join Us use. */
  nav.main .nav-dropdown-menu a:hover::before,nav.main .nav-dropdown-menu a:focus-visible::before,nav.main .nav-dropdown-menu a.active::before{
    opacity:1;transform:skewX(calc(-1 * var(--slant-deg)));
    background:var(--flame);border-color:transparent;
    box-shadow:0 8px 18px rgba(201,102,10,.3);
  }
  .nav-dropdown-menu a:hover::after,.nav-dropdown-menu a:focus-visible::after,.nav-dropdown-menu a.active::after{opacity:1;background:#fff}
  .nav-dropdown-menu a:hover,.nav-dropdown-menu a:focus-visible,.nav-dropdown-menu a.active{color:#fff;font-weight:700;text-shadow:0 1px 4px rgba(0,0,0,.4)}

  nav.main a.cta{
    margin-left:4px;background:var(--flame);
    clip-path:polygon(16px 0,100% 0,calc(100% - 16px) 100%,0 100%);
    color:#101014;font-weight:700;padding:0 20px;
  }
  nav.main a.cta:hover{filter:brightness(1.08)}
}
/* These tighter proportions started life as a 1024-1159px patch so a landscape tablet still
   got the real nav. They now run across the WHOLE desktop range, because .nav-wrap is capped
   at max-width:1120px -- a wider monitor gives the bar no more room than a 1120px one. At the
   untightened sizes the brand, the six nav items and the toggle came to ~1124px inside a
   1080px content box, so the bar had been overflowing its own wrap at every width from 1160px
   up; it only escaped notice because above ~1400px the page's side margins are wide enough to
   absorb the bleed instead of showing a scrollbar. Tightened, the same row needs ~979px, which
   leaves real slack -- and that slack is what the two social icons now sit in. */
@media(min-width:1024px){
  .brand img{width:84px;height:84px}
  .brand{gap:11px}
  .brand .name{font-size:1.02rem}
  nav.main{gap:11px}
  nav.main a,.nav-dropdown-toggle{padding:0 12px}
  nav.main a.cta{padding:0 15px}
  nav.main>a:not(.cta):not(:has(+.cta))::after,.nav-dropdown::after{right:-6px}
}
/* 1024-1059 is the tightest the real bar ever gets: 1024 is where the burger hands over and
   the wrap is still only 984px of content box. Even at the tightened sizes the row spilled
   ~27px past its padding there -- the toggle sat hard against the edge -- so this narrow band
   goes tighter again. (Pre-existing; it predates the social icons, which are off below 1120.) */
@media(min-width:1024px) and (max-width:1059px){
  .brand{gap:9px}
  .brand .name{font-size:.96rem}
  nav.main{gap:8px}
  nav.main a,.nav-dropdown-toggle{padding:0 9px}
  nav.main a.cta{padding:0 12px}
  nav.main>a:not(.cta):not(:has(+.cta))::after,.nav-dropdown::after{right:-5px}
}

.theme-toggle{display:flex;align-items:center;justify-content:center;width:42px;height:42px;background:none;border:1.5px solid rgba(16,16,20,.25);color:var(--ink);border-radius:50%;cursor:pointer;padding:0}
.theme-toggle:hover{border-color:var(--flame);color:var(--flame-dark)}
.burger{display:none;background:none;border:1.5px solid rgba(16,16,20,.25);color:var(--ink);border-radius:8px;padding:8px 10px;font-size:1.05rem;cursor:pointer}

/* ---------- quick links menu (desktop) ----------
   Facebook, Instagram and the day/night toggle used to sit as three separate buttons at the
   right of the bar; on a wide screen they're joined by the club's other off-site links (results,
   leagues, governing bodies), so they're collapsed into one menu button instead of growing the
   button row further. Below the 1120px bar-content breakpoint the standalone theme toggle takes
   over again and these links live in the drawer/footer instead. */
.quick-links{display:none;position:relative}
.quick-links-toggle{display:flex;align-items:center;justify-content:center;width:42px;height:42px;background:none;border:1.5px solid rgba(16,16,20,.25);color:var(--ink);border-radius:50%;cursor:pointer;padding:0}
.quick-links-toggle:hover{border-color:var(--flame);color:var(--flame-dark)}
.quick-links-menu{display:none;position:absolute;top:calc(100% + 10px);right:0;min-width:230px;background:#fff;border:1.5px solid var(--line);border-radius:12px;box-shadow:0 16px 32px rgba(16,16,20,.16);padding:8px;flex-direction:column;gap:2px;z-index:60}
.quick-links.open .quick-links-menu{display:flex}
.quick-links-menu a,.quick-links-menu button.theme-toggle{display:flex;align-items:center;justify-content:flex-start;gap:10px;color:var(--ink);text-decoration:none;font-size:.85rem;font-weight:600;white-space:nowrap;border-radius:8px;padding:9px 10px;background:none;border:none;width:100%;height:auto;text-align:left;cursor:pointer;font:inherit;font-weight:600}
.quick-links-menu a:hover,.quick-links-menu button.theme-toggle:hover{background:rgba(16,16,20,.06)}
.quick-links-menu button.theme-toggle{color:var(--ink)}
.quick-links-menu .icon{display:flex;flex:0 0 auto;width:18px;height:18px}
.quick-links-divider{height:1px;background:var(--line);margin:4px 2px}
/* Club Organiser: the brand's black banner with its logo, matching the mobile drawer's tile */
.quick-links-menu a.quick-co,body.theme-dark .quick-links-menu a.quick-co{flex-direction:column;align-items:center;gap:6px;margin:2px 0;padding:10px 12px 8px;background:#000;color:#fff;border:1.5px solid #000}
.quick-links-menu a.quick-co:hover,body.theme-dark .quick-links-menu a.quick-co:hover{background:#000;border-color:var(--flame)}
.quick-links-menu a.quick-co img{display:block;height:24px;width:auto;max-width:100%}
.quick-co-note{font-size:.66rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;line-height:1.2}
@media(min-width:1120px){
  .theme-toggle-standalone{display:none}
  .quick-links{display:block}
}
body.theme-dark .quick-links-toggle{color:#fff;border-color:rgba(255,255,255,.3)}
body.theme-dark .quick-links-menu{background:#1c1c22;border-color:#31313a}
body.theme-dark .quick-links-menu a,body.theme-dark .quick-links-menu button.theme-toggle{color:#e4e2de}
body.theme-dark .quick-links-menu a:hover,body.theme-dark .quick-links-menu button.theme-toggle:hover{background:rgba(255,255,255,.08)}
body.theme-dark .quick-links-divider{background:#31313a}
/* Buttons lean with everything else. Same ::before-fill technique as .pill and the skewed nav
   highlight: the FILL is skewed, the label stays upright, and because a skew transform (not a
   px offset) holds the shape, the edge sits at exactly --slant-deg whether the button is one
   line or two, small or big. Everything that used to paint a button -- background, border, the
   live pulse -- has to move onto that pseudo: anything left on the element itself would draw
   the old rectangle behind the lean. z-index:0 makes each button its own stacking context so
   the z-index:-1 fill cannot slip behind an ancestor card's background (a negative-z child
   paints before in-flow descendants' backgrounds otherwise). Side padding is raised to clear
   the lean, which costs height/2 * --slant-ratio at each edge. */
.btn{position:relative;z-index:0;display:inline-block;background:none;color:#fff;border:none;border-radius:0;
  font:inherit;font-weight:700;padding:10px 22px;cursor:pointer;text-decoration:none;transition:color .15s}
.btn::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--flame);
  transform:skewX(calc(-1 * var(--slant-deg)));transition:background .15s,border-color .15s}
.btn:hover::before{background:var(--flame-dark)}
.btn.ghost{color:inherit}
.btn.ghost::before{background:transparent;border:1.5px solid currentColor}
.btn.ghost:hover::before{background:rgba(242,107,33,.1)}
.btn.small{padding:6px 16px;font-size:.85rem}
.btn.dangerous{color:var(--warn)}
.btn.dangerous::before{background:transparent;border:1.5px solid var(--warn)}
.btn.dark{color:#fff}
.btn.dark::before{background:var(--ink)}
/* The focus ring has to follow the lean too -- an outline is drawn on the element's rectangle. */
.btn:focus-visible{outline:none}
.btn:focus-visible::before{box-shadow:0 0 0 3px rgba(245,132,31,.55)}
.path-card{font:inherit;color:inherit;text-align:left;cursor:pointer;transition:border-color .15s, box-shadow .15s}
.path-card:hover{border-color:var(--flame)}
.path-card.sel{border:2px solid var(--flame);box-shadow:0 0 0 3px rgba(245,132,31,.18)}
.btn.dark:hover::before{background:#2a2a32}

/* ---------- partners strip ---------- */
.partners{background:var(--ink);padding:13px 0}
.partners-wrap{max-width:1120px;margin:0 auto;padding:0 20px;display:flex;align-items:center;gap:26px;flex-wrap:wrap}
.partners .label{font-family:'Montserrat',sans-serif;font-weight:700;font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;color:var(--ember);flex:0 0 auto}
/* .logos-scroll > .logos-track holds two copies of the same .logos list (the second,
   aria-hidden, is real markup in every page -- see index.html). On desktop both are inert
   (display:contents all the way down) and the duplicate copy is hidden, so nothing changes
   from before. On phones .logos-scroll becomes the marquee's clipped viewport and .logos-track
   -- the single element holding BOTH copies side by side -- is what actually animates:
   translateX(-50%) on the TRACK moves it by exactly one copy's width (since the percentage is
   relative to the track's own width, which is two copies), so copy two lands exactly where
   copy one started and the loop is seamless. (Animating each .logos copy individually instead
   would move each by 50% of its OWN width and visibly desync -- it has to be the shared track.) */
.logos-scroll,.logos-track{display:contents}
.logos-scroll .logos[aria-hidden]{display:none}
.partners .logos{display:flex;align-items:center;flex:1;gap:20px;flex-wrap:wrap;min-width:0}
.partners .logos a{position:relative;flex:1 1 0;text-align:center;font-family:'Montserrat',sans-serif;font-weight:800;font-size:.95rem;letter-spacing:-.01em;color:#fff;text-decoration:none;opacity:.82;transition:opacity .15s,color .15s}
.partners .logos a:hover{opacity:1;color:var(--ember)}
/* a partner with no web address set is drawn as a link-less <a>: same look, nothing to click */
.partners .logos a:not([href]){cursor:default}
.partners .logos a:not([href]):hover{opacity:.82;color:#fff}
.partners .logos a::after{
  content:"";position:absolute;top:-6px;bottom:-6px;right:-13px;width:2px;
  background:var(--flame);opacity:.8;transform:skewX(calc(-1 * var(--slant-deg)));pointer-events:none;
}
.partners .logos a:last-child::after{display:none}
@media(max-width:760px){
  @keyframes partners-marquee{from{transform:translateX(0)}to{transform:translateX(-50%)}}
  .logos-scroll{
    display:block;flex:1;min-width:0;overflow:hidden;
    -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 24px,#000 calc(100% - 24px),transparent 100%);
    mask-image:linear-gradient(90deg,transparent 0,#000 24px,#000 calc(100% - 24px),transparent 100%);
  }
  .logos-track{display:flex;width:max-content;animation:partners-marquee 16s linear infinite}
  .logos-scroll .logos{flex:0 0 auto;flex-wrap:nowrap;justify-content:flex-start;gap:22px;padding-right:22px}
  .logos-scroll .logos[aria-hidden]{display:flex}
  /* the tick separators are normally hidden after each list's last item (see .partners .logos
     a:last-child::after above) -- in the marquee the two copies sit end to end, so the first
     copy's last item needs its tick back too, or the seam between loops reads as a bare gap
     next to every other, ticked gap */
  .logos-scroll .logos a:last-child::after{display:block}
  /* A marquee item must stay on ONE line: the links inherit flex:1 1 0 from the wrapping
     desktop layout, which inside the track's width:max-content squeezed a two-word partner
     ("Allens of Kingsbury") onto two lines and made the whole ink strip twice as tall as it
     needs to be. In the ticker each item is simply as wide as its own name. */
  .logos-scroll .logos a{flex:0 0 auto;white-space:nowrap;text-align:left}
  @media(hover:hover){.logos-scroll:hover .logos-track{animation-play-state:paused}}
}
:focus-visible{outline:3px solid var(--ember);outline-offset:2px}

/* ---------- mobile nav drawer: the same lean, stacked ----------
   a drawer row is ~46px tall, so a skewed fill leans only ~8px either side -- the 10px inset
   swallows that, which means the angle here is exactly the same --slant-deg as the desktop
   bar rather than a watered-down version for small screens. (a full-width CARD can't do this:
   at 250px tall the identical skew would eat ~90px of a 390px screen, which is why the cards
   further down carry the lean in their accents instead of their outline.) */
@media(max-width:1023px){
  .burger{display:block}
  nav.main{display:none;position:absolute;top:100%;left:0;right:0;background:#fff;flex-direction:column;align-items:stretch;padding:12px 14px 16px;border-bottom:3px solid var(--flame);box-shadow:0 12px 24px rgba(16,16,20,.12);
    max-height:var(--drawer-max,calc(100dvh - 100%));overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
  nav.main.open{display:flex}
  nav.main a,.nav-dropdown-toggle{
    position:relative;z-index:0;justify-content:flex-start;gap:12px;font-size:.95rem;
    padding:15px 22px;margin-bottom:6px;border:none;border-radius:0;background:none;
  }
  nav.main a::before,.nav-dropdown-toggle::before{
    content:"";position:absolute;inset:0 10px;z-index:-1;
    background:#f3f1ec;border:1.5px solid var(--line);
    transform:skewX(calc(-1 * var(--slant-deg)));
    transition:background .18s,border-color .18s;
  }
  /* touch has no hover, so :active is what gives a press its feedback */
  nav.main a:active::before,.nav-dropdown-toggle:active::before{background:#fff6ec;border-color:var(--flame)}
  /* an open Club Info is filled the same way the desktop bar fills it -- which also keeps the
     row legible when it is both open AND the current section */
  nav.main a.active,nav.main a.cta,.nav-dropdown-toggle.active,
  .nav-dropdown.open .nav-dropdown-toggle{color:#fff;font-weight:700;text-shadow:none}
  nav.main a.active::before,nav.main a.cta::before,.nav-dropdown-toggle.active::before,
  .nav-dropdown.open .nav-dropdown-toggle::before{
    background:var(--flame);border-color:transparent;
  }
  nav.main a.cta{margin:4px 0 0;justify-content:center;clip-path:none;filter:none}
  /* Club Organiser login: the brand's own black banner, set in the same skewed panel as the
     other rows so it reads as part of the drawer rather than a pasted-in ad */
  nav.main a.nav-co{flex-direction:column;justify-content:center;gap:7px;margin:10px 0 0;padding:12px 22px 10px}
  nav.main a.nav-co::before,body.theme-dark nav.main a.nav-co::before{background:#000;border-color:#000}
  nav.main a.nav-co:active::before,body.theme-dark nav.main a.nav-co:active::before{background:#000;border-color:var(--flame)}
  nav.main a.nav-co img{display:block;height:30px;width:auto;max-width:100%}
  /* the caption under the logo; white in both themes since the tile is always black */
  .nav-co-note{font-size:.72rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:#fff;line-height:1.2}
  body.theme-dark nav.main a.nav-co{color:#fff}
  .nav-dropdown{width:100%}
  .nav-dropdown-toggle{width:100%;justify-content:space-between}
  .nav-dropdown .caret{font-size:1.2em;opacity:1;color:var(--flame)}
  /* on a filled row the flame caret would vanish into the fill */
  .nav-dropdown-toggle.active .caret,.nav-dropdown.open .caret{color:inherit}
  .nav-dropdown-menu{position:static;display:none;flex-direction:column;box-shadow:none;border:none;background:none;padding:0 0 2px 16px;margin-bottom:2px}
  .nav-dropdown.open .nav-dropdown-menu{display:flex}
  nav.main .nav-dropdown-menu a{padding:12px 18px;margin-bottom:5px;font-size:.9rem;border-radius:0}
  nav.main .nav-dropdown-menu a::before{inset:0 8px}
  /* the leading tick the desktop dropdown already uses, so sub-items read as one family */
  nav.main .nav-dropdown-menu a::after{
    content:"";order:-1;flex:0 0 auto;width:4px;height:15px;background:var(--flame);
    transform:skewX(calc(-1 * var(--slant-deg)));transition:background .18s;
  }
  nav.main .nav-dropdown-menu a.active::after{background:#fff}

  /* Follow us: the drawer is where someone actually goes looking for the club, so the two
     social links sit at the foot of it rather than only down in the page footer. They are
     ordinary drawer rows -- same skewed ::before panel, same press state, same dark-theme
     recolouring, all inherited from the rules above -- just laid out two-up. The panel inset
     drops from 10px to 4px because on a half-width tile a 10px inset each side eats most of
     the lean; at this width the skew still reads at the full --slant-deg. */
  .nav-social{display:flex;gap:0;margin-top:10px}
  nav.main .nav-social a{
    flex:1;justify-content:center;gap:9px;
    padding:14px 10px;margin-bottom:0;font-size:.88rem;
  }
  nav.main .nav-social a::before{inset:0 4px}
  nav.main .nav-social a svg{flex:0 0 auto;width:20px;height:20px}
  /* the heading for the pair, carrying the same flame tick the dropdown rows use */
  .nav-social-label{
    display:flex;align-items:center;gap:9px;margin:16px 10px 2px;
    font-family:'Montserrat',sans-serif;font-weight:800;font-size:.68rem;
    text-transform:uppercase;letter-spacing:.14em;color:var(--muted);
  }
  .nav-social-label::before{
    content:"";flex:0 0 auto;width:4px;height:13px;background:var(--flame);
    transform:skewX(calc(-1 * var(--slant-deg)));
  }
}
/* phones: shrink the brand block so logo, name, theme toggle and menu button all fit on screen */
@media(max-width:560px){
  .nav-wrap{padding:8px 16px;gap:10px}
  .brand{gap:10px;min-width:0}
  .brand img{width:60px;height:60px}
  .brand .name{font-size:.92rem;white-space:normal}
  .brand .name .line-two{font-size:.6rem;letter-spacing:.16em}
  .nav-cta{gap:6px;flex:0 0 auto}
  .theme-toggle{width:38px;height:38px}
}

/* ---------- hero ---------- */
.hero{background:var(--flame);color:var(--ink);padding:16px 0;position:relative;overflow:hidden;box-shadow:0 8px 16px -6px rgba(16,16,20,.4);z-index:1}
.hero-photo-strip{height:var(--hero-strip-h);position:relative;overflow:hidden;background:#000;box-shadow:inset 0 10px 16px -10px rgba(0,0,0,.6),inset 0 -10px 16px -10px rgba(0,0,0,.6)}
.hero-carousel-inner{height:100%;position:relative;overflow:hidden}
.hero-slides{display:flex;height:100%;gap:0;transition:transform .45s cubic-bezier(.4,0,.2,1)}
.hero-slide{
  /* photos can't be skewed (it would distort the image), so this one keeps a clip-path --
     but the strip's height IS fixed (--hero-strip-h), so the offset can be derived from it and the
     angle still lands exactly on --slant-deg. the slides then overlap by nearly that offset
     so what shows between them is a thin constant seam, not a wide black wedge. */
  --slide-lean:calc(var(--hero-strip-h) * var(--slant-ratio));
  flex:0 0 clamp(460px,80vw,var(--hero-slide-w));height:100%;position:relative;display:flex;align-items:flex-end;
  filter:blur(3px) brightness(.55);opacity:.92;transition:filter .35s,opacity .35s;pointer-events:none;
  clip-path:polygon(var(--slide-lean) 0,100% 0,calc(100% - var(--slide-lean)) 100%,0 100%);
}
.hero-slide+.hero-slide{margin-left:calc(8px - var(--slide-lean))}
.hero-slide.active{filter:none;opacity:1;pointer-events:auto}
/* gallery photos stack here and cross-fade (cycleHeroPhotos in site.js); the ::after is the
   darkening that keeps the card legible over any photo */
/* its own stacking layer, so the photos' z-index (for the cross-fade below) stays inside it and
   can never rise over the card */
.hero-slide-media{position:absolute;inset:0;z-index:0;isolation:isolate}
/* a story with its own pictures for one screen draws both sets; show the one for this screen
   (640px: the same point the card and the photo framing switch at) */
@media(max-width:640px){.hero-slide-media.only-wide{display:none}}
@media(min-width:641px){.hero-slide-media.only-narrow{display:none}}
/* the incoming photo fades in ON TOP of the outgoing one, which stays fully shown underneath
   (.was) until it's covered -- fading one out while the other fades in let the black behind show
   through mid-change, so every change dipped the picture dark for a second */
.hero-slide-photo{position:absolute;inset:0;opacity:0;transition:opacity 1.6s ease}
.hero-slide-photo.was{opacity:1;transition:none}
.hero-slide-photo.show{opacity:1;z-index:1}
/* just enough shade along the bottom for the dots; the card carries its own dark glass, so the
   photo itself isn't dimmed */
.hero-slide-media::after{content:"";position:absolute;inset:0;z-index:2;background:linear-gradient(to top,rgba(16,16,20,.35),rgba(16,16,20,0) 30%)}
.hero-news-card{
  /* a fixed height, with the title and summary clamped to fit it, so a long story can't grow
     the card up into the slide's slanted left edge and lose its first letters. knowing the
     height means the margin can be worked out: the slide's edge sits --slant-ratio px further
     right for every px up, and the card's skewed box is centred (28px + height/2) up from the
     bottom -- so this margin keeps a constant --card-gap between the two slants. */
  --card-h:var(--hero-card-h);--card-gap:var(--hero-card-gap);
  position:relative;z-index:0;max-width:420px;height:var(--card-h);
  margin:0 0 28px calc(var(--card-gap) + (28px + var(--card-h) / 2) * var(--slant-ratio));
  display:flex;flex-direction:column;justify-content:center;
  color:#fff;transition:opacity .3s;padding:18px 48px;
}
.hero-news-card h3,.hero-news-card p:not(.eyebrow){display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden}
/* the heights above are sized to fit the clamped lines exactly; never let flex squash a line in half */
.hero-news-card>*,.fh-card>*{flex-shrink:0}
.hero-news-card>.eyebrow,.fh-card>.eyebrow{margin-top:0}
.hero-news-card h3{-webkit-line-clamp:2}
.hero-news-card p:not(.eyebrow){-webkit-line-clamp:3}
/* per-story layout, chosen in the framing editor (feed.hero_card), separately for computers and
   phones (heroCardClasses in core.js). Computer: "compact" drops the summary for a shorter card;
   "right" moves it to the other side, mirroring the margin sum above against the slide's
   right-hand slant, which leans the same way but starts --slide-lean in. Phone (640px down, where
   the card goes full width): "p-compact" drops the summary, "p-top" lifts the card to the top. */
@media(min-width:641px){
  .hero-news-card.card-compact{--card-h:var(--hero-card-h-compact)}
  .hero-news-card.card-compact p:not(.eyebrow){display:none}
  .hero-news-card.card-right{margin-left:auto;margin-right:calc(var(--card-gap) + var(--slide-lean) - (28px + var(--card-h) / 2) * var(--slant-ratio))}
}
@media(max-width:640px){
  .hero-news-card.card-p-compact p:not(.eyebrow){display:none}
  .hero-news-card.card-p-top{align-self:flex-start;margin-top:16px}
}

/* Framed photos (photoLook in core.js). The photo is drawn on ::before so it can be zoomed --
   scaled around the focus point -- without touching the box or its contents. The box's inline
   style supplies --img and the framing: --pos/--size/--z directly, or for .photo-hero and
   .photo-article a wide (-w) and a narrow (-n) set, switched at the breakpoints where those
   layouts change shape. --shade optionally darkens over the photo (social cards). */
.photo{position:relative;overflow:hidden;isolation:isolate}
.photo::before{content:"";position:absolute;inset:0;z-index:-1;
  background:var(--shade,none),var(--img) var(--pos,50% 50%)/var(--size,cover) no-repeat,#101014;
  transform:scale(var(--z,1));transform-origin:var(--pos,50% 50%)}
.photo-hero,.photo-article{--pos:var(--pos-w);--size:var(--size-w);--z:var(--z-w)}
@media(max-width:640px){.photo-hero{--pos:var(--pos-n);--size:var(--size-n);--z:var(--z-n)}}
@media(max-width:640px){.photo-article{--pos:var(--pos-n);--size:var(--size-n);--z:var(--z-n)}}
.hero-slide-photo.photo{position:absolute}
.hero-news-card::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:rgba(16,16,20,.55);border:1px solid rgba(255,255,255,.15);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  transform:skewX(calc(-1 * var(--slant-deg)));
}
.hero-slide:not(.active) .hero-news-card{opacity:0}
.hero-news-card .eyebrow{color:var(--ember)}
.hero-news-card h3{font-family:'Montserrat',sans-serif;font-weight:800;font-size:1.15rem;margin-top:6px;line-height:1.2}
.hero-news-card p{color:rgba(255,255,255,.82);font-size:.9rem;margin-top:8px}
.hero-news-card a{color:var(--ember);font-weight:600;font-size:.85rem;display:inline-block;margin-top:10px}
.hero-arrow{position:absolute;top:50%;transform:translateY(-50%);width:38px;height:38px;border-radius:50%;background:rgba(16,16,20,.45);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);border:1px solid rgba(255,255,255,.25);color:#fff;font-size:1.3rem;line-height:1;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:3;transition:opacity .2s,background .2s}
.hero-arrow:hover{background:rgba(16,16,20,.65)}
.hero-arrow:disabled{opacity:0;pointer-events:none}
.hero-dots{position:absolute;left:0;right:0;bottom:14px;display:flex;justify-content:center;gap:7px;z-index:3}
/* even the dots take the lean -- at 4px tall the skew is invisible across the bar itself,
   but it cuts both ends at --slant-deg, which is the whole read */
.hero-dot{width:24px;height:4px;background:rgba(255,255,255,.35);border:none;padding:0;cursor:pointer;transition:background .2s;transform:skewX(calc(-1 * var(--slant-deg)))}
.hero-dot.active{background:var(--ember)}
@media(max-width:640px){
  /* a card lifted to the top must clear the tabs */
  .hero-news-card.card-p-top{margin-top:54px}
}
.hero-bottom-bar{height:34px;background:var(--flame);position:relative;box-shadow:0 -8px 16px -6px rgba(16,16,20,.4);z-index:1}
@media(max-width:820px){.hero-slide{flex-basis:86vw}}
@media(max-width:600px){
  .hero-photo-strip{height:340px}
  /* a photo can't take a 20deg cut at this height without losing a third of the frame, so the
     slides stay square on phones and the strip's lean is carried by the card and dots instead.
     a fixed narrow peek reads as "there is another slide" rather than as a dead black band. */
  .hero-slide{clip-path:none;flex-basis:calc(100% - 30px)}
  .hero-slide+.hero-slide{margin-left:0}
  .hero-arrow{width:32px;height:32px;font-size:1.1rem}
}
.live-results{position:absolute;top:0;right:20px;display:inline-flex;align-items:center;gap:7px;background:#c81e2c;color:#fff;font-family:'Montserrat',sans-serif;font-weight:700;font-size:.78rem;letter-spacing:.03em;text-transform:uppercase;padding:9px 16px;border-radius:999px;text-decoration:none;box-shadow:0 4px 14px rgba(16,16,20,.28);z-index:2;animation:live-pulse 1.8s ease-in-out infinite}
.live-results:hover{background:#a8121e}
.live-results .live-dot{width:8px;height:8px;border-radius:50%;background:#fff;flex:0 0 auto}
@keyframes live-pulse{0%,100%{box-shadow:0 4px 14px rgba(16,16,20,.28),0 0 0 0 rgba(200,30,44,.5)}50%{box-shadow:0 4px 14px rgba(16,16,20,.28),0 0 0 9px rgba(200,30,44,0)}}
@media(max-width:600px){.live-results{position:static;margin:0 20px 18px}}
/* [hidden] must beat .live-results' own display:inline-flex, or the pill shows with no gala on. */
[hidden]{display:none!important}

/* Live results: the one red thing on the page, so it reads as "happening right now" wherever it appears. */
.btn.live{color:#fff;display:inline-flex;align-items:center;gap:8px}
.btn.live::before{background:#c81e2c;animation:live-pulse 1.8s ease-in-out infinite}
.btn.live:hover{color:#fff}
.btn.live:hover::before{background:#a8121e}
.btn.live .live-dot{width:8px;height:8px;border-radius:50%;background:#fff;flex:0 0 auto}
/* live video stream button: a play mark in place of the live dot */
.btn .stream-play{display:inline-block;margin-right:7px;font-size:.72em;line-height:1;vertical-align:.08em}
.btn.ghost .stream-play{color:#c81e2c}
.pill.live{background:#c81e2c;color:#fff;display:inline-flex;align-items:center;gap:6px}
.pill.live .live-dot{width:7px;height:7px;border-radius:50%;background:#fff;flex:0 0 auto;animation:live-blink 1.4s ease-in-out infinite}
@keyframes live-blink{0%,100%{opacity:1}50%{opacity:.25}}
.card.meet.live{outline:2px solid #c81e2c;outline-offset:-2px}
/* Shown in place of the entry pack button once the closing date has passed (or entries are set closed). */
.btn.entries-closed,body.theme-dark .btn.entries-closed{color:#fff;cursor:default;pointer-events:none}
.btn.entries-closed::before{background:#c81e2c}
@media(prefers-reduced-motion:reduce){.live-results,.btn.live::before,.pill.live .live-dot{animation:none}}

.hero-grid{display:grid;grid-template-columns:1.4fr 1fr;gap:40px;align-items:center;position:relative}
.hero h1{font-size:clamp(1.9rem,3.6vw,2.6rem);color:var(--ink);margin-top:4px}

.next-meet{
  position:relative;z-index:0;color:#101014;padding:18px 58px;
}
.next-meet::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:#fff;box-shadow:0 10px 30px rgba(120,55,0,.22);
  transform:skewX(calc(-1 * var(--slant-deg)));
}
.next-meet .eyebrow{color:var(--flame-dark)}
.next-meet h3{font-family:'Montserrat',sans-serif;font-weight:800;font-size:1.3rem;margin-top:6px;line-height:1.15;letter-spacing:-.01em}
.next-meet .meta{color:#5c5c63;font-size:.92rem;margin-top:6px}
.next-meet .meta div{margin-top:3px}
.next-meet .nm-cta{margin-top:12px}
@media(max-width:820px){.hero-grid{grid-template-columns:1fr}.hero{padding:42px 0 50px}}
@media(max-width:640px){.next-meet{padding:22px}.next-meet::before{transform:none;border-radius:4px}}

/* ---------- sections & cards ---------- */
main{min-height:60vh}
section.page{padding:52px 0 72px}
/* the homepage's orange banner sits almost straight under the partners strip, not a full gap down */
section.page#page-home{padding-top:14px}
.page-head{margin-bottom:34px;max-width:70ch}
.page-head h2{font-size:clamp(1.7rem,3.8vw,2.4rem)}
/* a second, subordinate heading part-way down a page (e.g. Academy coaches) */
.page-head h3{font-size:clamp(1.35rem,2.8vw,1.8rem)}
.page-head p{color:var(--muted);margin-top:12px}
/* Join Us intro: "what we offer" list under the opening paragraph, flame-coloured markers */
.join-offer{list-style:none;margin:14px 0 0;padding:0;display:grid;gap:8px}
.join-offer li{position:relative;padding-left:20px;color:var(--muted);font-size:.95rem}
.join-offer li::before{content:"";position:absolute;left:0;top:.55em;width:9px;height:9px;background:var(--flame);transform:skewX(-12deg)}
.join-offer strong{color:var(--text)}
.news-thumb{height:130px;margin:-22px -22px 14px;border-radius:var(--radius) var(--radius) 0 0;background-size:cover;background-position:center;display:flex;align-items:center;justify-content:center}
/* Tag filter chips: same skewed-::before fill as .pill/.cal-chip rather than a rounded pill, so
   the filter row carries the site's one --slant-deg lean like everything else on the page. */
.news-tag-chips{display:flex;flex-wrap:wrap;gap:10px;margin:0 0 26px}
.news-tag-chip{position:relative;z-index:0;font:inherit;font-weight:700;font-size:.8rem;text-transform:uppercase;letter-spacing:.05em;color:var(--text);background:none;border:none;padding:8px 18px;cursor:pointer}
.news-tag-chip::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--card);border:1.5px solid var(--line);transform:skewX(calc(-1 * var(--slant-deg)));transition:border-color .15s,background .15s}
.news-tag-chip:hover::before{border-color:var(--flame)}
.news-tag-chip.active{color:#fff}
.news-tag-chip.active::before{background:var(--flame);border-color:var(--flame)}
.meet .news-thumb{grid-column:1/-1}

/* ---- Following squads (see FOLLOWING SQUADS in site.js) ---- */
.follow-panel{margin:0 0 22px;background:var(--card);border:1.5px solid var(--line);border-left:4px solid var(--flame)}
.follow-panel summary{display:flex;align-items:center;gap:10px;padding:12px 16px;cursor:pointer;list-style:none;min-width:0}
.follow-panel summary::-webkit-details-marker{display:none}
.follow-panel summary::after{content:"▾";margin-left:auto;color:var(--muted);transition:transform .15s}
.follow-panel[open] summary::after{transform:rotate(180deg)}
.follow-bell{flex:0 0 auto}
.follow-sum{min-width:0;display:flex;flex-wrap:wrap;column-gap:8px;align-items:baseline}
.follow-sum-label{font-weight:800;font-size:.8rem;text-transform:uppercase;letter-spacing:.05em;color:var(--text)}
.follow-sum-names{color:var(--muted);font-size:.9rem;overflow-wrap:anywhere}
.follow-new{flex:0 0 auto;background:var(--flame);color:#101014;font-weight:800;font-size:.72rem;text-transform:uppercase;letter-spacing:.04em;padding:3px 9px;border-radius:999px}
.follow-body{padding:0 16px 16px}
.follow-note{color:var(--muted);font-size:.9rem;margin:0 0 14px;max-width:62ch}
.follow-chips{display:flex;flex-wrap:wrap;gap:10px}
.follow-group{margin:14px 0 8px;font-size:.72rem;font-weight:800;text-transform:uppercase;letter-spacing:.08em;color:var(--muted)}
.follow-note+.follow-group{margin-top:0}
.follow-warn{margin-top:18px;padding:12px 14px;border:1.5px dashed var(--line);border-radius:10px;font-size:.85rem;color:var(--muted)}
.follow-warn-head{margin:0 0 6px;font-weight:800;color:var(--text)}
.follow-warn ul{margin:0;padding-left:18px;display:grid;gap:5px}
.follow-warn b{color:var(--text)}
.follow-warn-foot{margin:8px 0 0}
.follow-read{margin-top:16px}
.news-tag-chip.chip-mine:not(.active){color:var(--flame-dark)}
.news-tag-chip.chip-mine:not(.active)::before{border-color:var(--flame)}
.news-marks{display:flex;gap:6px;margin:0 0 8px}
.news-mark{font-size:.68rem;font-weight:800;text-transform:uppercase;letter-spacing:.05em;padding:3px 8px;border-radius:999px}
.news-mark.mine{background:rgba(245,132,31,.16);color:var(--flame-dark);border:1px solid var(--flame)}
.news-mark.new{background:var(--flame);color:#101014}
.news-mark.pin{background:var(--text);color:var(--paper)}
.news-card.is-mine{border-left:3px solid var(--flame)}
/* the unread count on every Club News link, and a dot on the phone menu button */
.nav-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;margin-left:6px;
  border-radius:999px;background:var(--flame);color:#101014;font-size:.68rem;font-weight:800;line-height:1;text-shadow:none}
nav.main a.active .nav-badge{background:#101014;color:var(--flame)}
.burger{position:relative}
.burger.has-unread::after{content:"";position:absolute;top:-4px;right:-4px;width:11px;height:11px;border-radius:50%;
  background:var(--flame);border:2px solid #fff}
body.theme-dark .burger.has-unread::after{border-color:#111116}
body.theme-dark .news-mark.mine,body.theme-dark .news-tag-chip.chip-mine:not(.active){color:var(--flame)}

/* ---- Club News timeline (see renderNews in site.js) ----
   One scroller running backwards through time. Each period is a block with its own heading;
   the sticky bar above them is the way forward and back. --hdr-h is set by site.js from the
   real header height, because the header's height changes with the logo at each breakpoint. */
.news-jump{position:sticky;top:calc(var(--hdr-h,128px) + 0px);z-index:20;display:flex;align-items:center;gap:10px;
  margin:0 0 26px;padding:9px 12px;background:var(--card);border:1.5px solid var(--line);
  box-shadow:0 10px 22px rgba(16,16,20,.08)}
.news-jump-chips{display:flex;gap:8px;overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none;flex:1;scroll-behavior:smooth}
.news-jump-chips::-webkit-scrollbar{display:none}
.news-jump-chip{position:relative;z-index:0;flex:0 0 auto;font:inherit;font-weight:700;font-size:.76rem;text-transform:uppercase;
  letter-spacing:.05em;color:var(--muted);background:none;border:none;padding:7px 15px;cursor:pointer;transition:color .15s}
.news-jump-chip::before{content:"";position:absolute;inset:0;z-index:-1;background:transparent;border:1.5px solid transparent;
  transform:skewX(calc(-1 * var(--slant-deg)));transition:border-color .15s,background .15s}
.news-jump-chip:hover{color:var(--text)}
.news-jump-chip:hover::before{border-color:var(--line)}
.news-jump-chip.active{color:var(--flame-dark)}
.news-jump-chip.active::before{background:rgba(245,132,31,.14);border-color:var(--flame)}
.news-jump-arrow{flex:0 0 auto;font:inherit;font-weight:700;font-size:.76rem;letter-spacing:.03em;color:var(--text);
  background:none;border:1.5px solid var(--line);border-radius:999px;padding:7px 13px;cursor:pointer;white-space:nowrap;
  transition:border-color .15s,color .15s,opacity .15s}
.news-jump-arrow:hover:not(:disabled){border-color:var(--flame);color:var(--flame-dark)}
.news-jump-arrow:disabled{opacity:.3;cursor:default}

.news-era{scroll-margin-top:calc(var(--hdr-h,128px) + 74px)}
.news-era+.news-era{margin-top:38px}
.news-era-head{display:flex;align-items:baseline;gap:14px;margin:0 0 16px;padding-left:16px;position:relative}
.news-era-head::before{content:"";position:absolute;left:0;top:2px;bottom:2px;width:5px;
  background:linear-gradient(180deg,var(--flame),var(--flame-dark));transform:skewX(calc(-1 * var(--slant-deg)))}
.news-era-head h3{font-family:'Montserrat',sans-serif;font-weight:800;font-size:1.2rem;letter-spacing:-.01em}
.news-era-count{font-size:.76rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--muted)}
.news-date{font-size:.78rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin-top:6px}
/* This week's stories carry the warm wash the Open Meets page gives "ours" -- the eye lands on
   the newest block first without the archive below having to be dimmed. */
.news-card.is-latest{background:linear-gradient(160deg,rgba(245,132,31,.13),var(--card) 58%)}
body.theme-dark .news-card.is-latest{background:linear-gradient(160deg,rgba(245,132,31,.22),var(--card) 58%)}

/* The break between recent news and the archive. Deliberately a big empty stretch: it is the
   signal that the reader has reached the end of what is current, so it has to be impossible to
   scroll past without noticing. */
.news-break{margin:72px 0 56px;text-align:center;position:relative}
.news-break::before{content:"";position:absolute;left:0;right:0;top:17px;height:6px;
  background:repeating-linear-gradient(90deg,var(--ink) 0 16px,transparent 16px 22px,#fff 22px 38px,transparent 38px 44px);
  border-radius:3px;opacity:.5}
body.theme-dark .news-break::before{background:repeating-linear-gradient(90deg,var(--flame) 0 16px,transparent 16px 22px,#fff 22px 38px,transparent 38px 44px)}
.news-break-label{position:relative;z-index:1;display:inline-block;font-family:'Montserrat',sans-serif;font-weight:800;
  font-size:.82rem;text-transform:uppercase;letter-spacing:.14em;color:#fff;background:var(--ink);padding:10px 26px;
  transform:skewX(calc(-1 * var(--slant-deg)))}
body.theme-dark .news-break-label{background:var(--flame);color:var(--ink)}
.news-break-note{margin-top:14px;font-size:.86rem;color:var(--muted)}
.news-break-note-solo{margin:0 0 26px}
@media(max-width:640px){
  .news-jump{gap:6px;padding:7px 8px}
  .news-jump-arrow{padding:7px 9px;font-size:.72rem}
  .news-break{margin:54px 0 42px}
}

.social-card .art{background-size:cover;background-position:center}
.news-thumb-icon{font-size:2.4rem;filter:drop-shadow(0 2px 6px rgba(0,0,0,.35))}
.img-picker{display:grid;gap:10px}
.img-preview{height:110px;border-radius:10px;border:1.5px solid var(--line);background:var(--field);display:flex;align-items:center;justify-content:center;background-size:cover;background-position:center}
.img-preview.empty::after{content:"No picture selected";font-size:.8rem;font-weight:400;text-transform:none;letter-spacing:0;color:var(--muted)}
.img-swatches{display:flex;flex-wrap:wrap;gap:8px}
.img-swatch{width:44px;height:44px;border-radius:8px;border:2px solid transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:1.2rem;padding:0}
.img-swatch.selected{border-color:var(--flame)}
.img-upload-btn{display:inline-block;width:fit-content;font-size:.8rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--flame);border:1.5px dashed var(--line);border-radius:10px;padding:9px 13px;cursor:pointer}
.img-clear-btn{width:fit-content;font-size:.78rem;font-weight:400;text-transform:none;letter-spacing:0;color:var(--muted);background:none;border:none;text-decoration:underline;cursor:pointer;padding:0}
#admin .img-preview{background-color:var(--field);border-color:var(--line)}
#admin .img-preview.empty::after{color:var(--muted)}
.grid{display:grid;gap:18px}
.grid.cols-3{grid-template-columns:repeat(3,1fr)}
.grid.cols-2{grid-template-columns:repeat(2,1fr)}
@media(max-width:900px){.grid.cols-3{grid-template-columns:repeat(2,1fr)}}
/* Coach cards with a bio need more elbow room per card than a plain 2-up grid assumes, so they
   drop to one column sooner than .cols-2's usual 640px. */
@media(max-width:860px){#coachesList,#academyCoachesList{grid-template-columns:1fr}}
@media(max-width:640px){.grid.cols-3,.grid.cols-2{grid-template-columns:1fr}}
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);padding:22px}

/* homepage feature cards only -- same slant system as the nav/hero cards, kept as its
   own class (not .card) so every other page's plain rounded cards are untouched */
/* without this, CSS Grid's default row-stretch makes every card match the tallest one's
   content height -- taller than the assumed --card-h the clip-path angle is computed from,
   which both flattens the slant (mismatched vs the hero-news-card above) and, since the
   notch's pixel width stays fixed while the card grows, makes the visual gap between
   adjacent cards' cut corners look much wider than the 4px gap alone suggests */
/* a skewed shape leans outside its own box (by half its height x tan20), so the row's
   outer edges are clipped flush to the container -- inner seams stay true parallelograms,
   and nothing can push a horizontal scrollbar. align-items:start keeps each card at its
   own content height rather than grid's default stretch. */
.pointed-grid{gap:4px;align-items:start;overflow-x:clip}
.pointed-card{
  position:relative;z-index:0;color:var(--text);min-height:170px;padding:22px 72px;
}
.pointed-card::before{
  content:"";position:absolute;inset:0;z-index:-1;background:var(--card);
  transform:skewX(calc(-1 * var(--slant-deg)));
}
.pointed-card.feature{color:#101014}
.pointed-card.feature::before{background:var(--flame)}
.pointed-card.feature .eyebrow{color:#101014}
@media(max-width:640px){
  .pointed-card{padding:22px;min-height:0}
  .pointed-card::before{transform:none;border-radius:4px;border:1px solid var(--line);box-shadow:var(--shadow)}
  .pointed-card.feature::before{border-color:var(--flame)}
}
/* Every small status badge is a slanted ribbon rather than a rounded pill -- at this size the
   true --slant-deg angle costs nothing (a few px), so it's the one card-adjacent element that
   can carry the lean at any screen width, phones included. Same ::before-fill technique as the
   bigger skewed shapes: the fill leans, the label text stays upright. */
.pill{position:relative;z-index:0;display:inline-block;font-size:.74rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;padding:4px 12px}
.pill::before{content:"";position:absolute;inset:0;z-index:-1;transform:skewX(calc(-1 * var(--slant-deg)))}
.pill.open{color:var(--ok)}
.pill.open::before{background:#e6f4ec}
.pill.closed{color:var(--muted)}
.pill.closed::before{background:#f2f2f0}
.pill.results{color:var(--flame-dark)}
.pill.results::before{background:#fdeee2}
.pill.level{color:#fff}
.pill.level::before{background:var(--ink)}

/* meets */
/* align-items:start -- without it, CSS Grid's default stretch makes the short .datebox column
   match the row's full height (set by .meet-main's often-much-taller content: pills, title,
   venue, notes, closing date, accordion), so the date badge and its own text end up stretched
   or vertically centred down a tall dark column instead of sitting compactly at the top. */
/* The same bevel as the Club Calendar cards (--cut/--rise in :root), so a full-width gala card
   leans at the same --slant-deg as everything else. These stack vertically and the cut edges
   are parallel, so the 18px grid gap stays a uniform diagonal channel between neighbours.
   Side padding clears the cut: --cut at the bottom-right, a little less at the top-left where
   the first text line sits part-way down the cut. */
.meet{display:grid;grid-template-columns:86px minmax(0,1fr) auto;gap:18px;align-items:start;
  border-radius:0;padding:22px 44px 22px 36px;
  clip-path:polygon(var(--cut) 0,100% 0,100% calc(100% - var(--rise)),calc(100% - var(--cut)) 100%,0 100%,0 var(--rise))}
.meet .news-thumb{margin-left:-36px;margin-right:-44px}
.meets-heading{font-size:1.4rem;margin:0 0 14px}
.meets-heading:not(:first-of-type){margin-top:44px}
.meets-sub{color:var(--muted);font-size:.92rem;margin:-6px 0 14px;max-width:70ch}
.meet .host{font-weight:600;font-size:.94rem;color:var(--body2)}
.meet-actions{display:flex;flex-direction:column;gap:10px;width:220px}
.btn.big{padding:14px 26px;font-size:1rem;text-align:center}
.btn.disabled,body.theme-dark .btn.disabled{color:var(--muted);cursor:default;pointer-events:none}
.btn.disabled::before,body.theme-dark .btn.disabled::before{background:transparent;border:1.5px dashed var(--line)}
.meet.done .datebox{opacity:.6}
/* Completed-gala year groups. Unlike details.info this bar is a fixed ~54px whether it is open
   or shut -- the cards it reveals sit below it, outside the summary -- so it can take the plain
   skewX fill that .btn and .pill use instead of a bevel: there is no tall open state for a skew
   to throw a wedge across. That keeps ::after free for the +/- marker. Everything is scoped with
   > so none of it reaches the details.info accordion inside each card. Side padding clears the
   lean (height/2 * --slant-ratio at each edge, ~10px here). */
.year-group>summary{position:relative;z-index:0;cursor:pointer;list-style:none;
  display:flex;align-items:center;gap:14px;padding:15px 30px;
  font-family:'Montserrat',sans-serif;font-weight:800;font-size:1.25rem;letter-spacing:-.01em}
.year-group>summary::-webkit-details-marker{display:none}
.year-group>summary::before{content:"";position:absolute;inset:0;z-index:-1;
  background:var(--card);border:1.5px solid var(--line);
  transform:skewX(calc(-1 * var(--slant-deg)));transition:background .15s,border-color .15s}
.year-group>summary:hover::before{background:rgba(245,132,31,.08);border-color:var(--flame)}
.year-group[open]>summary::before{border-color:var(--flame)}
.year-group>summary:focus-visible{outline:none}
.year-group>summary:focus-visible::before{box-shadow:0 0 0 3px rgba(245,132,31,.55)}
.year-group>summary::after{content:"+";flex:0 0 auto;width:28px;height:28px;border-radius:50%;
  background:var(--flame);color:#fff;font-size:1.2rem;line-height:1;
  display:flex;align-items:center;justify-content:center}
.year-group[open]>summary::after{content:"\2013"}
.year-group>summary .year-count{margin-left:auto;font-weight:600;text-transform:uppercase;letter-spacing:.14em;
  font-size:.78rem;color:var(--muted)}
.year-group>.year-body{display:grid;gap:18px;margin-top:18px}
@media(max-width:640px){.year-group>summary{padding:14px 22px;font-size:1.1rem}}
@media(max-width:760px){
  .meet{grid-template-columns:70px minmax(0,1fr)}
  .meet-actions{grid-column:1/-1;width:auto;flex-direction:row;flex-wrap:wrap}
  .meet-actions .btn{flex:1 1 180px}
}
.btn.black,body.theme-dark .btn.black{color:#fff}
.btn.black::before,body.theme-dark .btn.black::before{background:#101014}
.btn.black:hover::before,body.theme-dark .btn.black:hover::before{background:#2a2a32}
/* club calendar: compact competition cards */
.comp-card{padding:16px 18px;display:flex;flex-direction:column;gap:8px;position:relative}
.comp-top{display:flex;align-items:flex-start;gap:12px}
/* Same treatment on the calendar cards' smaller chip -- a touch wider than before so the
   month label still clears the lean at the bottom edge. */
.comp-date{position:relative;z-index:0;flex:0 0 auto;display:flex;flex-direction:column;align-items:center;justify-content:center;
  width:58px;padding:6px 0;border-radius:0;background:none;color:#fff;line-height:1}
.comp-date::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--ink);
  transform:skewX(calc(-1 * var(--slant-deg)))}
.comp-date .d{font-weight:800;font-size:1.25rem}
.comp-date .m{font-size:.64rem;letter-spacing:.12em;text-transform:uppercase;color:var(--ember);margin-top:3px}
.comp-top h3{font-size:1rem;line-height:1.25;font-weight:800}
.comp-meta{font-size:.84rem;color:var(--muted)}
.comp-foot{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:4px 10px;margin-top:auto;font-size:.84rem;font-weight:700}
.comp-status{color:var(--muted);font-weight:600}
.comp-foot a{text-decoration:none;white-space:nowrap}
/* Open entries (calendar competition cards + Open Meets page). A border or box-shadow is drawn
   on the element's RECTANGLE and only then clipped, so on a bevelled card it stopped dead at
   the cut corners -- an outline simply cannot follow a clip-path. filter:drop-shadow() can: it
   works off the rendered alpha, so the glow hugs the real, visible silhouette whatever shape
   the card takes. So the highlight is now a warm background wash plus a slow breathing glow,
   which also reads as "live" on mobile where the card flattens back to a rectangle.
   (The global prefers-reduced-motion rule near the top stops the animation.) */
.entries-open,.comp-card.entries-open{
  position:relative;
  background:linear-gradient(150deg,rgba(245,132,31,.20),var(--card) 62%);
  animation:entries-pulse 1.6s ease-in-out infinite;
}
body.theme-dark .entries-open,body.theme-dark .comp-card.entries-open{
  background:linear-gradient(150deg,rgba(245,132,31,.30),var(--card) 62%);
}
/* Two stacked drop-shadows rather than one: a tight core that keeps the edge crisp plus a wide
   halo that carries the throb out far enough to catch the eye from across the page. */
@keyframes entries-pulse{
  0%,100%{filter:drop-shadow(0 0 3px rgba(245,132,31,.35)) drop-shadow(0 0 6px rgba(245,132,31,.2))}
  50%{filter:drop-shadow(0 0 7px rgba(245,132,31,.95)) drop-shadow(0 0 22px rgba(245,132,31,.6))}
}
/* The date badge leans outright. It is small enough to carry the full --slant-deg (a ~70px
   badge costs 13px of lean per side, which the card's own side padding and the 18px grid gap
   absorb), so it gets the skewed-::before fill rather than a bevel -- same call as the pills
   and the buttons. The digits stay upright on top of it. */
.meet .datebox{position:relative;z-index:0;background:none;border-radius:0;color:#fff;text-align:center;padding:12px 6px;height:fit-content}
.meet .datebox::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--ink);
  transform:skewX(calc(-1 * var(--slant-deg)))}
.meet .datebox .d{font-family:'Montserrat',sans-serif;font-weight:700;font-size:1.9rem;line-height:1}
.meet .datebox .m{font-size:.75rem;letter-spacing:.14em;text-transform:uppercase;color:var(--ember);margin-top:3px}
/* BPSC-hosted galas (as opposed to meets we just attend): the date badge takes the brand
   colour instead of ink, and the "BPSC hosted" pill becomes a small skewed ribbon -- same
   --slant-deg accent as the eyebrow tabs, sized small enough that the angle costs nothing. */
.meet.ours .datebox::before{background:linear-gradient(150deg,var(--flame) 0%,var(--flame-dark) 100%)}
.meet.ours .datebox .m{color:#3a1c00}
.pill.hosted{color:#fff}
.pill.hosted::before{background:linear-gradient(100deg,var(--flame) 0%,var(--flame-dark) 100%)}
body.theme-dark .meet.ours .datebox .m{color:#3a1c00}
.meet h3{font-family:'Montserrat',sans-serif;font-weight:800;font-size:1.35rem;line-height:1.15;margin:6px 0 4px;letter-spacing:-.01em}
.meet .venue{color:var(--muted);font-size:.94rem}
.meet .row{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.meet .links{margin-top:14px;display:flex;gap:10px;flex-wrap:wrap}
.meet .closing{font-size:.88rem;color:var(--muted);margin-top:10px}
.meet .closing strong{color:var(--text)}
/* Open Meets: intro on the left, visiting-club shortcuts on the right; stacks on narrow screens */
.meets-top{display:flex;gap:28px;align-items:flex-start;justify-content:space-between}
.meets-top .page-head{flex:1 1 auto}
.visit-box{flex:0 0 240px;display:flex;flex-direction:column;gap:10px;padding:18px 20px;border:1px solid var(--line);border-radius:var(--radius);background:var(--card)}
.visit-box .visit-q{font-weight:700;font-size:.95rem;margin:0 0 4px}
.visit-box .btn{text-align:center}
@media(max-width:760px){.meets-top{flex-direction:column;gap:0}.visit-box{flex:none;width:100%;margin-bottom:28px}}
@media(max-width:520px){.meet{grid-template-columns:58px minmax(0,1fr);gap:14px}.meet .datebox{padding:9px 4px}.meet .datebox .d{font-size:1.4rem}.meet h3{font-size:1.15rem}}
@media(max-width:640px){
  .meet{position:relative;clip-path:none;border-radius:var(--radius);padding:22px}
  .meet .news-thumb{margin-left:-22px;margin-right:-22px}
}

/* coaches */
.coach{text-align:left}
.coach-photo{height:200px;margin:-22px -22px 14px;border-radius:var(--radius) var(--radius) 0 0;background:linear-gradient(135deg,var(--flame),var(--ember));background-size:cover;background-position:center;display:flex;align-items:center;justify-content:center}
.coach-photo .avatar{width:74px;height:74px;border-radius:50%;background:rgba(16,16,20,.28);color:#fff;display:flex;align-items:center;justify-content:center;font-family:'Montserrat',sans-serif;font-weight:700;font-size:1.6rem}
.coach h3{font-size:1.15rem}
.coach .role{color:var(--flame-dark);font-weight:600;font-size:.92rem;margin:2px 0 10px}
.coach .quals{font-size:.86rem;color:var(--muted)}
.coach .squads{margin-top:12px;display:flex;gap:6px;flex-wrap:wrap}
/* A coach with a bio splits the card into the existing photo/name/role column plus a bio
   column alongside it, rather than stacking the bio underneath -- keeps the card's height in
   line with ones that have no bio, so a 2-up grid of mixed cards still lines up row to row. */
.card.coach.has-bio{display:flex;align-items:stretch;gap:0}
.card.coach.has-bio .coach-main{flex:0 0 200px;min-width:0}
.card.coach.has-bio .coach-bio{flex:1;min-width:0;padding-left:26px;margin-left:26px;
  border-left:1px solid var(--line);display:flex;align-items:center}
.card.coach.has-bio .coach-bio p{margin:0;color:var(--body2);font-size:.9rem;line-height:1.55}
/* skewed ::before fill rather than a rounded pill, same call as .pill and .cal-chip -- at this
   size the full --slant-deg costs a couple of px and keeps the lean consistent */
.tag{position:relative;z-index:0;font-size:.76rem;font-weight:600;padding:3px 12px;color:var(--muted)}
.tag::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--paper);border:1px solid var(--line);
  transform:skewX(calc(-1 * var(--slant-deg)))}

/* volunteers */
.role-cat-tabs{margin-bottom:40px}
/* Below 640px the three role-cat cards ate a full screen of scroll before any actual role
   showed up, and stacked full-height it wasn't obvious they were a filter rather than content
   in their own right. So on mobile they collapse to a single-line segmented row (title only)
   and their eyebrow/description/count move into .role-cat-desc below, swapped by JS on each
   click -- same data, just relocated so the choice reads as a control, not a wall of cards. */
.role-cat-desc{display:none}
.role-list{display:grid;gap:16px}
.role-card h3{font-family:'Montserrat',sans-serif;font-weight:800;font-size:1.25rem;letter-spacing:-.01em}
.role-card .meta{display:flex;gap:32px;flex-wrap:wrap;margin:10px 0 12px}
.role-card .meta span{font-size:.82rem;color:var(--muted)}
.role-card .meta strong{color:var(--text);display:block;font-size:.78rem;text-transform:uppercase;letter-spacing:.08em}
.role-card p{font-size:.95rem;color:var(--body2);max-width:70ch}
.role-cat-count{margin-top:14px;font-size:.78rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--flame)}

/* club committee: a scrollable role list drives a detail panel, rather than one long page of
   cards -- there are ~19 posts, most with several bullets each. */
.committee-layout{display:grid;grid-template-columns:300px 1fr;gap:24px;align-items:start}
.committee-list{display:flex;flex-direction:column;gap:6px;max-height:70vh;overflow-y:auto;padding-right:10px;
  scrollbar-width:thin;scrollbar-color:var(--line) transparent}
.committee-list::-webkit-scrollbar{width:8px}
.committee-list::-webkit-scrollbar-track{background:transparent}
.committee-list::-webkit-scrollbar-thumb{background:var(--line);border-radius:999px}
.committee-list::-webkit-scrollbar-thumb:hover{background:var(--flame)}
.committee-group-label{font-family:'Montserrat',sans-serif;font-weight:800;font-size:.72rem;text-transform:uppercase;
  letter-spacing:.1em;color:var(--muted);padding:14px 4px 2px}
.committee-group-label:first-child{padding-top:4px}
.committee-item{font:inherit;color:inherit;text-align:left;cursor:pointer;background:var(--card);
  border:1px solid var(--line);border-radius:var(--radius);padding:8px 14px 8px 8px;
  display:flex;align-items:center;gap:10px;transition:border-color .15s,background .15s}
.committee-item:hover{border-color:var(--flame)}
.committee-item .tp{display:flex;flex-direction:column;gap:2px;min-width:0}
.committee-item .t{font-weight:700;font-size:.92rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.committee-item .p{font-size:.78rem;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.committee-item.active{border-color:var(--flame);background:linear-gradient(150deg,rgba(245,132,31,.16),var(--card) 65%)}
.committee-item.active .t{color:var(--flame-dark)}
body.theme-dark .committee-item.active .t{color:var(--ember)}
/* photo, or initials on a flat tint when there isn't one -- "Vacant"/blank roles show a dash
   rather than a misleading letter (see committeeInitials in site.js) */
.committee-item-photo,.committee-detail-photo{border-radius:50%;flex:0 0 auto;background-size:cover;
  background-position:center;background-color:var(--paper)}
.committee-item-photo{width:36px;height:36px}
.committee-detail-photo{width:76px;height:76px}
.committee-item-photo.initials,.committee-detail-photo.initials{display:flex;align-items:center;justify-content:center}
.committee-item-photo.initials span{font-family:'Montserrat',sans-serif;font-weight:800;font-size:.76rem;color:var(--muted)}
.committee-detail-photo.initials span{font-family:'Montserrat',sans-serif;font-weight:800;font-size:1.4rem;color:var(--muted)}
.committee-card{padding:26px 30px}
.committee-card-head{display:flex;align-items:center;gap:18px}
.committee-card h3{font-size:1.5rem}
.committee-person{color:var(--muted);margin-top:6px;font-size:.95rem}
.committee-commitment{margin-top:10px;font-size:.9rem;color:var(--body2)}
.committee-card h4{margin-top:18px;font-family:'Montserrat',sans-serif;font-weight:800;font-size:.85rem;text-transform:uppercase;letter-spacing:.06em;color:var(--muted)}
.committee-card ul{margin-top:8px;padding-left:20px;color:var(--body2);font-size:.94rem;line-height:1.6}
.committee-card li{margin-bottom:4px}
@media(max-width:820px){
  .committee-layout{grid-template-columns:1fr}
  .committee-list{flex-direction:row;overflow-x:auto;overflow-y:visible;max-height:none;padding-bottom:6px}
  .committee-item{flex:0 0 200px}
}

/* socials */
.social-card{display:flex;flex-direction:column}
/* The photo used to sit as its own rounded rectangle inside the card's padding -- now it bleeds
   all the way to the card's real edges (negative margins cancelling the .comp-card/.social-card
   padding from the bevel rule below) so the whole top of the card IS the picture. clip-path
   clips its own descendants, so on desktop the bled rectangle still comes out bevelled to match
   the card; on mobile (bevel off, plain rounded card) the art gets the matching corner radius
   directly since there's no clip-path left to do it for us. */
.social-card .art{height:132px;border-radius:0;margin:-22px -38px 14px -34px;display:flex;align-items:flex-end;padding:14px 18px;color:#fff;font-family:'Montserrat',sans-serif;font-weight:800;font-size:1.2rem;letter-spacing:-.01em;line-height:1.15;text-shadow:0 1px 6px rgba(0,0,0,.35)}
.social-card .body{padding:0;display:flex;flex-direction:column;gap:10px;flex:1}
.social-card .when{font-weight:700;color:var(--flame-dark);font-size:.9rem;text-transform:uppercase;letter-spacing:.06em}
.social-card p{font-size:.94rem;color:var(--body2);flex:1}

/* Instagram row on the News page: the social card, with the post's photo bled to the card's
   edges the same way .social-card .art is. Taller than .art because Instagram posts are square
   or portrait -- a 132px strip would crop most of them down to a sliver. */
.ig-wrap{margin:8px 0 38px}
.ig-head{display:flex;align-items:baseline;justify-content:space-between;gap:8px 16px;flex-wrap:wrap}
.ig-follow{font-size:.9rem;font-weight:600;color:var(--flame-dark)}
.ig-follow:hover{text-decoration:underline}
.ig-card .ig-photo{position:relative;display:block;height:220px;margin:-22px -38px 14px -34px;background:var(--line);overflow:hidden}
.ig-card .ig-photo img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .3s}
.ig-card .ig-photo:hover img{transform:scale(1.04)}
.ig-badge{position:absolute;top:12px;right:14px;background:rgba(16,16,20,.7);color:#fff;font-size:.7rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;padding:3px 8px;border-radius:4px}
.ig-card .ig-caption{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:4;overflow:hidden;white-space:pre-line}
@media(max-width:640px){.ig-card .ig-photo{height:200px;margin:-18px -20px 14px -20px;border-radius:var(--radius) var(--radius) 0 0}}

/* calendar */
/* Bevelled like the other Club Calendar cards (--cut-sm/--rise-sm, same scale as the info
   accordions): the month grid is dense and its height swings 4-6 rows, so the full --cut/--rise
   used on .comp-card would throw a much bigger notch than this content can spare. Side/bottom
   padding is widened past --cut-sm so the dow header and the last grid row never sit in the
   corner cut. */
.cal-card{position:relative;z-index:0;background:var(--card);border:1px solid var(--line);border-radius:0;box-shadow:var(--shadow);padding:26px 30px 30px;margin-bottom:8px;
  clip-path:polygon(var(--cut-sm) 0,100% 0,100% calc(100% - var(--rise-sm)),calc(100% - var(--cut-sm)) 100%,0 100%,0 var(--rise-sm))}
@media(max-width:760px){.cal-card{clip-path:none;border-radius:var(--radius)}}
.cal-head{display:flex;align-items:center;justify-content:center;gap:18px}
.cal-head h3{font-family:'Montserrat',sans-serif;font-weight:800;font-size:1.15rem;min-width:170px;text-align:center}
.cal-nav-btn{width:34px;height:34px;border-radius:50%;border:1.5px solid var(--line);background:#fff;font-size:1.1rem;cursor:pointer;line-height:1}
.cal-nav-btn:hover{border-color:var(--flame);color:var(--flame-dark)}
.cal-legend{display:flex;gap:16px;flex-wrap:wrap;justify-content:center;margin:14px 0 4px;font-size:.78rem;color:var(--muted)}
.cal-legend span{display:inline-flex;align-items:center;gap:6px}
.cal-dot{width:9px;height:9px;border-radius:50%;flex:0 0 auto}
.cal-dot.comp{background:var(--flame-dark)}
.cal-dot.league{background:var(--ink)}
.cal-dot.social{background:var(--flame)}
.cal-dot.training{background:var(--warn)}
.cal-dow{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:4px;margin-top:14px;font-size:.76rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);text-align:center}
.cal-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:4px;margin-top:6px}
.cal-day{min-height:88px;border:1px solid var(--line);border-radius:8px;padding:6px;display:flex;flex-direction:column;gap:3px;background:var(--paper);min-width:0}
.cal-day.out{background:transparent;border-color:transparent}
.cal-day.today{border-color:var(--flame);box-shadow:0 0 0 1px var(--flame) inset}
.cal-daynum{font-size:.78rem;font-weight:700;color:var(--muted)}
/* Same skewed-::before fill as .pill -- a chip this small carries the full --slant-deg for
   free. The fill goes on the chip itself (not clipped), while the truncating ellipsis lives on
   an inner label span, since overflow:hidden on the chip would also clip the fill's slight
   skew overflow at the free corners. */
.cal-chip{position:relative;z-index:0;font-size:.68rem;font-weight:600;color:#fff;padding:2px 6px;white-space:nowrap;cursor:default}
.cal-chip::before{content:"";position:absolute;inset:0;z-index:-1;transform:skewX(calc(-1 * var(--slant-deg)))}
.cal-chip.comp::before{background:var(--flame-dark)}
.cal-chip.league::before{background:var(--ink)}
.cal-chip.social::before{background:var(--flame)}
.cal-chip.training::before{background:var(--warn)}
.cal-chip-label{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* chips that lead somewhere (an article, or the gala on Open Meets) */
a.cal-chip{text-decoration:none;cursor:pointer}
a.cal-chip:hover::before,a.cal-chip:focus-visible::before{filter:brightness(1.18)}
a.cal-chip:hover .cal-chip-label{text-decoration:underline}
/* a day with events opens its list when tapped; the date is the keyboard way in */
.cal-day.has-items{cursor:pointer}
.cal-day.has-items:hover{border-color:var(--muted)}
.cal-day.selected{border-color:var(--ink);box-shadow:0 0 0 1px var(--ink) inset}
button.cal-daynum{all:unset;font-size:.78rem;font-weight:700;color:var(--muted);cursor:pointer;align-self:flex-start;padding:0 3px;margin:0 -3px;border-radius:4px}
button.cal-daynum:focus-visible{outline:2px solid var(--flame);outline-offset:1px}
.cal-day.selected button.cal-daynum{color:var(--ink)}
.cal-daylist{margin-top:14px;border-top:1px solid var(--line);padding-top:12px;animation:pulse-in .18s ease-out}
.cal-daylist-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:8px}
.cal-daylist-head h4{font-family:'Montserrat',sans-serif;font-weight:800;font-size:1rem;margin:0}
.cal-daylist-close{width:32px;height:32px;border-radius:50%;border:1.5px solid var(--line);background:transparent;color:inherit;font-size:1.2rem;line-height:1;cursor:pointer;flex:0 0 auto}
.cal-daylist-close:hover{border-color:var(--flame);color:var(--flame-dark)}
/* the day's events as the same cards the Socials / Competitions rows use, at the same width */
.cal-daylist-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,300px));gap:16px;padding-top:6px}
@media(max-width:640px){.cal-daylist-cards{grid-template-columns:1fr}}
@media(prefers-reduced-motion:reduce){.cal-daylist{animation:none}}
@media(max-width:760px){.cal-day{min-height:60px}.cal-chip{font-size:.6rem}.cal-legend{font-size:.72rem;gap:10px}}
/* phones: day cells are ~45px wide, so events show as coloured bars -- too small to aim at, so a
   tap anywhere on the day opens its list rather than following whichever bar was nearest */
@media(max-width:560px){.cal-card{padding:14px 10px}.cal-dow{font-size:.62rem;letter-spacing:0}.cal-grid,.cal-dow{gap:3px}.cal-day{min-height:46px;padding:4px 3px;border-radius:6px}.cal-daynum,button.cal-daynum{font-size:.68rem}.cal-chip{font-size:0;height:5px;padding:0}.cal-chip::before{transform:none;border-radius:3px}a.cal-chip{pointer-events:none}.cal-head{gap:10px}.cal-head h3{min-width:0;font-size:1rem}}
/* Open Meets: the gala the calendar linked to gets a brief highlight when the page lands on it */
.card.meet.flash{animation:row-flash 2.4s ease-out}
@media(prefers-reduced-motion:reduce){.card.meet.flash{animation:none}}

/* club calendar category rows */
.cat-row-wrap{margin-top:34px}
.cat-row-wrap h3{font-size:1.2rem;position:relative;padding-left:16px}
/* the same tick the nav dropdown and partner strip use to mark a section start, at the one
   site-wide --slant-deg -- cheap on a 4px-wide element, so it stays true even where a whole
   card can't afford to */
.cat-row-wrap h3::before{content:"";position:absolute;left:0;top:3px;bottom:3px;width:5px;
  background:linear-gradient(180deg,var(--flame),var(--flame-dark));transform:skewX(calc(-1 * var(--slant-deg)))}
.cat-row-scroll{position:relative}
.cat-row{display:flex;gap:16px;overflow-x:auto;overflow-y:hidden;padding:14px 46px 16px;scroll-behavior:smooth;scrollbar-width:none;-ms-overflow-style:none}
.cat-row::-webkit-scrollbar{display:none}
.cat-row>*{flex:0 0 300px}

/* Bevelled corners, not a full parallelogram (see --cut/--rise on .slanted above): a leaning
   card wide enough to stay readable needs ~2x66px of side padding, which is what made these
   cards feel cramped and left a huge wedge of empty page between neighbours in a row. The
   bevel keeps the sides vertical, so the 16px row gap is the gap you actually see. */
.comp-card,.social-card,.news-card{
  position:relative;z-index:0;
  background:var(--card);border:1px solid var(--line);box-shadow:var(--shadow);border-radius:0;
  clip-path:polygon(var(--cut) 0,100% 0,100% calc(100% - var(--rise)),calc(100% - var(--cut)) 100%,0 100%,0 var(--rise));
  min-height:200px;padding:22px 38px 22px 34px;display:flex;flex-direction:column;gap:8px;
}
/* Same bled-to-edge treatment as .social-card .art -- the thumb has to bleed past the card's own
   padding to reach the bevelled edges, or the clip-path cuts a visible notch out of the picture. */
.news-card .news-thumb,.comp-card .news-thumb{position:relative;margin:-22px -38px 14px -34px;border-radius:0;overflow:hidden}
/* Fades the picture into the card body instead of ending on a hard line -- the gradient matches
   --card, so it reads as the image dissolving into the card rather than a visible band. */
.news-card .news-thumb::after,.comp-card .news-thumb::after{content:"";position:absolute;inset:auto 0 0 0;height:26px;
  background:linear-gradient(180deg,transparent,var(--card));pointer-events:none}
/* The same bevel family, extended to the rest of the site's content cards.
   Which of the two bevels a card takes is decided by how tall it actually gets: the full --rise
   is 93px, so on a card shorter than that the cut runs off the top of the edge it is meant to
   trim. The plain roster/contact cards are ~90px, hence the small bevel the calendar card and
   the info accordions use; the coach, role and route cards are 200px+ and take the full bevel,
   which also keeps them matching the meet/social/news cards they sit alongside. */
.card.slanted{border-radius:0;padding:22px 26px;
  clip-path:polygon(var(--cut-sm) 0,100% 0,100% calc(100% - var(--rise-sm)),calc(100% - var(--cut-sm)) 100%,0 100%,0 var(--rise-sm))}
.card.coach,.card.role-card,.card.path-card{border-radius:0;min-height:200px;padding:22px 38px 22px 34px;
  clip-path:polygon(var(--cut) 0,100% 0,100% calc(100% - var(--rise)),calc(100% - var(--cut)) 100%,0 100%,0 var(--rise))}
/* bleeds to the bevelled edges, same as .news-card .news-thumb */
.card.coach .coach-photo{margin:-22px -38px 14px -34px;border-radius:0}
/* With a bio column alongside, the photo still bleeds to the card's top/left bevel edges but
   stops at the bio divider rather than bleeding into it. */
.card.coach.has-bio .coach-photo{margin-right:0}
/* The route cards marked hover with a flame border and selection with a 2px flame border plus a
   box-shadow ring. Both are drawn on the card's RECTANGLE and only then clipped, so on a
   bevelled card they ran along the straight edges and stopped dead at the cuts -- it read as a
   broken outline, not a highlight. So both states are carried by a warm wash plus (when
   selected) a drop-shadow glow, which works off the rendered alpha and therefore hugs the real
   bevelled silhouette -- the same call .entries-open makes for the same reason. */
.card.path-card:hover{border-color:var(--line);background:linear-gradient(150deg,rgba(245,132,31,.12),var(--card) 62%)}
.card.path-card.sel{border-color:var(--line);box-shadow:none;
  background:linear-gradient(150deg,rgba(245,132,31,.22),var(--card) 60%);
  filter:drop-shadow(0 4px 14px rgba(245,132,31,.4))}
/* Volunteering's tab cards need to read as selectable controls, not just link-styled boxes, so
   they get a stronger hover lift, and the selected one goes to a solid flame fill rather than a
   wash -- same dark-ink-on-flame pairing as .hero, which reads clearly in both themes since
   --ink stays dark regardless of theme. .path-desc exists (rather than an inline color) so the
   selected state below can override it; the count text --flame default also gets overridden. */
.path-card .path-desc{margin-top:10px;color:var(--muted);font-size:.93rem}
#roleCatTabs .path-card{transition:transform .15s,filter .15s,background .15s}
#roleCatTabs .path-card:hover{transform:translateY(-3px);background:linear-gradient(150deg,rgba(245,132,31,.2),var(--card) 58%)}
#roleCatTabs .path-card.sel{background:linear-gradient(135deg,var(--flame),var(--flame-dark));
  filter:drop-shadow(0 10px 26px rgba(245,132,31,.55))}
#roleCatTabs .path-card.sel:hover{transform:translateY(-3px)}
#roleCatTabs .path-card.sel .eyebrow{color:rgba(16,16,20,.65)}
#roleCatTabs .path-card.sel h3{color:var(--ink)}
#roleCatTabs .path-card.sel .path-desc{color:rgba(16,16,20,.78)}
#roleCatTabs .path-card.sel .role-cat-count{color:var(--ink)}
/* our own hosted meets get a warm tint so they read as "ours" even scrolled past quickly --
   paired with the .pill.hosted ribbon (added inside .comp-top by site.js) */
.comp-card.ours{background:linear-gradient(160deg,rgba(245,132,31,.14),var(--card) 55%)}
body.theme-dark .comp-card.ours{background:linear-gradient(160deg,rgba(245,132,31,.22),var(--card) 55%)}
/* a gala that is both ours and taking entries: the open-entries wash is the stronger signal */
.comp-card.ours.entries-open{background:linear-gradient(150deg,rgba(245,132,31,.20),var(--card) 62%)}
body.theme-dark .comp-card.ours.entries-open{background:linear-gradient(150deg,rgba(245,132,31,.30),var(--card) 62%)}
@media(max-width:640px){
  .cat-row>*{flex:0 0 260px}
  .comp-card,.social-card,.news-card{padding:18px 20px;min-height:0;clip-path:none;border-radius:var(--radius)}
  .social-card .art,.news-card .news-thumb,.comp-card .news-thumb{margin:-18px -20px 14px -20px;border-radius:var(--radius) var(--radius) 0 0}
  .card.slanted,.card.coach,.card.role-card,.card.path-card{position:relative;padding:22px;min-height:0;clip-path:none;border-radius:var(--radius)}
  .card.coach .coach-photo{margin:-22px -22px 14px;border-radius:var(--radius) var(--radius) 0 0}
  /* Below the bevel breakpoint there's no room for the bio beside the card -- stack it under
     the existing content instead, same as a mobile meet/social card losing its side-by-side layout. */
  .card.coach.has-bio{flex-direction:column}
  .card.coach.has-bio .coach-main{flex:0 0 auto}
  .card.coach.has-bio .coach-bio{padding-left:0;margin-left:0;margin-top:14px;padding-top:14px;
    border-left:none;border-top:1px solid var(--line)}
  #roleCatTabs.role-cat-tabs{grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:16px}
  #roleCatTabs .path-card{padding:12px 10px;text-align:center}
  #roleCatTabs .path-card .eyebrow,#roleCatTabs .path-card .path-desc,#roleCatTabs .path-card .role-cat-count{display:none}
  #roleCatTabs .path-card h3{margin-top:0;font-size:.9rem;line-height:1.2}
  .role-cat-desc{display:block;padding:14px 16px;margin-bottom:24px;border:1.5px solid var(--line);border-radius:var(--radius);background:var(--card)}
  .role-cat-desc .eyebrow{margin-bottom:6px}
  .role-cat-desc .path-desc{color:var(--body2);font-size:.9rem;margin:0}
  .role-cat-desc .role-cat-count{margin-top:8px}
}
.cat-arrow{position:absolute;top:50%;transform:translateY(-50%);width:38px;height:38px;border-radius:50%;background:rgba(255,255,255,.92);backdrop-filter:blur(4px);border:1px solid var(--line);color:var(--ink);font-size:1.3rem;line-height:1;display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 4px 14px rgba(16,16,20,.16);z-index:2;padding:0;transition:opacity .2s,background .2s,border-color .2s}
.cat-arrow:hover{background:#fff;border-color:var(--flame);color:var(--flame-dark)}
.cat-arrow.prev{left:2px}
.cat-arrow.next{right:2px}
.cat-arrow:disabled{opacity:0;pointer-events:none}
@media(max-width:640px){.cat-row{padding-left:8px;padding-right:8px}.cat-arrow{display:none}}

/* squad timetables */
.tt-views{display:inline-flex;border:1.5px solid var(--line);border-radius:10px;padding:3px;background:var(--card);margin-bottom:16px}
.tt-views button{font:inherit;font-weight:600;font-size:.85rem;border:none;background:none;color:var(--muted);padding:8px 14px;border-radius:7px;cursor:pointer}
.tt-views button.active{background:var(--flame);color:#fff}
.tt-chips{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:22px}
.tt-chip{position:relative;z-index:0;font:inherit;font-weight:600;font-size:.85rem;padding:8px 16px;border:none;background:none;color:var(--text);cursor:pointer}
.tt-chip::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--card);border:1.5px solid var(--line);
  transform:skewX(calc(-1 * var(--slant-deg)));transition:background .15s,border-color .15s}
.tt-chip:hover::before{border-color:var(--flame)}
.tt-chip.active{color:#fff}
.tt-chip.active::before{background:var(--flame);border-color:var(--flame)}
.tt-select{display:grid;gap:6px;font-size:.8rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);width:100%;max-width:320px}
.tt-select select{font:inherit;font-size:1rem;font-weight:600;text-transform:none;letter-spacing:0;color:var(--text);background:var(--field);border:1.5px solid var(--line);border-radius:10px;padding:11px 40px 11px 13px;cursor:pointer;appearance:none;-webkit-appearance:none;
  background-image:linear-gradient(45deg,transparent 50%,var(--flame) 50%),linear-gradient(135deg,var(--flame) 50%,transparent 50%);background-position:calc(100% - 20px) 50%,calc(100% - 14px) 50%;background-size:6px 6px;background-repeat:no-repeat}
.tt-select select:hover{border-color:var(--flame)}
.tt-select select:focus{border-color:var(--flame);outline:none;box-shadow:0 0 0 3px rgba(245,132,31,.25)}
.tt-head{display:flex;justify-content:space-between;align-items:flex-end;gap:10px 16px;flex-wrap:wrap;margin-bottom:18px}
.tt-head h3{font-size:1.5rem}
.tt-lead{color:var(--muted);font-size:.92rem;margin-top:4px}
.tt-lead strong{color:var(--text)}
.tt-stats{font-size:.82rem;color:var(--muted)}
.tt-grid{display:grid;grid-template-columns:40px repeat(7,minmax(0,1fr));gap:6px}
.tt-dow{font-size:.74rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);text-align:center;padding:2px 0}
.tt-dow.today{color:var(--flame-dark)}
.tt-period{font-size:.72rem;font-weight:800;letter-spacing:.08em;color:var(--muted);display:flex;align-items:center;justify-content:center}
.tt-cell{min-height:80px;border:1px solid var(--line);border-radius:8px;padding:5px;display:flex;flex-direction:column;gap:5px;background:var(--paper)}
.tt-cell.today{border-color:var(--flame)}
.tt-sess{background:var(--card);border-left:3px solid var(--flame);border-radius:6px;padding:6px 7px}
.tt-sess .time{font-weight:700;font-size:.8rem}
.tt-sess .loc{font-size:.72rem;color:var(--muted);line-height:1.3;margin-top:1px}
.tt-sess.land{border-left-color:var(--muted)}
.tt-tag{position:relative;z-index:0;display:inline-block;font-size:.62rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;padding:1px 7px;color:var(--text);margin-left:5px;vertical-align:1px}
.tt-tag::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--line);transform:skewX(calc(-1 * var(--slant-deg)))}
.tt-list{display:none}
.tt-day h4{font-size:.95rem;margin-bottom:4px}
.tt-day+.tt-day{margin-top:14px}
.tt-row{display:grid;grid-template-columns:34px 100px minmax(0,1fr);gap:4px 10px;padding:8px 0;border-top:1px solid var(--line);font-size:.9rem;align-items:baseline}
.tt-row.club{grid-template-columns:100px minmax(0,260px) minmax(0,1fr)}
.tt-row .muted{color:var(--muted)}
.tt-ampm{font-size:.72rem;font-weight:800;color:var(--flame-dark)}
.tt-group{font-size:.74rem;font-weight:800;letter-spacing:.1em;color:var(--flame-dark);margin:14px 0 2px}
.tt-head+.tt-group{margin-top:0}
@media(max-width:760px){
  .tt-grid{display:none}.tt-list{display:block}
  .tt-row{grid-template-columns:30px minmax(0,1fr)}
  .tt-row>span:last-child{grid-column:2;color:var(--muted)}
  .tt-row.club{grid-template-columns:96px minmax(0,1fr)}
  .tt-row.club .muted{grid-column:2}
}

/* squad pathway (pathway.js): Bronze/Silver/Gold side by side on top of Junior Pathway and the
   Academy hats, Masters alongside; the chosen squad's details open in the box underneath */
.pw-diagram{display:grid;grid-template-columns:minmax(0,1fr) 210px;gap:22px;align-items:start}
.pw-lanes{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}
.pw-lane{display:flex;flex-direction:column;background:color-mix(in srgb,var(--c) 10%,var(--card));
  border:1px solid color-mix(in srgb,var(--c) 35%,transparent);border-top:4px solid var(--c);border-radius:var(--radius);padding:14px 10px 18px}
.pw-lanes .pw-lane{min-height:290px}
.pw-lane-head{text-align:center;margin-bottom:14px}
.pw-lane-head h4{font-size:1.05rem;font-weight:800;text-transform:uppercase;letter-spacing:.1em}
.pw-lane-head span{display:block;font-size:.76rem;font-weight:600;color:var(--muted);margin-top:1px}
.pw-stack{flex:1;display:flex;flex-direction:column;justify-content:space-around;gap:12px}

/* a squad: the site's slanted button shape in the squad's colour */
.pw-card{position:relative;z-index:0;font:inherit;border:none;background:none;cursor:pointer;margin:0 10px;padding:10px 16px;
  color:var(--ink);display:flex;flex-direction:column;align-items:center;text-align:center;line-height:1.15;transition:opacity .2s,transform .15s}
.pw-card::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--c);transform:skewX(calc(-1 * var(--slant-deg)));
  box-shadow:0 2px 8px rgba(16,16,20,.16);transition:box-shadow .15s}
.pw-card.light{color:#fff}
.pw-card strong{font-weight:800;font-size:1rem}
.pw-card span{font-size:.74rem;font-weight:600;opacity:.85;margin-top:2px}
.pw-card:hover{transform:scale(1.04)}
.pw-card:focus-visible{outline:none}
.pw-card:focus-visible::before,.pw-card.sel::before{box-shadow:0 0 0 3px var(--card),0 0 0 6px var(--flame),0 6px 16px rgba(16,16,20,.22)}
.pw-diagram.has-sel .pw-card:not(.sel){opacity:.5}

.pw-ups{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));text-align:center;color:var(--muted);font-weight:800;font-size:1.3rem;line-height:1;padding:8px 0}
.pw-ups.single{grid-template-columns:1fr}
.pw-base{display:flex;flex-direction:column}
.pw-base .pw-card{padding:14px 16px}
.pw-base .pw-card strong{font-size:1.2rem}
.pw-hats{text-align:center}
.pw-hats .pw-sub{margin-bottom:8px}
.pw-hat-row{display:flex;align-items:center;justify-content:center;gap:2px}
.pw-hats .pw-card{margin:0 8px;min-width:116px}
.pw-arrow{color:var(--muted);font-weight:800}

.pw-detail{position:relative;margin-top:26px;background:var(--card);border:1px solid var(--line);border-top:3px solid var(--flame);
  border-radius:var(--radius);box-shadow:var(--shadow);padding:22px 26px 24px;display:grid;grid-template-columns:minmax(0,1.3fr) minmax(0,1fr);gap:18px 34px}
.pw-detail.empty{display:block;text-align:center;padding:16px;background:none;box-shadow:none;border:1.5px dashed var(--line)}
.pw-detail h3{font-size:1.7rem;margin-top:4px;padding-right:30px}
.pw-close{position:absolute;top:10px;right:12px;width:36px;height:36px;border:none;background:none;color:var(--muted);font-size:1.6rem;line-height:1;cursor:pointer;border-radius:8px}
.pw-close:hover{color:var(--flame-dark);background:var(--paper)}
.pw-level{color:var(--flame-dark);font-weight:700;font-size:.92rem;margin-top:4px}
.pw-blurb{color:var(--body2);font-size:.95rem;margin-top:12px}
.pw-facts{display:grid;gap:10px;align-content:start;padding-top:6px}
.pw-facts div{border-top:1px solid var(--line);padding-top:9px}
.pw-facts div:first-child{border-top:none;padding-top:0}
.pw-facts dt,.pw-sub{font-size:.72rem;font-weight:800;text-transform:uppercase;letter-spacing:.1em;color:var(--muted)}
.pw-facts dd{font-size:.93rem;font-weight:600;margin-top:2px}
.pw-muted{color:var(--muted);font-weight:500}
.pw-hours{display:flex;align-items:baseline;gap:8px}
.pw-hours strong{font-size:1.7rem;font-weight:800;line-height:1.1}
.pw-hours span{color:var(--muted);font-weight:600}
.pw-hours-split{font-size:.85rem;color:var(--muted);font-weight:500;margin-top:2px}
.pw-actions{display:flex;flex-wrap:wrap;gap:10px 14px;margin-top:18px}
.pw-actions .btn.ghost{color:var(--text)}
.pw-actions .btn.ghost[aria-pressed="true"]{color:var(--flame-dark)}
.pw-note{color:var(--muted);font-size:.92rem;margin-top:16px;max-width:70ch}
.pw-note strong{color:var(--text)}

@media(max-width:860px){
  .pw-diagram{grid-template-columns:1fr}
  .pw-side .pw-stack{flex-direction:row;justify-content:center}
  .pw-side .pw-card{flex:0 1 180px}
}
@media(max-width:640px){
  .pw-lanes{gap:8px}
  .pw-lane{padding:12px 4px 14px}
  .pw-lanes .pw-lane{min-height:250px}
  .pw-lane-head h4{font-size:.9rem;letter-spacing:.06em}
  .pw-lane-head span{font-size:.68rem}
  .pw-card{margin:0 7px;padding:8px 6px}
  .pw-card strong{font-size:.86rem}
  .pw-card span{font-size:.68rem}
  .pw-base .pw-card strong{font-size:1.05rem}
  /* four hats in a row, read left to right; no room for arrows between them */
  .pw-hat-row{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}
  .pw-hats .pw-card{min-width:0;margin:0 5px}
  .pw-hats .pw-card strong{font-size:.78rem}
  .pw-arrow{display:none}
  .pw-detail{grid-template-columns:1fr;padding:20px 18px}
  .pw-detail h3{font-size:1.4rem}
}

/* forms */
form.stack{display:grid;gap:16px;max-width:560px}
.f{display:grid;gap:6px;font-size:.8rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--muted)}
label.f input,label.f select,label.f textarea{font:inherit;font-size:1rem;font-weight:400;text-transform:none;letter-spacing:0;color:var(--text);padding:11px 13px;border:1.5px solid var(--line);border-radius:10px;background:var(--field)}
label.f input:focus,label.f select:focus,label.f textarea:focus{border-color:var(--flame);outline:none;box-shadow:0 0 0 3px rgba(242,107,33,.18)}
.hint{font-size:.85rem;color:var(--muted);font-weight:400;text-transform:none;letter-spacing:normal}
label.f.checkbox-f{display:flex;align-items:center;gap:10px}
label.f.checkbox-f input{all:revert;width:18px;height:18px;accent-color:var(--flame)}
/* News form: "Which squads is this for?" */
.squad-picks{display:flex;flex-wrap:wrap;gap:8px 18px;margin-top:4px}
.squad-pick{display:flex;align-items:center;gap:8px;color:var(--text);font-weight:600;text-transform:none;letter-spacing:0;cursor:pointer}
.squad-pick input{width:18px;height:18px;accent-color:var(--flame)}
.tag-group-label{margin:10px 0 0;font-size:.75rem;font-weight:800;text-transform:uppercase;letter-spacing:.08em;color:var(--muted)}
/* A gala's news article (meetarticle field): set apart at the foot of the gala form */
.meet-article{border-top:1px solid var(--line);padding-top:6px}
.tag-add{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-top:4px}
.tag-add input{font:inherit;font-size:.95rem;color:var(--text);padding:8px 11px;border:1.5px solid var(--line);border-radius:10px;background:var(--field);min-width:0;flex:1 1 180px;max-width:280px}
.tag-add input:focus{border-color:var(--flame);outline:none}

/* info accordions */
/* Bevelled like the cards (--cut-sm/--rise-sm), not skewed: an accordion is 52px shut and can
   be 250px open, and a full parallelogram that reads as a neat 9px lean shut would throw a
   45px wedge across the text open. The bevel holds the same exact --slant-deg at either size.
   A border cannot follow a clip-path, so the 1.5px outline is faked with two stacked layers:
   ::before is the border colour at full size, ::after the panel fill inset by 1.5px, both
   bevelled. (Off the diagonal the band is 1.5px; along it, 1.9px -- not something the eye
   picks up.) The parent's clip-path also clips the summary's hover wash and focus ring to the
   real silhouette, which is exactly what we want. Side padding is up to clear the cut. */
details.info{position:relative;z-index:0;background:none;border:none;border-radius:0;padding:0;margin-bottom:12px;
  clip-path:polygon(var(--cut-sm) 0,100% 0,100% calc(100% - var(--rise-sm)),calc(100% - var(--cut-sm)) 100%,0 100%,0 var(--rise-sm))}
details.info::before,details.info::after{content:"";position:absolute;z-index:-1;transition:background-color .15s}
details.info::before{inset:0;background:var(--line)}
details.info::after{inset:1.5px;background:var(--card);
  clip-path:polygon(var(--cut-sm) 0,100% 0,100% calc(100% - var(--rise-sm)),calc(100% - var(--cut-sm)) 100%,0 100%,0 var(--rise-sm))}
details.info summary{cursor:pointer;list-style:none;padding:16px 24px;font-weight:700;display:flex;justify-content:space-between;align-items:center;gap:12px;transition:background-color .15s}
details.info summary:hover{background:rgba(245,132,31,.08)}
details.info summary:focus-visible{outline:2px solid var(--flame);outline-offset:-2px}
details.info summary::-webkit-details-marker{display:none}
details.info summary::after{content:"+";flex:0 0 auto;width:28px;height:28px;border-radius:50%;background:var(--flame);color:#fff;font-family:'Montserrat',sans-serif;font-size:1.2rem;line-height:1;display:flex;align-items:center;justify-content:center}
details.info[open]::before{background:var(--flame)}
details.info[open] summary::after{content:"\2013"}
details.info .body{padding:4px 24px 22px;color:var(--muted);font-size:.95rem}
details.info .body .link-line{padding:8px 0;border-top:1px solid var(--line)}
details.info .body .link-line:first-child{border-top:none}
/* A meet link line given a highlight colour in the members' area (LINK_HIGHLIGHTS in core.js).
   Translucent tints, so the same colours sit right on the light and the dark cards. */
details.info .body .link-line[class*="hl-"]{padding:8px 12px;margin:2px 0;border-top-color:transparent;border-left:4px solid var(--hl-edge);background:var(--hl-bg);color:var(--text)}
details.info .body .link-line[class*="hl-"]+.link-line{border-top-color:transparent}
.hl-orange{--hl-bg:rgba(245,132,31,.16);--hl-edge:#f5841f}
.hl-yellow{--hl-bg:rgba(240,196,25,.24);--hl-edge:#e0b400}
.hl-green{--hl-bg:rgba(31,138,76,.16);--hl-edge:#1f8a4c}
.hl-blue{--hl-bg:rgba(26,111,212,.15);--hl-edge:#1a6fd4}
.hl-red{--hl-bg:rgba(179,38,30,.15);--hl-edge:#d0342a}
details.info .body a{display:inline-flex;align-items:center;gap:6px;font-weight:700;color:var(--flame-dark);text-decoration:underline;text-underline-offset:3px}
details.info .body a:hover{color:var(--flame)}
details.info .body a::after{content:"\2192";text-decoration:none;transition:transform .15s}
details.info .body a:hover::after{transform:translateX(3px)}

/* footer */
footer.site{background:var(--ink);color:#c9c9cf;margin-top:20px;border-top:3px solid var(--flame)}
.foot-grid{display:grid;grid-template-columns:1.3fr 1fr 1fr;gap:32px;padding:44px 20px;max-width:1120px;margin:0 auto}
footer.site h4{color:#fff;font-family:'Montserrat',sans-serif;text-transform:uppercase;letter-spacing:.06em;margin-bottom:12px;font-size:1.05rem}
footer.site a{color:#c9c9cf;text-decoration:none;display:block;padding:4px 0;font-size:.92rem}
footer.site a:hover{color:var(--ember)}
.foot-base{border-top:1px solid rgba(255,255,255,.1);padding:16px 20px;font-size:.8rem;color:#84848c;text-align:center}
@media(max-width:760px){.foot-grid{grid-template-columns:1fr}}

/* ---------- admin ---------- */
#admin{min-height:100vh;min-height:100dvh;background:var(--paper);color:var(--text)}
.admin-top{display:flex;justify-content:space-between;align-items:center;padding:14px 22px;border-bottom:1px solid var(--line);position:sticky;top:0;background:var(--paper);z-index:5}
.admin-top .who{font-size:.88rem;color:var(--muted)}
.admin-top .who strong{color:var(--ember)}
.admin-shell{display:grid;grid-template-columns:230px 1fr;min-height:calc(100vh - 61px);min-height:calc(100dvh - 61px)}
.admin-side{border-right:1px solid var(--line);padding:20px 12px;display:flex;flex-direction:column;gap:4px}
.admin-side button{background:none;border:none;color:var(--body2);font:inherit;font-weight:600;text-align:left;padding:11px 14px;border-radius:9px;cursor:pointer}
.admin-side button:hover{background:var(--card)}
.admin-side button.active{background:var(--flame);color:#fff}
.admin-main{padding:28px 30px 60px;max-width:960px}
.admin-main h2{font-family:'Montserrat',sans-serif;font-weight:800;font-size:1.8rem;color:var(--text);letter-spacing:-.01em}
.admin-note{background:var(--card);border:1px solid var(--line);border-left:4px solid var(--flame);border-radius:10px;padding:12px 16px;font-size:.88rem;color:var(--body2);margin:16px 0 24px}
.item-block{margin-bottom:12px}
.admin-sub{font-size:.8rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--muted);margin:26px 0 10px}
#itemList>.admin-sub:first-child{margin-top:0}
/* Club Feed filter rows: the News page's tag chips, a touch smaller, with a count in each */
.admin-filter{gap:8px;margin:0 0 12px;align-items:center}
.admin-filter .news-tag-chip{font-size:.72rem;padding:7px 14px}
.admin-filter .chip-n{opacity:.6;font-weight:600;margin-left:3px}
.admin-filter-label{font-size:.72rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--muted);margin-right:4px}
.admin-filter+.admin-sub{margin-top:22px}
.item-block .item-row{margin-bottom:0}
.item-block:has(.edit-slot:not(:empty)) .item-row{border-radius:12px 12px 0 0;border-bottom-color:transparent}
.item-row{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:16px 18px;display:flex;justify-content:space-between;gap:16px;align-items:center;flex-wrap:wrap}
.item-row .t{font-weight:700;color:var(--text)}
.item-row .s{font-size:.85rem;color:var(--muted);margin-top:2px}
.item-row .acts{display:flex;gap:8px}
/* Club Feed: where each item stands on the homepage slideshow (members.js homeBadges). A row
   on the homepage gets a flame edge; a pinned one a solid flame edge plus a warm tint, so both
   read from across the list before any badge text is. */
.item-row.on-home{border-left:4px solid var(--ember)}
.item-row.is-pinned{border-left:4px solid var(--flame);background:linear-gradient(90deg,#fdeee2 0%,var(--card) 60%)}
.feed-badges{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
.feed-badge{font-size:.72rem;font-weight:700;padding:3px 9px;border-radius:999px;line-height:1.4}
.feed-badge.home{background:#e6f4ec;color:var(--ok)}
.feed-badge.pin{background:var(--flame);color:#fff}
.feed-badge.note{background:transparent;color:var(--muted);border:1px solid var(--line);font-weight:600}
.feed-badge.off{background:#f2f2f0;color:var(--muted)}
.item-block.flash .item-row{animation:row-flash 1.6s ease-out}
@keyframes row-flash{0%,30%{box-shadow:0 0 0 3px var(--flame)}100%{box-shadow:0 0 0 3px transparent}}
@media(prefers-reduced-motion:reduce){.item-block.flash .item-row{animation:none;box-shadow:0 0 0 3px var(--flame)}}
.home-panel{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:14px 18px 12px;margin:0 0 20px}
.home-panel .admin-sub{margin:0 0 8px}
.home-slides{margin:0;padding-left:22px;display:grid;gap:6px}
.home-slides li{font-size:.9rem;color:var(--text)}
.home-slides li::marker{font-weight:700;color:var(--muted)}
.home-slides li.is-pinned::marker{color:var(--flame)}
.home-slide-link{background:none;border:0;padding:0;font:inherit;font-weight:700;color:var(--text);cursor:pointer;text-align:left;text-decoration:underline;text-decoration-color:var(--line);text-underline-offset:3px}
.home-slide-link:hover,.home-slide-link:focus-visible{text-decoration-color:var(--flame)}
.home-slide-meta{display:block;font-size:.8rem;color:var(--muted)}
@media(min-width:640px){.home-slide-meta{display:inline;margin-left:8px}}
/* Arranging the slideshow: pin and up/down on each row; the slides past the homepage's count are
   the next in line, dimmed under a divider */
.home-slides-hint{margin:0 0 10px;font-size:.84rem;color:var(--muted)}
/* the buttons stay on the right of every row; a long title wraps beside them, not over them */
.home-slide-row{display:flex;align-items:center;justify-content:space-between;gap:10px}
.home-slide-row>div:first-child{flex:1;min-width:0}
.home-slide-acts{display:flex;align-items:center;gap:6px;flex-shrink:0}
@media(max-width:560px){.home-slide-row{flex-wrap:wrap}}
.home-slide-acts .doclink-move button{height:32px;width:30px}
.home-slide-pin{background:none;border:1.5px solid var(--line);color:var(--muted);border-radius:8px;height:32px;padding:0 10px;cursor:pointer;font:inherit;font-size:.78rem;font-weight:700}
.home-slide-pin:hover{border-color:var(--flame);color:var(--text)}
.home-slide-pin.on{border-color:var(--flame);color:var(--text)}
.home-slide-acts button:disabled{opacity:.35;cursor:default}
.home-slide-title{font-weight:700}
.home-slide-off{background:none;border:1.5px solid var(--line);color:var(--warn);border-radius:8px;height:32px;width:32px;padding:0;cursor:pointer;font:inherit;font-size:.95rem;font-weight:700}
.home-slide-off:hover,.home-slide-off:focus-visible{border-color:var(--warn);background:var(--warn);color:#fff}
body.theme-dark .home-slide-off{color:#ff7a70}
.home-slides-off-head{margin:14px 0 6px;font-size:.78rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--muted)}
.home-slides-off{list-style:none;padding-left:0}
.home-slides-off li{opacity:.7}
.home-slides li.is-next{opacity:.7}
.home-slides li.home-slides-break{display:block;list-style:none;margin:6px 0 0 -22px;padding-top:8px;border-top:1px dashed var(--line);font-size:.78rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--muted)}
/* Instagram section: the one-off setup guide folds away once a feed is connected, and each
   post row is a thumbnail + caption with its "Show on website" tick. An unticked post fades
   so hidden ones stand out when scanning the list. */
.ig-setup{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:0 18px;max-width:760px}
.ig-setup>summary{cursor:pointer;padding:14px 0;font-weight:700;color:var(--text)}
.ig-setup[open]>summary{border-bottom:1px solid var(--line)}
.ig-setup-body{padding:12px 0 16px;font-size:.92rem;color:var(--body2);line-height:1.55}
.ig-setup-body ol,.ig-setup-body ul{padding-left:22px;display:grid;gap:8px;margin:0 0 12px}
.ig-setup-body a{color:var(--flame-dark);text-decoration:underline}
.ig-setup-body code{font-size:.85em;background:var(--field);padding:1px 5px;border-radius:4px;overflow-wrap:anywhere}
.ig-admin-row{margin-bottom:10px;transition:opacity .2s}
.ig-admin-row.is-hidden{opacity:.5}
.ig-admin-post{display:flex;gap:14px;align-items:center;flex:1 1 320px;min-width:0}
.ig-admin-post img,.ig-admin-noimg{width:64px;height:64px;object-fit:cover;border-radius:8px;flex:0 0 64px;background:var(--line)}
.ig-admin-post>div{min-width:0}
.ig-admin-caption{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}
.ig-admin-row a.s{display:inline-block;color:var(--flame-dark)}
.ig-admin-row label.checkbox-f{white-space:nowrap}
.edit-slot:not(:empty){background:var(--card);border:1px solid var(--line);border-top:none;border-radius:0 0 12px 12px;padding:2px 18px 18px}
.edit-slot form.stack{margin-top:0!important}
#admin form.stack{max-width:640px;background:var(--card);border:1px solid var(--line);border-radius:14px;padding:22px}
#admin .f{color:var(--muted)}
#admin label.f input,#admin label.f select,#admin label.f textarea{background:var(--field);border-color:var(--line);color:var(--text)}
#admin .form-title{font-weight:700;color:var(--text);font-size:1.05rem}
.login-wrap{max-width:460px;margin:8vh auto;padding:0 20px}
.login-wrap .card{background:var(--card);border-color:var(--line);color:var(--text)}
.role-pick{display:grid;gap:8px;margin:18px 0}
.role-pick button{background:var(--field);border:1.5px solid var(--line);color:var(--text);font:inherit;font-weight:600;padding:12px 14px;border-radius:10px;cursor:pointer;text-align:left;display:flex;justify-content:space-between;align-items:center}
.role-pick button:hover{border-color:var(--flame)}
.role-pick button.sel{border-color:var(--flame);background:rgba(242,107,33,.12)}
.role-pick .desc{font-size:.78rem;color:var(--muted);font-weight:400}
#admin form.squad-form{max-width:none}
/* Squads > Squad details: one box per squad, edged in its pathway colour */
.sqd-squad{border:1.5px solid var(--line);border-left:5px solid var(--c);border-radius:10px;padding:12px 14px 14px;margin:0 0 12px;display:grid;gap:12px;background:var(--card)}
.sqd-squad legend{font-weight:800;padding:0 6px;font-size:.98rem}
.sqd-squad legend span{font-weight:600;font-size:.78rem;color:var(--muted);margin-left:4px}
.sqd-row{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,2fr);gap:12px}
@media (max-width:600px){.sqd-row{grid-template-columns:1fr}}
.sqd-save{position:sticky;bottom:0;padding:12px 0;background:var(--paper)}
.sess-title{font-size:.8rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);margin-bottom:6px}
.sess-rows{display:grid;gap:8px;margin-bottom:10px}
.sess-row{display:grid;grid-template-columns:1fr .8fr .8fr 44px 2.6fr .8fr 38px;gap:8px;align-items:center}
.sess-row input,.sess-row select{font:inherit;font-size:.9rem;padding:8px 9px;border:1.5px solid var(--line);border-radius:8px;background:var(--field);color:var(--text);min-width:0;width:100%}
.sess-row input:focus,.sess-row select:focus{border-color:var(--flame);outline:none}
.sess-head{font-size:.7rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--muted)}
.sess-ampm{text-align:center;font-weight:800;font-size:.78rem;color:var(--flame-dark)}
body.theme-dark .sess-ampm{color:var(--ember)}
.sess-del{background:none;border:1.5px solid var(--line);color:var(--warn);border-radius:8px;height:38px;cursor:pointer;font-size:1.1rem;line-height:1}
.sess-del:hover{border-color:var(--warn)}
/* Meet documents & links editor: name, link text, URL, highlight, move, remove. */
.doclink-rows{display:grid;gap:8px}
.doclink-rows:empty{display:none}
.doclink-row{display:grid;grid-template-columns:1.3fr 1fr 1.6fr .9fr auto 38px;gap:8px;align-items:center;padding:6px;border-radius:10px;border-left:4px solid var(--hl-edge,transparent);background:var(--hl-bg,transparent)}
.doclink-row input,.doclink-row select{font:inherit;font-size:.9rem;padding:8px 9px;border:1.5px solid var(--line);border-radius:8px;background:var(--field);color:var(--text);min-width:0;width:100%}
.doclink-row input:focus,.doclink-row select:focus{border-color:var(--flame);outline:none}
.doclink-move{display:flex;gap:4px}
.doclink-move button{background:none;border:1.5px solid var(--line);color:var(--muted);border-radius:8px;width:32px;height:38px;cursor:pointer;font-size:1rem;line-height:1}
.doclink-move button:hover{border-color:var(--flame);color:var(--text)}
.doclink-row .sess-del{height:38px}
@media(max-width:700px){
  .sess-head{display:none}
  .doclink-row{grid-template-columns:repeat(4,minmax(0,1fr));grid-template-areas:"label label label label" "text text text text" "url url url url" "hl hl move del";border:1px solid var(--line);padding:10px}
  .doclink-row [data-k="label"]{grid-area:label}
  .doclink-row [data-k="text"]{grid-area:text}
  .doclink-row [data-k="url"]{grid-area:url}
  .doclink-row [data-k="hl"]{grid-area:hl}
  .doclink-row .doclink-move{grid-area:move;justify-self:end}
  .doclink-row .sess-del{grid-area:del}
  .sess-row{grid-template-columns:repeat(4,minmax(0,1fr));grid-template-areas:"day day day ampm" "start start end end" "loc loc loc loc" "type type type del";border:1px solid var(--line);border-radius:10px;padding:10px}
  .sess-row [data-k="day"]{grid-area:day}
  .sess-row [data-k="start"]{grid-area:start}
  .sess-row [data-k="end"]{grid-area:end}
  .sess-row .sess-ampm{grid-area:ampm}
  .sess-row [data-k="loc"]{grid-area:loc}
  .sess-row [data-k="type"]{grid-area:type}
  .sess-row .sess-del{grid-area:del}
}
@media(max-width:560px){
  .admin-top{padding:10px 16px;gap:10px}
  .admin-top .brand small{display:none}
  .admin-top .brand .name{font-size:.95rem}
  .admin-top .who{font-size:.76rem;line-height:1.3}
  .admin-top .btn{white-space:nowrap}
  .edit-slot:not(:empty){padding:2px 8px 8px}
  #admin form.stack{padding:16px 12px}
  .admin-top .theme-toggle{width:36px;height:36px;flex:0 0 auto}
}
@media(max-width:820px){.admin-shell{grid-template-columns:1fr}.admin-side{flex-direction:row;overflow-x:auto;border-right:none;border-bottom:1px solid var(--line)}.admin-side button{white-space:nowrap}.admin-main{padding:22px 18px 60px}}

/* ---------- black & orange theme (default; toggle in header) ---------- */
body.theme-dark{--paper:#0d0d11;--card:#1e1e26;--line:#3a3a44;--muted:#a5a3a0;--text:#eceae6;--body2:#c9c7c2;--field:#0f0f14;
  --shadow:0 1px 2px rgba(0,0,0,.5),0 6px 20px rgba(0,0,0,.35)}
body.theme-dark header.site{background:#111116;color:#fff;box-shadow:0 1px 0 #282830}
body.theme-dark .brand{color:#fff}
body.theme-dark .brand .name .line-two{color:var(--ember)}
body.theme-dark .cal-day.selected{border-color:var(--text);box-shadow:0 0 0 1px var(--text) inset}
body.theme-dark .cal-day.selected button.cal-daynum{color:var(--text)}
/* dark desktop nav: the flame fill reads fine on the dark bar unchanged -- only the
   plain (non-active) text colors need to shift for the dark background */
@media(min-width:1024px){
  body.theme-dark nav.main a{color:#dcdad4}
  body.theme-dark .nav-dropdown-toggle{color:#dcdad4}
  body.theme-dark .nav-dropdown-menu{background:transparent;border-color:transparent}
  body.theme-dark .nav-dropdown-menu a{color:#e4e2de}
  body.theme-dark nav.main .nav-dropdown-menu a::before{background:#26262f;border-color:#48484f;box-shadow:0 6px 16px rgba(0,0,0,.55)}
  body.theme-dark nav.main .nav-dropdown-menu a:hover::before,
  body.theme-dark nav.main .nav-dropdown-menu a:focus-visible::before,
  body.theme-dark nav.main .nav-dropdown-menu a.active::before{
    background:var(--flame);border-color:transparent;
    box-shadow:0 8px 18px rgba(0,0,0,.5);
  }
  body.theme-dark .nav-dropdown-menu a:hover,
  body.theme-dark .nav-dropdown-menu a:focus-visible,
  body.theme-dark .nav-dropdown-menu a.active{color:#fff}
  body.theme-dark .nav-dropdown-menu a:hover::after,
  body.theme-dark .nav-dropdown-menu a:focus-visible::after,
  body.theme-dark .nav-dropdown-menu a.active::after{background:#fff}
}
/* dark mobile drawer: same skewed panels, just recolored -- only the resting panel and the
   plain text need shifting, the flame fill reads correctly on either ground */
@media(max-width:1023px){
  body.theme-dark nav.main{background:#111116;box-shadow:0 12px 24px rgba(0,0,0,.45)}
  body.theme-dark nav.main a,body.theme-dark .nav-dropdown-toggle{color:#e4e2de}
  body.theme-dark nav.main a::before,body.theme-dark .nav-dropdown-toggle::before{background:#16161c;border-color:#31313a}
  body.theme-dark nav.main a:active::before,body.theme-dark .nav-dropdown-toggle:active::before{background:#221c16;border-color:var(--flame)}
  /* the resting-panel rule above outranks the light theme's fill selectors, so the filled
     states have to be restated here or the current page and the CTA come out blank */
  body.theme-dark nav.main a.active::before,
  body.theme-dark nav.main a.cta::before,
  body.theme-dark .nav-dropdown-toggle.active::before,
  body.theme-dark .nav-dropdown.open .nav-dropdown-toggle::before{
    background:var(--flame);border-color:transparent;
  }
  body.theme-dark nav.main a.active,body.theme-dark nav.main a.cta,
  body.theme-dark .nav-dropdown-toggle.active,body.theme-dark .nav-dropdown.open .nav-dropdown-toggle{color:#101014}
  body.theme-dark nav.main .nav-dropdown-menu a.active::after{background:#101014}
}
body.theme-dark .burger{color:#fff;border-color:rgba(255,255,255,.3)}
body.theme-dark .theme-toggle{color:#fff;border-color:rgba(255,255,255,.3)}
body.theme-dark .eyebrow{color:var(--ember)}
body.theme-dark .lane-rope:not(.on-dark){background:repeating-linear-gradient(90deg,var(--flame) 0 16px,transparent 16px 22px,#fff 22px 38px,transparent 38px 44px)}
body.theme-dark .pill.open{color:#5fce93}
body.theme-dark .pill.open::before{background:rgba(31,138,76,.2)}
body.theme-dark .feed-badge.home{background:rgba(31,138,76,.2);color:#5fce93}
body.theme-dark .feed-badge.off{background:#26262e;color:#a5a3a0}
body.theme-dark .item-row.is-pinned{background:linear-gradient(90deg,rgba(245,132,31,.14) 0%,var(--card) 60%)}
body.theme-dark .pill.closed{color:#a5a3a0}
body.theme-dark .pill.closed::before{background:#26262e}
body.theme-dark .pill.results{color:var(--ember)}
body.theme-dark .pill.results::before{background:rgba(245,132,31,.16)}
body.theme-dark .pill.level::before{border:1px solid #31313a}
body.theme-dark .meet .datebox::before{border:1px solid #31313a}
body.theme-dark .tag::before{background:#0f0f14}
body.theme-dark .tt-chip.active,body.theme-dark .tt-views button.active{color:#101014}
body.theme-dark .tt-dow.today,body.theme-dark .tt-ampm,body.theme-dark .tt-group{color:var(--ember)}
body.theme-dark a{color:var(--ember)}
body.theme-dark .btn{color:#101014}
body.theme-dark .btn.ghost{color:inherit}
body.theme-dark .btn.dangerous{color:#ff7a70}
body.theme-dark .btn.dangerous::before{border-color:#ff7a70}
body.theme-dark .btn.dark{color:#101014}
body.theme-dark .btn.dark::before{background:#fff}
body.theme-dark .btn.dark:hover::before{background:#e8e6e2}
/* no ring: it would be clipped by the bevel (see .card.path-card.sel above) -- the wash and the
   silhouette-following glow carry the selected state on dark too */
body.theme-dark .card.path-card.sel{box-shadow:none;background:linear-gradient(150deg,rgba(245,132,31,.30),var(--card) 60%)}
body.theme-dark label.f input:focus,body.theme-dark label.f select:focus,body.theme-dark label.f textarea:focus{box-shadow:0 0 0 3px rgba(245,132,31,.3)}

/* ---------- phones: where the lean lives when there is no room to lean ----------
   a 20deg edge needs height to travel: over a 46px drawer row it costs 8px of width, but over
   a 250px-tall card it costs ~90px -- a quarter of a 390px screen, and the leftover text column
   is too narrow to read. so on phones the cards keep their full width and go square-edged, and
   the lean moves into accents that are short enough to carry it at the real --slant-deg: the
   eyebrow sits on a skewed tab, and separators become skewed ticks. same angle, same family,
   none of the width cost. this block sits last in the file so it also lands over the dark
   theme's own .eyebrow colour. */
@media(max-width:640px){
  .hero-news-card{max-width:none;height:auto;margin:0 16px 46px;padding:18px 22px}
  .hero-news-card::before{transform:none;border-radius:4px}
  /* the card is square from here down, so the slide it sits on has to be too (the 600px rule
     above only squares it from 600) or the slant eats the card's top-left corner */
  .hero-slide{clip-path:none}

  .pointed-card .eyebrow,.next-meet .eyebrow,.hero-news-card .eyebrow,
  body.theme-dark .pointed-card .eyebrow,body.theme-dark .next-meet .eyebrow,body.theme-dark .hero-news-card .eyebrow{
    position:relative;z-index:0;display:inline-block;
    padding:5px 15px;margin:0 0 4px;color:#101014;font-size:.78rem;
  }
  .pointed-card .eyebrow::before,.next-meet .eyebrow::before,.hero-news-card .eyebrow::before{
    content:"";position:absolute;inset:0;z-index:-1;
    background:linear-gradient(100deg,var(--flame) 0%,var(--flame-dark) 100%);
    transform:skewX(calc(-1 * var(--slant-deg)));
  }
  /* the feature card is already flame, so its tab inverts to stay legible on it */
  .pointed-card.feature .eyebrow,body.theme-dark .pointed-card.feature .eyebrow{color:#fff}
  .pointed-card.feature .eyebrow::before{background:linear-gradient(100deg,#101014 0%,#2a2a32 100%)}

  /* Homepage banner: on a computer the next-meet card sits beside the headline, but stacked
     on a phone the two filled most of the first screen and pushed the news photos out of
     sight. Here the banner tightens and the card becomes one short row -- title and date on
     the left, a "Details" button on the right -- with the venue and closing date left to the
     Open Meets page the button goes to. */
  .hero{padding:16px 0 18px}
  .hero-grid{gap:12px}
  .hero-grid>div>.eyebrow{display:none}
  .hero h1{font-size:1.4rem;margin-top:0}
  .next-meet{
    display:grid;grid-template-columns:1fr auto;column-gap:12px;align-items:center;
    padding:10px 12px;
  }
  .next-meet>.eyebrow{grid-column:1;justify-self:start;padding:3px 12px;font-size:.7rem;margin-bottom:3px}
  .next-meet h3{grid-column:1;font-size:1rem;margin-top:0;
    display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}
  .next-meet .meta{grid-column:1;font-size:.82rem;margin-top:2px}
  .next-meet .meta div{margin-top:0}
  .next-meet .nm-venue,.next-meet .nm-closing,.next-meet .nm-long{display:none}
  .next-meet .nm-cta{grid-column:2;grid-row:1 / span 3;margin-top:0}
}
/* The partners row used to WRAP on phones, and a leading tick was added here because a
   trailing separator could dangle at the end of a wrapped line. That layout is gone -- at
   <=760px the row is now a single nowrap auto-scrolling ticker (see .logos-scroll above), so
   a leading tick is simply a second separator sitting beside the trailing one, and every gap
   between partners drew two diagonals. The trailing tick alone is kept: it is the same tall
   skewed divider the desktop bar and the nav use. */

/* ---------- article page & admin article preview ---------- */
.article-container{max-width:760px}
/* Typography shared verbatim between the public article page and the rich-text editor in the
   members' area (members.js gives the editor this same class), so an admin sees the real thing
   while writing, not a stand-in. */
.article-body{font-size:1.02rem;line-height:1.7;color:var(--body2)}
.article-body>*+*{margin-top:14px}
.article-body h3{font-family:'Montserrat',sans-serif;font-weight:800;font-size:1.2rem;color:var(--text);margin-top:26px}
.article-body ul,.article-body ol{padding-left:1.3em}
.article-body li+li{margin-top:6px}
.article-body a{color:var(--flame-dark);text-decoration:underline;text-underline-offset:2px}
body.theme-dark .article-body a{color:var(--ember)}
.article-body img{display:block;max-width:100%;border-radius:var(--radius);margin:18px auto}
.article-cover{height:260px;border-radius:var(--radius);background-size:cover;background-position:center;display:flex;align-items:center;justify-content:center;margin-bottom:28px}
.article-cover .news-thumb-icon{font-size:3.4rem}

.article-gallery{position:relative;margin-bottom:28px;border-radius:var(--radius);overflow:hidden;background:#000;box-shadow:var(--shadow)}
.article-gallery-track{display:flex;overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none;-ms-overflow-style:none}
.article-gallery-track::-webkit-scrollbar{display:none}
.article-gallery-slide{flex:0 0 100%;scroll-snap-align:center;aspect-ratio:16/10;overflow:hidden}
.article-gallery-slide img{width:100%;height:100%;object-fit:cover;display:block;border-radius:0;margin:0}
@media(max-width:640px){.article-gallery-slide{aspect-ratio:4/3}}
.gallery-arrow{position:absolute;top:50%;transform:translateY(-50%);width:38px;height:38px;border-radius:50%;background:rgba(16,16,20,.45);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);border:1px solid rgba(255,255,255,.25);color:#fff;font-size:1.3rem;line-height:1;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:3;transition:opacity .2s,background .2s}
.gallery-arrow:hover{background:rgba(16,16,20,.65)}
.gallery-arrow:disabled{opacity:0;pointer-events:none}
.gallery-arrow.prev{left:10px}
.gallery-arrow.next{right:10px}
.gallery-dots{position:absolute;left:0;right:0;bottom:12px;display:flex;justify-content:center;gap:7px;z-index:3}
.gallery-dot{width:8px;height:8px;border-radius:50%;background:rgba(255,255,255,.4);border:none;padding:0;cursor:pointer;transition:background .2s,transform .2s}
.gallery-dot.active{background:#fff;transform:scale(1.2)}

/* rich text editor (members' area) */
.rte-toolbar{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}
.rte-toolbar button,.rte-img-btn{background:var(--field);border:1.5px solid var(--line);color:var(--text);font:inherit;font-size:.85rem;font-weight:700;text-transform:none;letter-spacing:0;border-radius:8px;padding:6px 11px;cursor:pointer;line-height:1.3;display:inline-flex;align-items:center;gap:4px}
.rte-toolbar button:hover,.rte-img-btn:hover{border-color:var(--flame)}
.rte-editor{min-height:200px;border:1.5px solid var(--line);border-radius:10px;padding:14px 16px;background:var(--field);
  /* .f (the label wrapper) sets uppercase/bold/tracked type for field labels, which would
     otherwise leak into the editable text by inheritance and break the WYSIWYG match with the
     public article page, which has no such ancestor. */
  font-weight:400;text-transform:none;letter-spacing:normal}
.rte-editor:focus{outline:none;border-color:var(--flame);box-shadow:0 0 0 3px rgba(242,107,33,.18)}
.rte-editor img{max-height:220px;object-fit:cover}

/* photo gallery picker (members' area) */
.gallery-picker{display:grid;gap:10px}
.gallery-thumbs{display:flex;flex-wrap:wrap;gap:10px}
.gallery-thumb{position:relative;width:76px;height:76px;border-radius:9px;overflow:hidden;border:1.5px solid var(--line)}
.gallery-thumb img{width:100%;height:100%;object-fit:cover;display:block;background:#101014}
.gallery-thumb-frame{position:absolute;left:0;right:0;bottom:0;padding:5px 0;background:rgba(16,16,20,.72);color:#fff;border:none;font-size:.7rem;font-weight:700;letter-spacing:.04em;cursor:pointer}
.gallery-thumb-frame:hover{background:var(--flame-dark)}
.img-frame-btn{margin-top:8px;justify-self:start}
.img-picker [hidden]{display:none}
.img-add-row{display:flex;flex-wrap:wrap;gap:8px}
button.img-upload-btn{background:none;font-family:inherit}

/* photo library (pickLibraryImages in members.js) */
.library-body{padding:18px 20px 24px;display:grid;gap:14px}
.library-body [hidden]{display:none}
.library-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(104px,1fr));gap:10px}
.library-item{position:relative;display:block;aspect-ratio:1;padding:0;border:2px solid transparent;border-radius:9px;overflow:hidden;background:#101014;cursor:pointer}
.library-item:hover{border-color:var(--line)}
.library-item.on{border-color:var(--flame)}
.library-item img{width:100%;height:100%;object-fit:cover;display:block;margin:0;border-radius:0}
.library-num{position:absolute;top:5px;right:5px;min-width:22px;height:22px;padding:0 6px;border-radius:11px;background:var(--flame);color:#fff;font-size:.75rem;font-weight:700;display:none;align-items:center;justify-content:center}
.library-item.on .library-num{display:flex}
.library-date{position:absolute;left:0;right:0;bottom:0;padding:3px 0;background:rgba(16,16,20,.72);color:#fff;font-size:.68rem;text-align:center}
.library-more{justify-self:start}
/* Manage Images section (showImagesSection in members.js) */
.img-manage-bar{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 16px;margin-bottom:14px}
.img-manage-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:14px}
.img-manage-card{display:flex;flex-direction:column;gap:8px;background:var(--card);border:1px solid var(--line);border-radius:12px;padding:10px}
.img-manage-thumb{display:block;aspect-ratio:4/3;border-radius:8px;overflow:hidden;background:#101014}
.img-manage-thumb img{width:100%;height:100%;object-fit:cover;display:block;margin:0;border-radius:0}
.img-manage-info{flex:1;display:grid;gap:4px;font-size:.8rem;color:var(--muted);overflow-wrap:anywhere}
.img-manage-uses b{color:var(--text)}
.img-manage-unused{font-style:italic}
.img-manage-card .btn{align-self:flex-start}
@media(max-width:640px){.library-body{padding:16px 16px 24px}.library-grid{grid-template-columns:repeat(auto-fill,minmax(90px,1fr));gap:8px}}

/* framing editor (openFramingEditor in members.js) */
.frame-body{padding:18px 20px 24px;display:grid;gap:16px}
.frame-stage{position:relative;justify-self:center;max-width:100%;line-height:0;cursor:crosshair;touch-action:none;user-select:none;-webkit-user-select:none}
.frame-stage img{max-width:100%;max-height:52vh;display:block;border-radius:8px;margin:0}
.frame-stage.fit{cursor:default}
.frame-stage.fit img{opacity:.55}
.frame-marker{position:absolute;width:30px;height:30px;margin:-15px 0 0 -15px;border-radius:50%;border:3px solid #fff;box-shadow:0 0 0 2px var(--flame),0 2px 10px rgba(0,0,0,.55);pointer-events:none}
.frame-stage.fit .frame-marker{display:none}
.frame-strip{display:flex;gap:8px;overflow-x:auto;padding:2px;scrollbar-width:thin}
.frame-strip button{flex:0 0 auto;width:64px;height:64px;padding:0;border:2px solid transparent;border-radius:8px;overflow:hidden;background:#101014;cursor:pointer;opacity:.6;transition:opacity .15s,border-color .15s}
.frame-strip button.on{border-color:var(--flame);opacity:1}
.frame-strip img{width:100%;height:100%;object-fit:cover;display:block;margin:0;border-radius:0}
.frame-seg-views{flex-wrap:wrap;border-radius:14px;justify-self:start}
/* homepage pictures in the edit form: one row per screen */
.hero-sets{display:grid;gap:14px}
.hero-set{display:grid;gap:10px;padding:12px 14px;border:1.5px solid var(--line);border-radius:10px}
.hero-set-head{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px}
.hero-set-title{font-size:.8rem;font-weight:700;text-transform:none;letter-spacing:normal}
.hero-set .frame-seg button{text-transform:none;letter-spacing:normal}
.hero-set .img-upload-btn{justify-self:start}
.frame-seg-views button{padding:8px 12px}
.frame-copy{background:none;border:none;padding:6px 2px;font:inherit;font-size:.8rem;font-weight:700;color:var(--ember);text-decoration:underline;cursor:pointer}
.frame-zoom{display:flex;align-items:center;gap:12px}
.frame-zoom input{flex:1;accent-color:var(--flame)}
.frame-zoom output{min-width:3.2em;text-align:right;font-weight:700;font-size:.85rem}
.frame-label{font-size:.78rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--muted)}
.frame-card-opts{display:grid;gap:10px;margin-top:-4px}
.frame-card-row{display:flex;flex-wrap:wrap;align-items:center;gap:10px 22px}
.frame-opt{display:inline-flex;align-items:center;gap:10px}
.frame-seg{display:inline-flex;border:1.5px solid var(--line);border-radius:999px;overflow:hidden}
.frame-seg button{background:none;border:none;padding:8px 16px;font:inherit;font-size:.85rem;font-weight:700;color:var(--muted);cursor:pointer;min-height:40px}
.frame-seg button.on{background:var(--flame);color:#101014}
.frame-seg-views{align-self:start}
.frame-copy{justify-self:start}
.frame-controls{display:grid;gap:16px;padding-top:16px;border-top:1px solid var(--line)}
/* the one preview: the phone views are shown at roughly phone size, not stretched to the editor */
#framePreview .frame-preview{border-radius:6px;background-color:#101014}
#framePreview .frame-preview[data-paint="ap"],#framePreview .frame-hero-phone{max-width:380px;margin:0 auto;width:100%}

/* Homepage replicas in the framing editor: laid out at a real slide's pixel size (set inline)
   and scaled to fit (--s, from JS). Their rules are standalone rather than reusing .hero-slide
   and .hero-news-card, because those follow the ADMIN's screen width -- on a phone they'd show
   the phone layout in the "computer" preview. Keep in step with the hero rules above. */
.fh{position:relative;overflow:hidden;border-radius:6px;background:#101014}
.fh-inner{position:absolute;left:0;top:0;transform:scale(var(--s,.5));transform-origin:0 0;overflow:hidden}
.fh-photo,.fh-shade{position:absolute;inset:0}
.fh-photo.photo{position:absolute}
.fh-shade{background:linear-gradient(160deg,rgba(16,16,20,.55),rgba(16,16,20,.15) 65%)}
.frame-hero-desk .fh-inner{--slide-lean:calc(var(--hero-strip-h) * var(--slant-ratio));clip-path:polygon(var(--slide-lean) 0,100% 0,calc(100% - var(--slide-lean)) 100%,0 100%)}
.frame-hero-desk .fh{border-radius:0;background:#000}
.fh-card{position:absolute;z-index:1;color:#fff;display:flex;flex-direction:column;justify-content:center}
.fh-card .eyebrow{color:var(--ember)}
.fh-card h3{font-family:'Montserrat',sans-serif;font-weight:800;font-size:1.15rem;margin-top:6px;line-height:1.2;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}
.fh-blurb{color:rgba(255,255,255,.82);font-size:.9rem;margin-top:8px;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;overflow:hidden}
.fh-link{color:var(--ember);font-weight:600;font-size:.85rem;display:inline-block;margin-top:10px;text-decoration:underline}
.frame-hero-desk .fh-card.card-compact .fh-blurb,.frame-hero-phone .fh-card.card-p-compact .fh-blurb{display:none}
.frame-hero-phone .fh-card.card-p-top{bottom:auto;top:16px}
.fh-card::before{content:"";position:absolute;inset:0;z-index:-1;background:rgba(16,16,20,.55);border:1px solid rgba(255,255,255,.15);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}
.frame-hero-desk .fh-card{
  --card-h:var(--hero-card-h);
  max-width:420px;height:var(--card-h);padding:18px 48px;bottom:28px;
  left:calc(var(--hero-card-gap) + (28px + var(--card-h) / 2) * var(--slant-ratio));
}
.frame-hero-desk .fh-card.card-compact{--card-h:var(--hero-card-h-compact)}
.frame-hero-desk .fh-card.card-right{left:auto;right:calc(var(--hero-card-gap) + var(--slide-lean) - (28px + var(--card-h) / 2) * var(--slant-ratio))}
.frame-hero-desk .fh-card::before{transform:skewX(calc(-1 * var(--slant-deg)))}
.frame-hero-phone .fh-card{left:16px;right:16px;bottom:46px;padding:18px 22px}
.frame-hero-phone .fh-card::before{border-radius:4px}
.frame-hero-phone .fh-card .eyebrow{position:relative;z-index:0;align-self:flex-start;padding:5px 15px;margin:0 0 4px;color:#101014;font-size:.78rem}
.frame-hero-phone .fh-card .eyebrow::before{content:"";position:absolute;inset:0;z-index:-1;background:linear-gradient(100deg,var(--flame) 0%,var(--flame-dark) 100%);transform:skewX(calc(-1 * var(--slant-deg)))}
.gallery-thumb-del{position:absolute;top:2px;right:2px;width:20px;height:20px;border-radius:50%;background:rgba(16,16,20,.7);color:#fff;border:none;font-size:.9rem;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0}
.gallery-thumb-del:hover{background:var(--warn)}

/* "Preview as article page" overlay */
.preview-overlay{position:fixed;inset:0;z-index:300;background:rgba(10,10,12,.7);display:none;overflow-y:auto;padding:20px 0 60px}
.preview-overlay.open{display:block}
.preview-overlay-inner{max-width:800px;margin:0 auto;background:var(--paper);border-radius:var(--radius);overflow:hidden;box-shadow:0 20px 60px rgba(0,0,0,.4)}
.preview-overlay-bar{position:sticky;top:0;z-index:2;display:flex;justify-content:space-between;align-items:center;gap:12px;padding:14px 20px;background:var(--ink);color:#fff;font-size:.85rem;font-weight:700}
.preview-overlay-body{padding:32px 0 40px}
@media(max-width:640px){.preview-overlay{padding:0}.preview-overlay-inner{border-radius:0;min-height:100vh;min-height:100dvh}}

/* toast + badges */
#toast{position:fixed;bottom:22px;left:50%;transform:translateX(-50%) translateY(20px);background:var(--ink);color:#fff;padding:12px 22px;border-radius:999px;border:1.5px solid var(--flame);font-weight:600;font-size:.92rem;opacity:0;pointer-events:none;transition:all .25s;z-index:400}
#toast.show{opacity:1;transform:translateX(-50%) translateY(0)}
.inbox-msg{white-space:pre-wrap}

/* ---------- mission & club history ----------
   Two tabs over one page: the same pill-group switch the timetable uses for its two views,
   sized up because here it IS the page's navigation rather than a filter above content. */
.page-tabs{display:inline-flex;border:1.5px solid var(--line);border-radius:10px;padding:3px;background:var(--card);margin-bottom:30px}
.page-tabs button{font:inherit;font-weight:700;font-size:.95rem;border:none;background:none;color:var(--muted);padding:11px 22px;border-radius:7px;cursor:pointer;transition:background .15s,color .15s}
.page-tabs button:hover{color:var(--text)}
.page-tabs button.active{background:var(--flame);color:#fff}
@media(max-width:520px){.page-tabs{display:flex;width:100%}.page-tabs button{flex:1;padding:11px 6px;font-size:.88rem}}

/* the statement itself is the page's one headline claim, so it gets display weight and a
   lane-rope tick rather than sitting as another paragraph of body copy */
.mission-statement{position:relative;max-width:780px;font-family:'Montserrat',sans-serif;font-weight:700;font-size:1.42rem;line-height:1.35;letter-spacing:-.01em;padding-left:20px}
.mission-statement::before{content:"";position:absolute;left:0;top:.28em;bottom:.28em;width:6px;background:var(--flame);transform:skewX(calc(-1 * var(--slant-deg)))}
.mission-lead{margin:22px 0 0;font-weight:600;color:var(--muted)}
.mission-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(290px,100%),1fr));gap:18px;margin-top:16px}
.mission-item{display:flex;flex-direction:column;gap:8px}
/* the numeral is set big and faint so the five points read as a numbered sequence at a glance
   without a bullet column narrowing the text */
.mission-num{font-family:'Montserrat',sans-serif;font-weight:800;font-size:1.6rem;line-height:1;color:var(--flame);opacity:.55}
.mission-item h3{font-family:'Montserrat',sans-serif;font-weight:800;font-size:1.06rem;line-height:1.25}
.mission-item p{color:var(--body2);font-size:.95rem}
.mission-foot{margin-top:24px;color:var(--muted);font-size:.95rem}
body.theme-dark .page-tabs button.active{color:#101014}

/* ---------- member guides ----------
   Four guides as .page-tabs over one full-width panel. Four labels don't fit one row on a
   phone, so below 680px the switch becomes a 2x2 grid instead of squeezing the text. */
.guide-tabs{flex-wrap:wrap}
@media(max-width:680px){.guide-tabs{display:grid;grid-template-columns:1fr 1fr;width:100%}.guide-tabs button{padding:11px 6px;font-size:.88rem}}
.guide-panel{padding:30px 32px}
.guide-panel>h3{font-size:1.35rem}
/* A guide is plain document markup -- opening paragraph, h3 headings, bullet lists, blockquote
   highlights -- written in the members' area editor. This one block styles it as a classic
   document (bold underlined headings, orange bullets) both on the page and in that editor,
   so the editor shows exactly what will publish. */
.guide-doc{color:var(--muted);font-size:.95rem}
.guide-doc p{margin:8px 0 0}
.guide-doc h3{font-family:'Montserrat',sans-serif;font-weight:800;font-size:1.1rem;line-height:1.3;color:var(--text);margin:32px 0 10px;padding-bottom:8px;border-bottom:2px solid var(--line)}
.guide-doc h3:first-child{margin-top:8px}
.guide-doc h3+p{margin-top:0}
.guide-doc ul{list-style:none;margin:0;padding:0}
.guide-doc li{position:relative;padding:6px 0 6px 20px;overflow-wrap:anywhere}
.guide-doc li::before{content:"";position:absolute;left:2px;top:15px;width:6px;height:6px;border-radius:50%;background:var(--flame)}
.guide-doc blockquote{margin:6px 0;padding:12px 14px;border-left:4px solid #f5841f;background:rgba(245,132,31,.16);color:var(--text);overflow-wrap:anywhere}
.guide-doc strong,.guide-doc b{color:var(--text)}
.guide-doc a{font-weight:700;color:var(--flame-dark);text-decoration:underline;text-underline-offset:3px}
.guide-doc a:hover{color:var(--flame)}
.rte-editor.guide-doc{font-size:.95rem}
@media(max-width:520px){.guide-panel{padding:22px 18px}}
body.theme-dark .mission-num{opacity:.75}

/* The timeline rail is a lane rope stood on its end: same flame/ink alternation as .lane-rope,
   rotated into a vertical gradient, with each era's marker sitting on it. */
.history-intro{max-width:760px;color:var(--muted);margin-bottom:30px}
.timeline{list-style:none;position:relative;max-width:900px;padding-left:120px}
.timeline::before{content:"";position:absolute;left:78px;top:8px;bottom:8px;width:6px;border-radius:3px;
  background:repeating-linear-gradient(180deg,var(--flame) 0 16px,transparent 16px 22px,var(--ink) 22px 38px,transparent 38px 44px)}
.timeline>li{position:relative;padding-bottom:34px}
.timeline>li:last-child{padding-bottom:0}
/* the dot that pins each entry to the rail. drawn on the entry, not the rail, so it always
   lands level with the year no matter how long the previous entry's prose runs */
.timeline>li::before{content:"";position:absolute;left:-47px;top:4px;width:16px;height:16px;border-radius:50%;
  background:var(--flame);border:3px solid var(--paper);box-shadow:0 0 0 2px var(--flame)}
.tl-year{position:absolute;left:-120px;top:0;width:78px;text-align:right;padding-right:18px;
  font-family:'Montserrat',sans-serif;font-weight:800;font-size:.92rem;line-height:1.15;color:var(--flame-dark);letter-spacing:-.01em}
.timeline h3{font-family:'Montserrat',sans-serif;font-weight:800;font-size:1.22rem;line-height:1.25;margin-bottom:8px}
.timeline p{color:var(--body2);font-size:.98rem;line-height:1.65}
.timeline p+p{margin-top:12px}
/* --ink is all but invisible on the dark ground, so the rope's dark half goes white there --
   the same swap .lane-rope.on-dark already makes */
body.theme-dark .timeline::before{background:repeating-linear-gradient(180deg,var(--flame) 0 16px,transparent 16px 22px,#fff 22px 38px,transparent 38px 44px)}
body.theme-dark .tl-year{color:var(--ember)}
/* phones have no room for a year gutter beside the rail, so the rail moves hard left and the
   year sits inline above its heading -- the sequence still reads top to bottom */
@media(max-width:620px){
  .mission-statement{font-size:1.2rem}
  .timeline{padding-left:26px}
  .timeline::before{left:0}
  .timeline>li::before{left:-29px;top:2px;width:13px;height:13px}
  .tl-year{position:static;display:block;width:auto;text-align:left;padding:0;margin-bottom:2px;font-size:.98rem}
}

/* ==========================================================================
   MOBILE PASS
   Phones are the majority of this site's traffic, so this block is the
   backstop for everything the per-component breakpoints above don't cover.
   It deliberately changes NO angles: the slant system (skewed fills on short
   elements, bevels on tall ones, square cards plus a corner flame flag once a
   card is too tall to lean) is exactly as designed. What's fixed here is the
   plumbing around it -- overflow, tap targets, viewport units and the couple
   of screen shapes the existing breakpoints didn't reach.
   ========================================================================== */

/* ---- 1. long unbreakable strings ----------------------------------------
   A club email is one 40-character "word" with no break opportunity, e.g.
   cluborganiserissues@phoenixbasildonsc.org on the Committee page. At 320px
   the card's text column is ~236px and that address is ~300px, so it pushed
   the whole PAGE sideways -- every phone got a horizontal scrollbar and the
   header slid off. break-word alone is not enough (it only breaks a word that
   would otherwise overflow its own line box, which a table-less flex/grid
   child can dodge), so links get the stronger anywhere. */
body{overflow-wrap:break-word}
a[href^="mailto:"],a[href^="http"],.card a,.item-row .s,.admin-top .who{overflow-wrap:anywhere}
/* Belt and braces: if any one skewed fill or bevelled card ever leans past the
   page edge, clip it rather than let it become a sideways scroll. clip (not
   hidden) is used deliberately -- hidden would turn main into a scroll
   container and break the sticky Club News period bar inside it. */
main{overflow-x:clip}

/* ---- 2. touch targets ---------------------------------------------------
   Scoped to pointer:coarse so the desktop bar keeps its tighter proportions.
   Anything a thumb has to hit gets to ~44px without changing its shape: the
   chips keep their skewed ::before fill, the round nav buttons stay round. */
@media(pointer:coarse){
  .btn.small{padding:10px 18px}
  .news-tag-chip,.news-jump-chip,.tt-chip{padding-top:11px;padding-bottom:11px}
  .news-jump-arrow{padding-top:10px;padding-bottom:10px}
  /* sponsor links were a 24px-tall target on every page */
  .partners .logos a{padding-block:8px}
  .partners{padding:7px 0}
  .cal-nav-btn{width:42px;height:42px;font-size:1.2rem}
  .gallery-arrow,.hero-arrow{width:44px;height:44px}
  .comp-foot a{padding:6px 0}
  /* footer links sat ~30px apart, which on a phone is the hardest part of the
     page to hit accurately -- it is also the last thing a parent scrolls to */
  footer.site a{padding:9px 0}
  .tt-views button{padding:11px 16px}
  .role-pick button{padding:14px 14px}
  /* the carousel dots stay visually 4-8px; the hit area grows around them */
  .hero-dot,.gallery-dot{position:relative}
  .hero-dot::after,.gallery-dot::after{content:"";position:absolute;inset:-14px -3px}
  .hero-dots{bottom:18px}
}

/* ---- 3. narrow phones (<=400px) -----------------------------------------
   The 560px header rules leave logo + name + theme toggle + burger just
   fitting at 390px. Below that the name started wrapping to three lines and
   shoved the burger against the edge, so the block tightens once more. */
@media(max-width:400px){
  .nav-wrap{padding:8px 12px;gap:8px}
  .brand img{width:50px;height:50px}
  .brand{gap:8px}
  .brand .name{font-size:.82rem}
  .brand .name .line-two{font-size:.55rem;letter-spacing:.12em}
  .theme-toggle{width:36px;height:36px}
  .burger{padding:7px 9px}
  .container{padding:0 14px}
  .page-head{margin-bottom:26px}
  section.page{padding:36px 0 54px}
  .meets-heading{font-size:1.2rem}
  .tt-views{width:100%}
  .tt-views button{flex:1;text-align:center;padding:11px 6px;font-size:.8rem}
  /* the count would otherwise be squeezed onto the same line as a long year
     label and the +/- marker */
  .year-group>summary{flex-wrap:wrap;gap:8px 12px}
  .year-group>summary .year-count{margin-left:0;flex-basis:100%;order:3}
}

/* ---- 4. landscape phones ------------------------------------------------
   A 360px-tall viewport gave the 340px photo strip the entire screen, so the
   page looked like it had no content under it. Height-based, not width-based,
   so a tablet in landscape is untouched. */
@media(max-width:900px) and (max-height:520px) and (orientation:landscape){
  .hero-photo-strip{height:min(340px,62vh)}
  .hero{padding:26px 0 32px}
  .hero-news-card{height:auto;margin-bottom:22px;padding:14px 20px}
  .hero-news-card p:not(.eyebrow){-webkit-line-clamp:2}
  nav.main{max-height:var(--drawer-max,72dvh)}
}

/* ---- 5. notch / rounded-corner safe area --------------------------------
   In landscape on a notched phone the cutout eats the left or right gutter.
   The gutter is widened by exactly the inset the device reports, so on every
   other device this resolves to the normal padding. */
@supports(padding:max(0px)){
  .container,.nav-wrap,.partners-wrap,.foot-grid,.foot-base{
    padding-left:max(var(--gutter,20px),env(safe-area-inset-left));
    padding-right:max(var(--gutter,20px),env(safe-area-inset-right));
  }
  @media(max-width:400px){.container{--gutter:14px}}
  .nav-wrap{--gutter:20px}
  @media(max-width:560px){.nav-wrap{--gutter:16px}}
  @media(max-width:400px){.nav-wrap{--gutter:12px}}
}

/* ---- 6. members' area on a phone ----------------------------------------
   iOS Safari zooms the page in whenever a focused field's text is under 16px
   and does not zoom back out, which left an admin editing a squad timetable
   stuck at 1.3x with the form off-screen. The session rows already restack at
   700px; this just takes their type back up to the no-zoom threshold. */
@media(max-width:760px){
  .sess-row input,.sess-row select,
  .doclink-row input,.doclink-row select,
  .rte-toolbar button,.rte-img-btn{font-size:16px}
  .rte-toolbar{gap:8px}
  .rte-toolbar button,.rte-img-btn{padding:9px 12px}
}
/* The sticky admin bar is the only way back out of the members' area, so it
   has to survive the longest role name without pushing the page sideways. */
@media(max-width:560px){
  .admin-top{flex-wrap:wrap}
  .admin-top .brand{flex:1 1 100%}
  .item-row{gap:10px}
  .item-row .acts{flex:1 1 100%}
  .item-row .acts .btn{flex:1;text-align:center}
}

/* ---- 7. remaining phone proportions -------------------------------------
   Fixed pixel heights that read fine on a laptop but take over a phone. */
@media(max-width:640px){
  /* was a flat 260px -- over a third of a small phone's screen before a word
     of the article */
  .article-cover{height:clamp(170px,46vw,260px)}
  .article-cover .news-thumb-icon{font-size:2.6rem}
  /* deliberately NOT shrunk with the others: these are portraits of people, and the
     background-position:center crop takes the top of the head off first, so a shorter
     box costs a face rather than whitespace. */
  .news-thumb{height:clamp(110px,32vw,130px)}
  .social-card .art{height:clamp(110px,32vw,132px)}
  /* the page's one headline claim shouldn't need three lines of scroll */
  .mission-statement{padding-left:16px}
  .foot-grid{gap:26px;padding-block:34px}
}

/* ---------- the two social links in the header ----------
   Phones get them as rows at the foot of the drawer (.nav-social, above); from 1120px up
   they're inside the .quick-links menu instead (see above). Each is its own breakpoint's
   version of the same thing, so only one is ever on. */
@media(min-width:1024px){.nav-social,.nav-social-label,nav.main a.nav-co{display:none}}

/* ---------- tappable cards ----------
   A card with a single destination (news, socials, calendar competitions, the hero story, the
   next-meet card) is one big link: .card-link's ::after is stretched over the card, which is
   already position:relative with its own stacking context. The anchor itself must stay
   unpositioned for that to work -- which is why the leaning .btn look (position:relative for
   its skewed fill) lives on a span inside it rather than on the anchor. Anything else in the
   card that goes somewhere different (.card-extra) is lifted above the overlay. */
.card-link{text-decoration:none}
/* a ghost button takes the card's text colour, as it did when the anchor was the button (the
   dark theme's link colour would otherwise win) */
.card-link:has(>.btn),body.theme-dark .card-link:has(>.btn){color:inherit}
.card-link::after{content:"";position:absolute;inset:0;z-index:1}
.card-link:focus-visible{outline:none}
.card-link:focus-visible::after{box-shadow:inset 0 0 0 3px rgba(245,132,31,.6)}
.tap-card .card-extra{position:relative;z-index:2}
.tap-card{transition:transform .15s ease}
.tap-card:hover .card-link .btn.ghost::before{background:rgba(242,107,33,.1)}
.tap-card:hover .card-link .btn:not(.ghost)::before{background:var(--flame-dark)}
.comp-card.tap-card:hover .card-link,.hero-news-card.tap-card:hover .card-link{text-decoration:underline}
/* a story sliding out (or peeking in beside the current one) is invisible, so it mustn't catch taps */
.hero-slide:not(.active) .hero-news-card{pointer-events:none}
/* Phones: no "Read more" / "Details" labels -- the whole card is the button, marked by a small
   leaning tab with a flame arrow, which fills flame when the card is pressed. The tab is cut
   with clip-path rather than skewed so the arrow stays upright (same lean as .btn). Its fill
   contrasts with the surface under it: white on dark cards and the hero's dark glass, ink on
   white cards (light theme, and the next-meet card in both themes). The label stays for
   screen readers. */
@media(max-width:640px){
  .card-link>.cl-label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
  .tap-card{--tap-bg:#101014;--tap-h:30px}
  body.theme-dark .tap-card,body .hero-news-card.tap-card{--tap-bg:#fff}
  body .next-meet.tap-card,body.theme-dark .next-meet.tap-card{--tap-bg:#101014;--tap-h:34px}
  .card-link::before{content:"→";display:inline-flex;align-items:center;justify-content:center;
    width:calc(var(--tap-h) * 1.5);height:var(--tap-h);background:var(--tap-bg);color:var(--flame);
    font-family:'Montserrat',sans-serif;font-size:1.1rem;font-weight:800;line-height:1;
    clip-path:polygon(calc(var(--tap-h) * var(--slant-ratio)) 0,100% 0,calc(100% - var(--tap-h) * var(--slant-ratio)) 100%,0 100%);
    transition:background .12s,color .12s}
  .tap-card:active{transform:scale(.98)}
  .tap-card:active .card-link::before{background:var(--flame);color:#fff}
  .tap-card .card-extra{display:none}
  /* the badge sits bottom-right of the card */
  .news-card .card-link,.social-card .card-link{float:right}
  .news-card>div:has(>.card-link),.social-card .body>div:has(>.card-link){margin-top:4px!important;display:flow-root}
  .comp-foot{align-items:center}
  .hero-news-card .card-link{align-self:flex-end;margin-top:4px}
}

/* ================= HOMEPAGE V2: CLUB PULSE =================
   (HOMEPAGE V2 in site.js.) V2 is the homepage. Everything it adds is shown only while the body
   has .home-v2 (set in index.html), so taking that class off brings back Classic (V1) as it was. Same visual language as the rest of the site: ink and flame, the
   one --slant-deg lean on tabs, ticks and buttons, square-edged blocks on phones. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
body:not(.home-v2) .v2-only{display:none!important}

/* --- Club Pulse: the "today" area above the orange banner --- */
.pulse{padding:6px 0 18px;animation:pulse-in .35s ease-out both}
@keyframes pulse-in{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}
.pulse-head{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px 16px;margin-bottom:12px}
.pulse-title{display:flex;align-items:center;flex-wrap:wrap;gap:4px 10px;font-family:'Montserrat',sans-serif;font-weight:800;
  font-size:.78rem;letter-spacing:.14em;text-transform:uppercase;color:var(--text)}
.pulse-title::before{content:"";width:4px;height:14px;background:var(--flame);transform:skewX(calc(-1 * var(--slant-deg)))}
.pulse-date{font-weight:600;letter-spacing:.06em;color:var(--muted)}
/* "Viewing: Race Day | Club Home" -- only on a day something's on */
.pulse-ctx{display:flex;align-items:center;gap:6px}
.pulse-ctx-label{font-size:.68rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);margin-right:4px}
.pulse-ctx-btn{position:relative;z-index:0;min-height:32px;padding:6px 15px;background:none;border:none;cursor:pointer;color:var(--text);
  font-family:'Montserrat',sans-serif;font-weight:700;font-size:.74rem;letter-spacing:.05em;text-transform:uppercase;line-height:1}
.pulse-ctx-btn::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--card);border:1.5px solid var(--line);
  transform:skewX(calc(-1 * var(--slant-deg)));transition:background .15s,border-color .15s}
.pulse-ctx-btn:hover::before{border-color:var(--flame)}
.pulse-ctx-btn[aria-pressed="true"]{color:#101014;cursor:default}
.pulse-ctx-btn[aria-pressed="true"]::before{background:var(--flame);border-color:var(--flame)}
.pulse-ctx-btn:focus-visible{outline:none}
.pulse-ctx-btn:focus-visible::before{box-shadow:0 0 0 3px rgba(245,132,31,.55)}

.training-summary{color:var(--muted);font-size:.9rem;margin-top:8px;
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;overflow:hidden}

/* the event panel: a broadcast-style ink block in both themes, never full-screen */
.pulse-event{position:relative;display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:end;gap:18px 36px;
  margin-bottom:12px;padding:24px 28px 24px 34px;background:#101014;color:#fff;border-bottom:4px solid var(--flame);
  box-shadow:0 10px 26px rgba(16,16,20,.28);overflow:hidden}
.pulse-event::before{content:"";position:absolute;left:0;top:0;bottom:0;width:6px;background:var(--flame)}
.pulse-event-tags{display:flex;align-items:center;flex-wrap:wrap;gap:8px 12px}
.pulse-tag,.pulse-live-flag{position:relative;z-index:0;display:inline-flex;align-items:center;gap:7px;padding:4px 13px;
  font-family:'Montserrat',sans-serif;font-weight:800;font-size:.74rem;letter-spacing:.12em;text-transform:uppercase}
.pulse-tag{color:#101014}
.pulse-tag::before,.pulse-live-flag::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--flame);transform:skewX(calc(-1 * var(--slant-deg)))}
.pulse-live-flag{color:#fff}
.pulse-live-flag::before{background:#c81e2c}
.pulse-live-flag .live-dot{width:7px;height:7px;border-radius:50%;background:#fff;flex:0 0 auto;animation:live-blink 1.4s ease-in-out infinite}
.pulse-who{font-size:.74rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--ember)}
.pulse-event-title{font-size:clamp(1.55rem,3.2vw,2.4rem);margin-top:12px;color:#fff;overflow-wrap:anywhere}
.pulse-where{margin-top:6px;font-weight:600;font-size:.98rem;color:rgba(255,255,255,.88)}
.pulse-note{margin-top:8px;max-width:68ch;font-size:.9rem;color:rgba(255,255,255,.72);white-space:pre-line;
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;overflow:hidden}
.pulse-also{margin-top:10px;font-size:.85rem;color:rgba(255,255,255,.72)}
.pulse-also span{font-weight:700;text-transform:uppercase;letter-spacing:.08em;font-size:.72rem;margin-right:4px}
.pulse-also a,body.theme-dark .pulse-also a{color:var(--ember)}
.pulse-actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:10px 14px;max-width:380px}
/* a second gala on the same day: the same panel, a size down, so the lead one still reads first */
.pulse-event.is-secondary{padding-block:18px;border-bottom-width:3px}
.pulse-event.is-secondary .pulse-event-title{font-size:clamp(1.25rem,2.3vw,1.75rem);margin-top:10px}
.pulse-event.is-secondary .pulse-note{-webkit-line-clamp:2}
/* buttons on ink in both themes: flame with ink text, white outlines, the one red live button */
body .pulse-event .btn{color:#101014}
body .pulse-event .btn.ghost{color:#fff}
body .pulse-event .btn.ghost:hover::before{background:rgba(255,255,255,.1)}
body .pulse-event .btn.live{color:#fff}
.pulse-event .btn:focus-visible::before{box-shadow:0 0 0 3px var(--ember)}

/* Session update / Today / Next / Results / This week -- always one row: on a computer the boxes
   share the width (the session update takes a double share), on a phone it's a row you swipe */
.pulse-strip{display:flex;background:var(--card);border:1px solid var(--line);box-shadow:var(--shadow)}
.pulse-cell,body.theme-dark .pulse-cell{position:relative;flex:1 1 0;display:flex;flex-direction:column;gap:2px;min-width:0;padding:12px 18px 12px 24px;
  color:var(--text);text-decoration:none;transition:background .15s}
/* training change: first thing a parent needs, but not an alarm -- flame edge, no red */
.pulse-cell.is-notice{flex-grow:2;box-shadow:inset 4px 0 0 var(--flame)}
.pulse-sum{font-size:.85rem;color:var(--body2);line-height:1.35;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}
.pulse-cell+.pulse-cell::before{content:"";position:absolute;left:0;top:12px;bottom:12px;width:2px;background:var(--line);transform:skewX(calc(-1 * var(--slant-deg)))}
.pulse-cell:hover{background:rgba(245,132,31,.08)}
.pulse-cell:hover .pulse-s{text-decoration:underline}
.pulse-cell:focus-visible{outline:3px solid var(--ember);outline-offset:-3px}
.pulse-k{display:flex;align-items:center;gap:6px;font-size:.68rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:var(--flame-dark)}
body.theme-dark .pulse-k{color:var(--flame)}
.pulse-k .live-dot{width:7px;height:7px;border-radius:50%;background:#c81e2c;flex:0 0 auto;animation:live-blink 1.4s ease-in-out infinite}
.pulse-v{font-weight:700;font-size:.95rem;line-height:1.25;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pulse-s{font-size:.8rem;color:var(--muted)}
.pulse-strip-dots:empty{display:none}

/* Race Day demo (?demo=race-day): a plain ink bar that says it's a sample, with the two samples
   and a way out -- deliberately not the flame of the real panel */
.pulse-demo{display:flex;align-items:center;flex-wrap:wrap;gap:8px 10px;margin-bottom:12px;padding:8px 12px;
  border:1.5px dashed var(--line);background:var(--card)}
.pulse-demo-note{margin:0 6px 0 0;font-size:.8rem;color:var(--muted)}
.pulse-demo-note strong{color:var(--text);text-transform:uppercase;letter-spacing:.1em;font-size:.72rem}
.pulse-demo-btn{position:relative;z-index:0;min-height:30px;padding:5px 13px;background:none;border:none;cursor:pointer;color:var(--text);
  font-family:'Montserrat',sans-serif;font-weight:700;font-size:.72rem;letter-spacing:.03em;line-height:1.15}
.pulse-demo-btn::before{content:"";position:absolute;inset:0;z-index:-1;border:1.5px solid var(--line);transform:skewX(calc(-1 * var(--slant-deg)));transition:border-color .15s,background .15s}
.pulse-demo-btn:hover::before{border-color:var(--flame)}
.pulse-demo-btn[aria-pressed="true"]{color:var(--paper);cursor:default}
.pulse-demo-btn[aria-pressed="true"]::before{background:var(--text);border-color:var(--text)}
.pulse-demo-exit{margin-left:auto}
.pulse-demo-btn:focus-visible{outline:none}
.pulse-demo-btn:focus-visible::before{box-shadow:0 0 0 3px rgba(245,132,31,.55)}

/* the rest of the V2 homepage adapting around the panel */
body.home-v2.home-event .hero h1{font-size:clamp(1.4rem,2.4vw,1.85rem)}
/* the panel already carries the live button -- two pulsing red things would compete */
body.home-v2.home-live #liveResultsPill{display:none}
/* content couldn't load: no empty black slideshow or blank card, just the ordinary banner */
body.home-v2.content-failed .hero-photo-strip,body.home-v2.content-failed #nextMeetCard:empty{display:none}

@media(max-width:820px){
  .pulse-event{grid-template-columns:1fr;align-items:start}
  .pulse-actions{justify-content:flex-start;max-width:none}
}
@media(max-width:640px){
  .pulse{padding:2px 0 14px}
  .pulse .container{padding:0 16px}
  .pulse-head{margin-bottom:10px}
  .pulse-ctx{width:100%}
  .pulse-ctx-btn{flex:1 1 0;min-height:36px}
  .pulse-event{padding:18px 16px 18px 20px;gap:14px}
  .pulse-event::before{width:4px}
  .pulse-event-title{font-size:1.45rem;margin-top:10px}
  .pulse-event.is-secondary{padding-block:14px}
  .pulse-event.is-secondary .pulse-event-title{font-size:1.2rem}
  .pulse-where{font-size:.9rem}
  .pulse-actions{gap:10px 12px}
  /* one row, like on a computer: two boxes fill the width, and a third or fourth sits off to the
     right with its edge peeking in, a swipe away -- rather than wrapping onto a second row */
  .pulse-strip{display:grid;grid-template-columns:none;grid-auto-flow:column;grid-auto-columns:minmax(46%,1fr);
    overflow-x:auto;scroll-snap-type:x mandatory;overscroll-behavior-x:contain;scrollbar-width:none}
  .pulse-strip::-webkit-scrollbar{display:none}
  .pulse-cell{padding:10px 12px 10px 16px;scroll-snap-align:start}
  /* the session update on a phone: title and when only -- the summary is a tap away */
  .pulse-sum,.pulse-s-more{display:none}
  /* "there's more this way": a fade over the edge with a flame arrow, at whichever end has more
     (classes from wirePulseStrip in site.js) */
  .pulse-strip-frame{position:relative}
  .pulse-strip-frame::before,.pulse-strip-frame::after{position:absolute;top:1px;bottom:1px;width:44px;z-index:1;pointer-events:none;
    display:flex;align-items:center;font-weight:800;font-size:1.35rem;line-height:1;color:var(--flame);opacity:0;transition:opacity .2s}
  .pulse-strip-frame::before{content:"‹";left:1px;justify-content:flex-start;padding-left:6px;background:linear-gradient(90deg,var(--card) 35%,transparent)}
  .pulse-strip-frame::after{content:"›";right:1px;justify-content:flex-end;padding-right:6px;background:linear-gradient(270deg,var(--card) 35%,transparent)}
  .pulse-strip-frame.more-left::before,.pulse-strip-frame.more-right::after{opacity:1}
  /* where you are: the slideshow's leaning bars, small */
  .pulse-strip-dots{display:flex;justify-content:center;gap:2px;margin-top:4px}
  .pulse-strip-dot{width:30px;height:18px;padding:0;border:0;background:none;cursor:pointer;display:flex;align-items:center;justify-content:center}
  .pulse-strip-dot::before{content:"";width:18px;height:4px;background:var(--line);transform:skewX(calc(-1 * var(--slant-deg)));transition:background .2s}
  .pulse-strip-dot.active::before{background:var(--flame)}
  /* the small grey line stays on one line, trimmed with "..." if it must be */
  .pulse-s{font-size:.75rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .pulse-v{white-space:normal;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;font-size:.88rem}
  .pulse-demo-exit{margin-left:0}
}
@media(prefers-reduced-motion:reduce){.pulse,.pulse-live-flag .live-dot,.pulse-k .live-dot{animation:none}}
