/* =================================================================
   THE PRECINCT v2 — luxury residential publication theme
   -----------------------------------------------------------------
   Manrope (rounder sans) primary, Newsreader italic reserved for
   page-title emphasis (matched x-height with the sans). Cream paper
   from v1, terracotta accent, multi-colour icon chips for wayfinding.
   Frosted-glass pill (one component, contextual styling).
   Wide diffuse sheen on image-bg cards. Mobile-first throughout.
   ================================================================= */

@import url('https://fonts.googleapis.com/css2?family=Marcellus&display=swap');

/* 1. Reset */
*,*::before,*::after { box-sizing: border-box; margin: 0; padding: 0; }
img, svg { display: block; max-width: 100%; }
button { font: inherit; cursor: pointer; background: none; border: 0; color: inherit; }
a { color: inherit; }
/* The HTML `hidden` attribute must always win. Author rules like
   .lux-menu-sublink{display:block}, .lux-row{display:flex} and inline
   display:flex otherwise override the UA default and leave [hidden]
   elements visible. !important is required to beat inline styles. This
   is what makes the COO-CANDIDATES-HIDE tagged elements actually hide.
   JS-toggled elements (e.g. .lux-pocket-expanded) remove the attribute
   when shown, so they are unaffected. */
[hidden] { display: none !important; }

/* 2. Tokens */
:root {
  /* Palette — matched to v1 */
  --bone:      #f5f3ef;
  --bone-soft: #F8F4ED;
  --bone-dark: #eceae5;
  --paper:     #FFFFFF;
  /* Page canvas — a clean off-white that the bone hero gradient fades into.
     Slightly warmer than pure white but readable as off-white against
     bone (#f5f3ef). */
  --canvas:    #faf9f5;
  --ink:       #1a1916;
  --ink-mid:   #4B4742;
  --stone:     #8A847C;
  --rule:      #d4d0ca;
  --rule-soft: #e2ddd3;
  --rule-faint: rgba(45, 35, 25, 0.06);
  --noir:      #1a1612;

  /* Accent — terracotta */
  --acc:       #B85C1E;
  --acc-deep:  #8A3F0F;
  --acc-soft:  #EBDDC8;

  /* Multi-colour icon tones — darker for better legibility on the lighter chips */
  --tone-sage:  #4F6649;
  --tone-slate: #3D5A82;
  --tone-rose:  #8E5763;
  --tone-terra: #8A3F0F;
  --tone-clay:  #80523A;
  --tone-amber: #8A5A14;

  /* Chip backgrounds — lifted ~5% so the icon shows more clearly */
  --chip-sage:  #ECEFE7;
  --chip-slate: #E7ECF2;
  --chip-rose:  #F1E8E9;
  --chip-terra: #F0E5D5;
  --chip-clay:  #EEE4D5;
  --chip-amber: #F1E7D7;

  /* Section tints (residents guide) — washed out, mostly cream-leaning */
  --tint-parchment:        #f3ecdb;
  --tint-aqua:             #e6ede9;
  --tint-lavender:         #e8e2ed;
  --tint-rose:             #f1e5e5;
  --tint-parchment-text:   #6f5634;
  --tint-aqua-text:        #166e68;
  --tint-lavender-text:    #3d3590;
  --tint-rose-text:        #7c2c44;
  /* Slightly deeper variant of each tint — used for dividers and tags */
  --tint-parchment-rule:   #e3d6b8;
  --tint-aqua-rule:        #c8d6cd;
  --tint-lavender-rule:    #cec3d8;
  --tint-rose-rule:        #e0c5c5;
  /* Sage — positive / affirmative green tint (proxy + "have your say") */
  --tint-sage:             #e6efe4;
  --tint-sage-text:        #3f6038;
  --tint-sage-rule:        #cadcc4;
  /* Cool, less-yellow panel tint for Something Missing / Get in Touch panels */
  --panel-bg:              #f1efea;

  /* Safety palette — pulled from v1, washed-out warm red */
  --safety-bg:             #faf2f0;
  --safety-bg-soft:        #f5e6e0;
  --safety-rule:           #eaccc4;
  --safety-rule-soft:      #f0d9d2;
  --safety-text:           #9a2810;
  --safety-text-deep:      #6a1808;

  /* SAT v1-matched colours */
  --sat-amber-bg:    #fdf3e3;
  --sat-amber-border: #e8c870;
  --sat-amber-text:  #7a5010;
  --sat-blue-bg:     #e8f2fa;
  --sat-blue-border: #90b8d8;
  --sat-blue-text:   #1a4a6a;
  --sat-red-note-bg: #fef0f0;
  --sat-red-note-border: #f0b8b8;
  --sat-red-note-text: #5a2020;
  --sat-red-pill-bg: #fce8e8;
  --sat-red-pill-text: #a03030;

  /* Type families */
  --font-sans:   'Mulish', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --font-italic: 'IBM Plex Serif', Georgia, 'Times New Roman', serif;
  --font-mono:   'JetBrains Mono Variable', 'JetBrains Mono', ui-monospace, 'SF Mono', monospace;

  /* Type sizes (mobile-first) */
  --fz-h1: clamp(1.85rem, 6vw, 2.6rem);
  --fz-h2: clamp(1.4rem, 4.4vw, 1.85rem);
  --fz-h3: clamp(1.15rem, 3vw, 1.4rem);
  --fz-h4: 1.05rem;

  /* Tweakable knobs (locked from the picker tool) */
  --nav-glass-alpha:    0.85;
  --pill-glass-alpha:   0.55;
  --pill-padding-y:     8px;
  --pill-padding-x:     14px;
  --pill-fz:            9.5px;
  --pill-bg-rgb:        232, 230, 228;     /* cool stone — replaces yellowish cream */

  /* Promo gradient — 5-stop curve. Locked values from picker. */
  --promo-overlay-top:   0;
  --promo-top-stop:      10%;
  --promo-bot-start:     34%;
  --promo-bot-mid:       66%;
  --promo-bot-mid-alpha: 0.56;
  --promo-overlay-bot:   0.78;
  --promo-h-fz:          1.6rem;

  /* Layout */
  --container:        980px;
  --container-narrow: 720px;
  --container-pad:    1.15rem;
  --band-py:          clamp(2rem, 7vw, 4rem);
  --band-py-sm:       clamp(1.5rem, 5vw, 2.5rem);
  --hero-py:          clamp(2rem, 6vw, 3.75rem);
  --nav-h:            58px;

  /* Radii */
  --r:    4px;
  --r-md: 6px;
  --r-lg: 12px;
}

@media (min-width: 720px) {
  :root { --container-pad: 1.5rem; }
}

/* 3. Type primitives */
html { background: var(--canvas); -webkit-text-size-adjust: 100%; }
body {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--ink);
  background: var(--canvas);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
}

/* Italic emphasis — IBM Plex Serif italic. Plex Serif has a smaller x-height
   than Mulish; nudge size for body but trim it back inside heroes/h1s where
   the larger glyph sizes make Plex feel oversized next to Mulish. */
.lux-em {
  font-family: var(--font-italic);
  font-style: italic;
  font-weight: 400;
  color: var(--acc);
  letter-spacing: 0;
  font-size: 1.04em;
}
.lux-hero h1 .lux-em,
.lux-hero h2 .lux-em,
h1 .lux-em,
h2 .lux-em {
  font-size: 0.95em;
  /* Optical alignment — Plex Serif italic sits slightly higher than Mulish */
  vertical-align: -0.01em;
}

/* Headings — pulled left by ~0.025em so their optical edge lines up with
   the eyebrow above and the description prose below (negative letter-spacing
   otherwise tucks the first character slightly inside the column). */
.lux-h1 { font-family: var(--font-sans); font-weight: 500; letter-spacing: -0.02em; line-height: 1.05; color: var(--ink); font-size: var(--fz-h1); text-wrap: balance; margin-left: -0.025em; }
.lux-h2 { font-family: var(--font-sans); font-weight: 500; letter-spacing: -0.02em; line-height: 1.08; color: var(--ink); font-size: var(--fz-h2); text-wrap: balance; margin-left: -0.025em; }
.lux-h3 { font-family: var(--font-sans); font-weight: 500; letter-spacing: -0.018em; line-height: 1.12; color: var(--ink); font-size: var(--fz-h3); margin-left: -0.02em; }
.lux-h4 { font-family: var(--font-sans); font-weight: 500; letter-spacing: -0.014em; line-height: 1.18; color: var(--ink); font-size: var(--fz-h4); margin-left: -0.015em; }

.lux-eye {
  display: inline-block;
  font-size: 10.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--stone);
  font-weight: 500;
  margin-bottom: 11px;
}

.lux-prose { font-size: 0.95rem; color: var(--ink-mid); line-height: 1.65; }
.lux-prose-sm { font-size: 0.88rem; color: var(--ink-mid); line-height: 1.6; }
.lux-prose strong, .lux-prose-sm strong { color: var(--ink); font-weight: 600; }
.lux-prose a, .lux-prose-sm a { color: var(--acc); text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
.lux-prose a:hover, .lux-prose-sm a:hover { color: var(--acc-deep); }
.lux-prose p + p, .lux-prose-sm p + p { margin-top: 0.85em; }

/* 4. Layout */
.lux-container { width: 100%; max-width: var(--container); margin: 0 auto; padding: 0 var(--container-pad); }
.lux-container--narrow { max-width: var(--container-narrow); }

.lux-band { padding: var(--band-py) 0; position: relative; }
.lux-band--sm { padding: var(--band-py-sm) 0; }
/* Neutral sections all sit on the page canvas — no alternation. The home
   channel strip uses .lux-channels-band to keep its distinct cream tone. */
.lux-band--bone     { background: transparent; }
.lux-band--paper    { background: transparent; }
.lux-band--soft     { background: transparent; }
.lux-band--canvas   { background: transparent; }
.lux-band--bone-dark { background: var(--bone-dark); }

/* Owner's hub — slate-mist surfaces (bands are transparent and inherit the
   tinted page bg; these retint the warm card/tip surfaces to match). */
body.oh-tint .lux-tip { background: #e9eef5; border-color: rgba(60,90,124,0.20); }
/* Tip accent bar — blue on every oh-tint page, including neutral (bone/paper)
   bands where --section-text is unset and would otherwise fall back to orange. */
body.oh-tint .lux-tip::before { background: #3c5a7c; }
html body.oh-tint .lux-card { background: #ffffff !important; border-color: rgba(60,90,124,0.18) !important; }
html body.oh-tint .lux-card--bone { background: #e6ebf2 !important; }
/* Pills — the global `html body .lux-pill { …!important }` refresh layer (further
   down this file) overrides plain `body.oh-tint` rules, so match its weight with
   `html body.oh-tint … !important` to keep owner's-hub pills in the slate-mist palette. */
html body.oh-tint .lux-pill,
html body.oh-tint .lux-acc-body .lux-pill { background: #dce6f1 !important; border-color: rgba(60,90,124,0.32) !important; color: #2f4a63 !important; -webkit-backdrop-filter: none; backdrop-filter: none; }
html body.oh-tint .lux-pill:hover,
html body.oh-tint .lux-acc-body .lux-pill:hover { background: #ccdcec !important; border-color: rgba(60,90,124,0.46) !important; }
html body.oh-tint .lux-pill .lux-ic,
html body.oh-tint .lux-acc-body .lux-pill .lux-ic { color: #3c5a7c !important; }
body.oh-tint .lux-em { color: #3c5a7c; }
body.oh-tint .lux-missing { background: rgba(60,90,124,0.05); border-color: rgba(60,90,124,0.16); }
body.oh-tint .lux-chip { background: #e6ecf3; }
body.oh-tint .lux-chip .lux-ic { color: #3c5a7c; }
/* Owner's hub — drive every in-page section tint (parchment / aqua /
   lavender / rose / sage) to the slate-mist family so icon chips,
   accordions, tags, section pills and the "2026" flag all read as one
   palette instead of their original warm/contrasting section colours. */
body.oh-tint .lux-band--tint-parchment,
body.oh-tint .lux-band--tint-aqua,
body.oh-tint .lux-band--tint-lavender,
body.oh-tint .lux-band--tint-rose,
body.oh-tint .lux-band--tint-sage {
  --section-rule: #c3cfdd;
  --section-text: #3c5a7c;
  --section-soft: #e4eaf1;
}
body.oh-tint .agm-now-flag { background: #d3ddea; color: #2f4a63; }
html body.oh-tint .lux-toc a { background: #e4eaf1 !important; border-color: #c3cfdd !important; color: #3c5a7c !important; }

/* Channels strip on the home page — kept distinct as a warm bone band. */
.lux-channels-band { background: var(--bone); padding: 0.5rem 0; }

/* Section tints — every tint variant sits on the standard page bg.
   The colour comes through inside the accordion card (see scoped rules
   below) and via --section-text / --section-rule on tags + dividers.
   The .lux-band--tint-residents wrapper applies a subtle parchment-tone
   page bg for the resident guide; the safety variants share the paler
   safety bg so the whole guide reads as one warm wash. */
.lux-band--tint-parchment { background: transparent; --section-rule: var(--tint-parchment-rule); --section-text: var(--tint-parchment-text); --section-soft: var(--tint-parchment); }
.lux-band--tint-aqua      { background: transparent; --section-rule: var(--tint-aqua-rule);      --section-text: var(--tint-aqua-text);      --section-soft: var(--tint-aqua); }
.lux-band--tint-lavender  { background: transparent; --section-rule: var(--tint-lavender-rule);  --section-text: var(--tint-lavender-text);  --section-soft: var(--tint-lavender); }
.lux-band--tint-rose      { background: transparent; --section-rule: var(--tint-rose-rule);      --section-text: var(--tint-rose-text);      --section-soft: var(--tint-rose); }
.lux-band--tint-sage      { background: transparent; --section-rule: var(--tint-sage-rule);      --section-text: var(--tint-sage-text);      --section-soft: var(--tint-sage); }
.lux-band--tint-safety    { background: var(--safety-bg); --section-rule: var(--safety-rule);     --section-text: var(--safety-text);         --section-soft: var(--safety-bg-soft); }
.lux-band--tint-safety-soft { background: var(--safety-bg); --section-rule: var(--safety-rule-soft); --section-text: var(--safety-text);     --section-soft: var(--safety-bg-soft); }

/* Inside any tinted section, dividers + indicators reflect the section colour */
[class*="lux-band--tint-"] .lux-acc                       { border-top-color: var(--section-rule); }
[class*="lux-band--tint-"] .lux-acc-it                    { border-bottom-color: var(--section-rule); }
[class*="lux-band--tint-"] .lux-acc-it:last-child         { border-bottom-color: var(--section-rule); }
[class*="lux-band--tint-"] .lux-acc-ind                   { color: var(--section-text); opacity: 0.65; }
[class*="lux-band--tint-"] .lux-acc-it.is-open .lux-acc-ind { color: var(--section-text); opacity: 1; }

/* Section icon chip inside a tinted section — washed-out section bg with
   the section text colour for the icon and a soft section-coloured border. */
[class*="lux-band--tint-"] .lux-section-icon-chip {
  background:
    linear-gradient(rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0.55)),
    var(--section-rule);
  color: var(--section-text);
  border: 1px solid var(--section-rule);
}

/* Accordion list inside a residents-guide tinted section becomes a rounded,
   softly coloured card so the colour reads as the accordion's home rather
   than the whole section. Safety sections already wash the section bg, so
   they keep a flat accordion. */
.lux-band--tint-parchment .lux-acc,
.lux-band--tint-aqua      .lux-acc,
.lux-band--tint-lavender  .lux-acc,
.lux-band--tint-rose      .lux-acc,
.lux-band--tint-sage      .lux-acc {
  background:
    linear-gradient(rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0.55)),
    var(--section-rule);
  border: 1px solid var(--section-rule);
  border-radius: var(--r-md);
  padding: 0 1.1rem;
  border-top-color: var(--section-rule);
}
.lux-band--tint-parchment .lux-acc-it,
.lux-band--tint-aqua      .lux-acc-it,
.lux-band--tint-lavender  .lux-acc-it,
.lux-band--tint-rose      .lux-acc-it,
.lux-band--tint-sage      .lux-acc-it { border-bottom-color: var(--section-rule); }
.lux-band--tint-parchment .lux-acc-it:last-child,
.lux-band--tint-aqua      .lux-acc-it:last-child,
.lux-band--tint-lavender  .lux-acc-it:last-child,
.lux-band--tint-rose      .lux-acc-it:last-child,
.lux-band--tint-sage      .lux-acc-it:last-child { border-bottom: 0; }

/* Hollow tags inside a tinted section — fully transparent so the section's
   wash shows through; the section-rule outline carries the colour. */
[class*="lux-band--tint-"] .lux-tag--hollow,
[class*="lux-band--tint-"] .lux-acc-tag--stone {
  background: transparent;
  border-color: var(--section-rule);
}

/* Inside a tinted section, the body pills (button-style) follow the section
   colour with a soft white-tinted bg for contrast. Tag labels (.lux-acc-tag,
   .lux-tag) automatically inherit --section-text via the rules in 5b. */
[class*="lux-band--tint-"] .lux-acc-body .lux-pill {
  background: rgba(255, 255, 255, 0.55);
  border-color: var(--section-rule);
  color: var(--section-text);
}
[class*="lux-band--tint-"] .lux-acc-body .lux-pill:hover {
  background: rgba(255, 255, 255, 0.85);
  border-color: var(--section-text);
}
[class*="lux-band--tint-"] .lux-acc-body .lux-pill .lux-ic { color: var(--section-text); }

.lux-hr { height: 1px; background: var(--rule); border: 0; margin: 0; }

/* 5. Frosted glass pill */
.lux-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: var(--pill-padding-y) var(--pill-padding-x);
  border-radius: 100px;
  background: rgba(var(--pill-bg-rgb), var(--pill-glass-alpha));
  -webkit-backdrop-filter: blur(14px) saturate(180%);
          backdrop-filter: blur(14px) saturate(180%);
  border: 1px solid rgba(45, 40, 36, 0.14);
  color: #1B1B16;
  font-size: var(--pill-fz);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 500;
  text-decoration: none;
  position: relative;
  isolation: isolate;
  transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}
.lux-pill:hover { background: rgba(var(--pill-bg-rgb), calc(var(--pill-glass-alpha) + 0.25)); border-color: rgba(45, 40, 36, 0.26); }
.lux-pill .lux-ic { color: var(--acc); }

/* Section-header pill — used at the top of a section to take the user to
   the full version of that index. Toasted bone bg with bright off-white
   writing for clear contrast. */
.lux-pill--section {
  background: #9c8e78;
  border-color: #8a7d68;
  color: var(--paper);
}
.lux-pill--section:hover {
  background: #847864;
  border-color: #6f6453;
  color: var(--paper);
}
.lux-pill--section .lux-ic { color: var(--paper); }

/* Pill on dark / image */
.on-dark .lux-pill,
.lux-promo .lux-pill {
  background: rgba(245, 240, 232, 0.14);
  border-color: rgba(255, 255, 255, 0.2);
  color: var(--bone);
}
.on-dark .lux-pill:hover,
.lux-promo .lux-pill:hover { background: rgba(245, 240, 232, 0.28); border-color: rgba(255, 255, 255, 0.36); }
.on-dark .lux-pill .lux-ic, .lux-promo .lux-pill .lux-ic { color: var(--bone); }

/* 5b. Tag — rounded rectangle label (sits next to titles or as status chips).
   Two variants: --solid for key information, --hollow for location/context.
   Always picks up --section-text / --section-rule when scoped inside a tinted
   section, otherwise falls back to ink/stone. */
.lux-tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 4px 8px;
  border-radius: 4px;
  vertical-align: middle;
  line-height: 1;
}
/* Solid tag — key information. Soft section-coloured fill (section rule
   washed back to ~45% over white) + section-coloured text + a section-rule
   outline for definition. */
.lux-tag--solid {
  background:
    linear-gradient(rgba(255, 255, 255, 0.45), rgba(255, 255, 255, 0.45)),
    var(--section-rule, var(--bone-dark));
  color: var(--section-text, var(--ink));
  border: 1px solid var(--section-rule, var(--rule));
}
/* Hollow tag — location/context (e.g. 'Stage 1', 'Stage 2'). No fill at all
   so the page bg shows through, just a section-coloured outline + text. */
.lux-tag--hollow {
  background: transparent;
  color: var(--section-text, var(--ink-mid));
  border: 1px solid var(--section-rule, var(--rule));
}

/* 6. Sheen — codeguage classic shimmer (background-position-based, -45deg).
   Faster swipe, longer gap between cycles, shorter trailing edge,
   ~30% more transparent than the previous pass. */
.lux-sheen {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.lux-sheen::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    -45deg,
    transparent 46%,
    rgba(255, 255, 255, 0.29) 50%,
    transparent 54%
  );
  background-size: 300% 300%;
  background-position: 100% 100%;
  pointer-events: none;
  z-index: 4;
  animation: lux-sheen 7s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  animation-delay: var(--d, 0s);
}
@keyframes lux-sheen {
  0%, 65% { background-position: 100% 100%; }
  100%    { background-position: 0% 0%; }
}

@media (prefers-reduced-motion: reduce) {
  .lux-pill--glow::before,
  .lux-sheen::after { animation: none; }
}

/* 7. Icons */
.lux-ic { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.2; stroke-linecap: round; stroke-linejoin: round; flex-shrink: 0; }
.lux-ic--sm { width: 13px; height: 13px; }
.lux-ic--lg { width: 22px; height: 22px; }

.lux-chip {
  width: 36px; height: 36px;
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  background: var(--chip);
  color: var(--tone);
}
.lux-chip--sm { width: 32px; height: 32px; }
.lux-chip--lg { width: 40px; height: 40px; }

.t-sage  { --tone: var(--tone-sage);  --chip: var(--chip-sage); }
.t-slate { --tone: var(--tone-slate); --chip: var(--chip-slate); }
.t-rose  { --tone: var(--tone-rose);  --chip: var(--chip-rose); }
.t-terra { --tone: var(--tone-terra); --chip: var(--chip-terra); }
.t-clay  { --tone: var(--tone-clay);  --chip: var(--chip-clay); }
.t-amber { --tone: var(--tone-amber); --chip: var(--chip-amber); }
.t-parchment { --tone: var(--tint-parchment-text); --chip: var(--tint-parchment); }
.t-aqua-tint { --tone: var(--tint-aqua-text);      --chip: var(--tint-aqua); }
.t-lavender  { --tone: var(--tint-lavender-text);  --chip: var(--tint-lavender); }
.t-rose-tint { --tone: var(--tint-rose-text);      --chip: var(--tint-rose); }
/* Indigo midnight — newsletter tone (moved off plum/purple, which the
   Grapevine podcast now uses). */
.t-indigo { --tone: #2E3A78; --chip: #DEE1F4; }

/* 8. Channel cells — no outer top/bottom rules (clean entry/exit) */
.lux-channels {
  display: grid;
  /* auto-fit so the grid collapses cleanly when channel cards are
     added or removed (e.g. forum is currently hidden, leaving 2 cards). */
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.lux-channel { padding: 1.4rem 1.15rem 1.5rem; display: flex; flex-direction: column; }
.lux-channel + .lux-channel { border-left: 1px solid var(--rule-faint); }
.lux-channel-icon { margin-bottom: 14px; }
.lux-channel-name { font-weight: 600; font-size: clamp(1.22rem, 3vw, 1.32rem); letter-spacing: -0.022em; line-height: 1.18; margin-bottom: 8px; color: var(--ink); }
.lux-channel-desc { font-size: 0.92rem; color: var(--ink-mid); line-height: 1.55; margin-bottom: 16px; flex: 1; }
.lux-channel-pills { display: flex; flex-wrap: wrap; gap: 8px; align-self: flex-start; }
.lux-channel-pills .lux-pill--mobile { display: inline-flex; }
.lux-channel-pills .lux-pill--desktop { display: none; }
@media (min-width: 701px) {
  .lux-channel-pills .lux-pill--mobile { display: none; }
  .lux-channel-pills .lux-pill--desktop { display: inline-flex; }
}
@media (max-width: 700px) {
  .lux-channels { grid-template-columns: 1fr; }
  .lux-channel + .lux-channel { border-left: 0; border-top: 1px solid var(--rule-faint); }
  .lux-channel { padding: 1.05rem 1rem 1.15rem; }
  .lux-channel-icon { margin-bottom: 10px; }
  .lux-channel-name { font-size: 1.18rem; margin-bottom: 5px; }
  .lux-channel-desc { font-size: 0.88rem; margin-bottom: 11px; }
}

/* 8b. Connect-card chips — brighter backing circle + deeper icon + 1px
   ring, to match the resident-guide section chips (.lux-section-icon-chip).
   Scoped to .lux-channel-icon so the standard .lux-chip used elsewhere
   (app cards, pocket features, etc.) keeps its softer treatment. If a
   third channel returns (e.g. forum, t-slate), add a matching line here. */
.lux-channel-icon.lux-chip { border: 1px solid transparent; }
.lux-channel.t-sage .lux-channel-icon.lux-chip { background: #D7E2CF; color: #3F5A37; border-color: #BCCFB4; }
.lux-channel.t-rose .lux-channel-icon.lux-chip { background: #EDDADA; color: #7C2C44; border-color: #E0C5C5; }
.lux-channel.t-indigo .lux-channel-icon.lux-chip { background: #DEE1F4; color: #2E3A78; border-color: #CFD3EC; }

/* 9. Accordion */
/* Top, between-item and bottom rules all share the same faint colour. */
/* Empty-state placeholder (e.g. "No upcoming meetings or elections.") */
.lux-empty {
  border: 1px dashed var(--rule);
  border-radius: 10px;
  padding: 1.1rem 1.25rem;
  color: var(--ink-mid);
  font-size: 0.95rem;
  line-height: 1.5;
  background: rgba(0,0,0,0.012);
}

.lux-acc { border-top: 1px solid var(--rule-faint); }
.lux-acc-it { border-bottom: 1px solid var(--rule-faint); }
.lux-acc-it:last-child { border-bottom: 1px solid var(--rule-faint); }
.lux-acc-head {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 1.1rem 0;
  text-align: left;
}
.lux-acc-tw { display: flex; align-items: center; gap: 14px; min-width: 0; flex: 1; }
.lux-acc-title {
  font-size: 1.02rem;
  font-weight: 600;
  letter-spacing: -0.018em;
  line-height: 1.22;
  color: var(--ink);
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}
/* Accordion-title tag — same washed-out solid as .lux-tag--solid. */
.lux-acc-tag {
  display: inline-flex;
  align-items: center;
  font-size: 9.5px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase;
  padding: 4px 8px; border-radius: 4px;
  background:
    linear-gradient(rgba(255, 255, 255, 0.45), rgba(255, 255, 255, 0.45)),
    var(--section-rule, var(--bone-dark));
  color: var(--section-text, var(--ink));
  border: 1px solid var(--section-rule, var(--rule));
  line-height: 1;
}
.lux-acc-tag--stone {
  background: transparent;
  color: var(--section-text, var(--ink-mid));
  border: 1px solid var(--section-rule, var(--rule));
}
.lux-acc-tag--terra { background: var(--acc-soft); color: var(--acc-deep); border-color: var(--acc); }
.lux-acc-ind {
  font-size: 1.2rem;
  color: var(--stone);
  line-height: 1;
  flex-shrink: 0;
  font-weight: 300;
  align-self: center;
  transition: transform 0.25s ease, color 0.2s ease;
}
.lux-acc-it.is-open .lux-acc-ind { transform: rotate(45deg); color: var(--acc); }
/* Body breathes open/close. JS measures the actual content height
   and writes inline max-height so the transition runs to the real
   height rather than a generic ceiling. The CSS rule below is a
   no-JS fallback (90rem still produces an animation, just slightly
   off-pace). Opacity transitions in/out faster than height so the
   text fades in once the row is partway open and fades out
   immediately when closing. */
.lux-acc-body {
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  padding: 0 0 0 0;
  font-size: 0.92rem;
  color: var(--ink-mid);
  line-height: 1.65;
  /* Height + padding share the same duration/curve so they finish together.
     The JS (luxAccApplyState) measures the true open height with transitions
     frozen and animates from a fully collapsed state, so the row no longer
     "sticks" just before it settles. */
  transition: max-height 0.4s cubic-bezier(0.32, 0.72, 0, 1),
              opacity 0.2s ease,
              padding 0.4s cubic-bezier(0.32, 0.72, 0, 1);
}
.lux-acc-it.is-open .lux-acc-body {
  max-height: 90rem;
  opacity: 1;
  padding: 0.5rem 0 1.25rem 0;
  /* Tiny delay on the fade-in so it follows just behind the height,
     reading as content arriving INTO an opening row. */
  transition: max-height 0.4s cubic-bezier(0.32, 0.72, 0, 1),
              opacity 0.18s ease 0.06s,
              padding 0.4s cubic-bezier(0.32, 0.72, 0, 1);
}
@media (prefers-reduced-motion: reduce) {
  .lux-acc-body { transition: none; }
}
.lux-acc-body p + p { margin-top: 0.75em; }
.lux-acc-body strong { color: var(--ink); font-weight: 600; }
.lux-acc-body a { color: var(--acc); text-decoration: underline; text-underline-offset: 3px; }
.lux-acc-body .lux-pill { margin-top: 0.85rem; text-decoration: none !important; }
.lux-acc-body .lux-pill { background: rgba(var(--pill-bg-rgb), var(--pill-glass-alpha)); }

/* 10. Image-bg promo */
.lux-promo {
  display: block;
  position: relative;
  aspect-ratio: 4/5;
  background-size: cover;
  background-position: center;
  border-radius: var(--r-md);
  overflow: hidden;
  isolation: isolate;
  text-decoration: none;
  color: var(--bone);
}
.lux-promo--wide { aspect-ratio: 16/10; }
.lux-promo::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(11,11,8,var(--promo-overlay-top)) 0%,
    rgba(11,11,8,0) var(--promo-top-stop),
    rgba(11,11,8,0) var(--promo-bot-start),
    rgba(11,11,8,var(--promo-bot-mid-alpha)) var(--promo-bot-mid),
    rgba(11,11,8,var(--promo-overlay-bot)) 100%);
}
.lux-promo-cap { position: absolute; left: 16px; right: 16px; bottom: 16px; z-index: 3; }
.lux-promo-eye {
  font-family: var(--font-sans);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(245,240,232,0.85);
  margin-bottom: 4px;
}
.lux-promo-h {
  font-weight: 500;
  font-size: var(--promo-h-fz);
  letter-spacing: -0.025em;
  line-height: 1.04;
  margin-bottom: 18px;
  color: var(--bone);
}
.lux-promo-h .lux-em { color: var(--bone); }
.lux-promo-actions { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 0; }
@media (min-width: 720px) {
  .lux-promo--wide { aspect-ratio: 16/10; }
  .lux-promo-cap { left: 22px; right: 22px; bottom: 22px; }
  .lux-promo-h { font-size: 1.65rem; }
}

/* 11. Promo grid — promo cards adopt the wide aspect (16/10) so they match
   the home-page resident-guide promo's mobile height. Two-column grid on
   tablet and up. */
.lux-promo-grid { display: grid; grid-template-columns: 1fr; gap: 12px; }
.lux-promo-grid .lux-promo { aspect-ratio: 16/10; }
@media (min-width: 720px) {
  .lux-promo-grid { grid-template-columns: 1fr 1fr; gap: 14px; }
}

/* 11b. Services card — promo-style banner (bottom-left stacked caption) on a
   solid fill, no image. Sits ~60% of an image card's height.
   A "director"/pointer card: NO sheen and no hover lift (the sheen is reserved
   for the photographic image cards). Uses `on-dark` so the nested `.lux-pill`
   reads as translucent glass with uppercase lettering, matching the image cards.
   Fill is eucalyptus; alternative palettes (bone, warm sand, clay, slate,
   charcoal) are documented in Precinct Hub/STYLEGUIDE.md (Services card). */
.lux-svc {
  display: flex; flex-direction: column; justify-content: flex-end;
  min-height: clamp(110px, 34vw, 156px);
  padding: 18px;
  background: #38574a;
  border-radius: var(--r-md);
  text-decoration: none;
}
.lux-svc-eye {
  font-size: 10.5px; letter-spacing: 0.22em; text-transform: uppercase;
  font-weight: 500; color: rgba(245, 240, 232, 0.82); margin-bottom: 5px;
}
.lux-svc-h {
  font-weight: 500; font-size: 1.45rem; letter-spacing: -0.025em;
  line-height: 1.04; color: var(--bone); margin: 0 0 14px;
}
.lux-svc-h .lux-em { color: var(--bone); }
.lux-svc .lux-pill { align-self: flex-start; }
@media (min-width: 720px) {
  .lux-svc-h { font-size: 1.6rem; }
}

/* 12. Contact card — slim, paper, no edge stripe, unified eyebrow tag */
.lux-contact {
  display: flex;
  flex-direction: column;
  background: var(--paper);
  border-radius: var(--r-md);
  border: 1px solid var(--rule);
  overflow: hidden;
  position: relative;
}
.lux-contact-header {
  padding: 0.8rem 1.05rem 0.85rem;
  border-bottom: 1px solid var(--rule-faint);
}
/* Single neutral eyebrow style across every card */
.lux-contact-role {
  display: inline-block;
  font-size: 9px; letter-spacing: 0.22em; text-transform: uppercase;
  font-weight: 600;
  padding: 3px 9px; border-radius: 4px;
  background: var(--bone-dark);
  color: var(--ink-mid);
  margin-bottom: 7px;
}
.lux-contact-name {
  font-weight: 600; font-size: 1.05rem; letter-spacing: -0.02em;
  color: var(--ink); line-height: 1.2;
}
/* Single-row contact card foot — one row spans the full width */
.lux-contact-foot {
  display: flex;
  flex-direction: row;
  align-items: stretch;
}
.lux-contact-row {
  display: flex; align-items: center; gap: 8px;
  padding: 0.65rem 0.95rem;
  font-size: 0.84rem; color: var(--ink);
  flex: 1 1 0;
  min-width: 0;
}
.lux-contact-row .lux-ic {
  width: 14px; height: 14px; flex-shrink: 0;
  color: var(--ink-mid);
  opacity: 0.85;
}
.lux-contact-action-text {
  flex: 1; min-width: 0;
  color: var(--ink); text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  letter-spacing: -0.005em;
  font-feature-settings: "tnum";
  transition: color 0.15s ease;
}
.lux-contact-action-text:hover { color: var(--acc); }
.lux-contact-copy { display: none !important; }

/* Slide-toggle layout: faces stack absolutely. The visible face has
   .is-current. Each toggle slides the current face out to the LEFT and the
   incoming face in from the RIGHT — both directions move leftward.
   The JS resets the incoming face to the right WITHOUT animation before
   triggering the slide so the second toggle never bounces. */
.lux-contact-foot--slide {
  position: relative;
  overflow: hidden;
  display: block;
}
.lux-contact-deck {
  position: relative;
  width: 100%;
  min-height: 44px;
}
.lux-contact-face {
  display: flex; align-items: center;
  position: absolute;
  inset: 0;
  width: 100%;
  padding: 0.65rem 0.95rem;
  gap: 8px;
  font-size: 0.84rem; color: var(--ink);
  background: var(--paper);
  transform: translateX(100%);
  transition: transform 0.32s cubic-bezier(0.4, 0, 0.2, 1);
  will-change: transform;
}
.lux-contact-face.is-current { transform: translateX(0); }
.lux-contact-face.is-leaving { transform: translateX(-100%); }
/* JS uses .lux-contact-face--snap to position a face without animating. */
.lux-contact-face--snap { transition: none !important; transform: translateX(100%) !important; }

.lux-contact-face .lux-ic {
  width: 14px; height: 14px; flex-shrink: 0;
  color: var(--ink-mid); opacity: 0.85;
}
.lux-contact-face .lux-contact-action-text {
  flex: 1; min-width: 0;
  color: var(--ink); text-decoration: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  letter-spacing: -0.005em;
}
/* Toggle button on the right — shows the *other* mode's icon */
.lux-contact-toggle {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border-radius: 6px;
  background: var(--bone);
  border: 1px solid var(--rule-faint);
  color: var(--ink-mid);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.lux-contact-toggle:hover { background: var(--bone-dark); color: var(--acc); }
.lux-contact-toggle .lux-ic { width: 14px; height: 14px; opacity: 1; }

/* Contacts grid (multiple cards) */
.lux-contact-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
}
@media (min-width: 540px) {
  .lux-contact-grid { grid-template-columns: 1fr 1fr; gap: 14px; }
}

/* 13. List rows — top, bottom and between dividers all share --rule-faint
   for a soft, even rhythm. */
.lux-rows { border-top: 1px solid var(--rule-faint); }
.lux-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 1.15rem 0;
  border-bottom: 1px solid var(--rule-faint);
  text-decoration: none;
  color: inherit;
}
.lux-row:last-child { border-bottom: 1px solid var(--rule-faint); }
.lux-row-left { display: flex; align-items: center; gap: 14px; min-width: 0; flex: 1; }
.lux-row-name { font-weight: 600; font-size: 1.06rem; letter-spacing: -0.02em; color: var(--ink); line-height: 1.2; }
.lux-row-desc { font-size: 0.85rem; color: var(--ink-mid); line-height: 1.5; margin-top: 4px; }
.lux-row-arrow { color: var(--stone); font-size: 1.05rem; flex-shrink: 0; transition: color 0.15s ease, transform 0.15s ease; display: inline-flex; align-items: center; }
.lux-row-arrow .lux-ic { color: currentColor; }
.lux-row:hover .lux-row-arrow { color: var(--acc); transform: translateX(3px); }

/* External-link variant — colour change only on hover, no movement. Use for
   any row whose target opens off-site. */
.lux-row--ext:hover .lux-row-arrow { color: var(--acc); transform: none; }
.lux-row--ext:hover .lux-row-name { color: var(--acc); transition: color 0.15s ease; }

/* Store-pills row variant — non-link parent, keeps iOS/Android (or "Visit X")
   pills on the right at every breakpoint. */
.lux-row--store { cursor: default; }
.lux-row--store:hover { background: transparent; }
.lux-row--store .lux-app-btns { flex-shrink: 0; justify-content: flex-end; }
@media (max-width: 540px) {
  .lux-row--store {
    flex-direction: column;
    align-items: flex-end;
    gap: 10px;
  }
  .lux-row--store .lux-row-left { width: 100%; }
}

/* Category pills — audience labels for helpful resources rows + page heroes.
   Two fixed variants: --owners (teals 2) and --tenants (olive 2). */
.lux-cat-pills {
  display: inline-flex; gap: 5px; flex-wrap: wrap; align-items: center;
  vertical-align: middle;
}
.lux-cat-pill {
  display: inline-flex; align-items: center;
  font-size: 9.5px; font-weight: 600; letter-spacing: 0.07em;
  text-transform: uppercase;
  border-radius: 4px;
  padding: 2.5px 7.5px;
  background: var(--cat-pill-bg);
  color: var(--cat-pill-fg);
  border: 1px solid var(--cat-pill-border);
  white-space: nowrap;
  line-height: 1.4;
  font-family: var(--font-sans);
}
.lux-cat-pill--owners {
  --cat-pill-bg: #c5e0db;
  --cat-pill-fg: #1a443f;
  --cat-pill-border: #a4cbc4;
}
.lux-cat-pill--tenants {
  --cat-pill-bg: #e3dec0;
  --cat-pill-fg: #3e3814;
  --cat-pill-border: #cdc6a1;
}

/* Pills sit above the row name, left-aligned. column-reverse keeps the
   existing markup order (name then pills) but renders pills first visually. */
.lux-row-name-line {
  display: flex;
  flex-direction: column-reverse;
  align-items: flex-start;
  gap: 6px;
}

/* 14. Status pills */
.lux-stat {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 12px;
  border-radius: 100px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  border: 1px solid;
}
.lux-stat::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: 0.85; }
.lux-stat--no-dot::before { display: none; }
.lux-stat--blue   { color: var(--sat-blue-text);  background: var(--sat-blue-bg);  border-color: var(--sat-blue-border); }
.lux-stat--amber  { color: var(--sat-amber-text); background: var(--sat-amber-bg); border-color: var(--sat-amber-border); }
.lux-stat--rose   { color: var(--sat-red-pill-text); background: var(--sat-red-pill-bg); border-color: var(--sat-red-note-border); }
.lux-stat--stone  { color: var(--ink-mid);        background: var(--bone-dark);     border-color: var(--rule); }

/* 15. Generic card */
.lux-card { background: var(--paper); border: 1px solid var(--rule); border-radius: var(--r-md); padding: 1.4rem 1.5rem; }
.lux-card--bone { background: var(--bone-dark); }
.lux-card-eye { font-size: 9.5px; letter-spacing: 0.22em; text-transform: uppercase; color: var(--stone); font-weight: 500; margin-bottom: 9px; display: inline-block; }

/* 15b. Bold crosslink card — a deliberate "go to this related page" block.
   Solid accent fill so it stands out against calm tinted bands. Reuse everywhere
   pages cross-link to each other (one canonical style, not a bespoke box each time). */
.lux-next {
  display: flex; align-items: center; gap: 15px;
  background: #3c5a7c; color: #fff;
  border-radius: var(--r-lg); padding: 17px 19px;
  text-decoration: none;
  box-shadow: 0 12px 28px rgba(60, 90, 124, 0.26);
  transition: transform 0.16s ease, box-shadow 0.16s ease;
}
.lux-next:hover { transform: translateY(-2px); box-shadow: 0 16px 34px rgba(60, 90, 124, 0.34); }
.lux-next-chip {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 11px; background: rgba(255, 255, 255, 0.16);
}
.lux-next-chip .lux-ic { width: 22px; height: 22px; color: #fff; }
.lux-next-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.lux-next-eye {
  font-size: 9.5px; letter-spacing: 0.16em; text-transform: uppercase;
  font-weight: 600; color: rgba(255, 255, 255, 0.74);
}
.lux-next-title { font-size: 1.04rem; font-weight: 700; line-height: 1.25; color: #fff; }
.lux-next-desc { font-size: 0.86rem; line-height: 1.45; color: rgba(255, 255, 255, 0.86); }
.lux-next-arrow { flex: none; width: 22px; height: 22px; color: #fff; transition: transform 0.16s ease; }
.lux-next:hover .lux-next-arrow { transform: translateX(3px); }

/* 15c. Caution alert — the one canonical "this matters, don't get caught out"
   call-out. Maroon is reserved for cautions only, so it reads as a clear signal
   against the calm slate of the rest of the page. Reuse instead of hand-rolling. */
.lux-alert {
  background: #f1e3e7; border: 1px solid #ddbfc8; border-left: 4px solid #8a3550;
  border-radius: var(--r-md); padding: 16px 18px;
}
.lux-alert-head { display: flex; align-items: flex-start; gap: 11px; }
.lux-alert-head .lux-ic { width: 24px; height: 24px; color: #8a3550; flex: none; margin-top: 1px; }
.lux-alert-body { font-size: 14px; line-height: 1.55; color: #7c4256; }
.lux-alert-body strong { color: #5e2b3d; }
.lux-alert-btn {
  display: inline-flex; align-items: center; gap: 6px;
  background: #8a3550; color: #fff; border-radius: 100px;
  padding: 8px 16px; font-size: 13px; text-decoration: none; margin-top: 13px;
}
.lux-alert-btn .lux-ic { color: #fff; }

/* 16. Section title pattern */
.lux-section-title {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.4rem;
}
.lux-section-title h2 { margin: 0; }
.lux-section-count { font-family: var(--font-mono); font-size: 0.78rem; color: var(--stone); letter-spacing: 0.04em; }

/* Section with icon (residents guide) */
.lux-section-icon {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 1.4rem;
}
.lux-section-icon-chip {
  width: 44px; height: 44px;
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  background: var(--chip);
  color: var(--tone);
}
.lux-section-icon-chip svg { width: 22px; height: 22px; }

/* 17. Splitout */
.lux-split { display: grid; grid-template-columns: 1fr; border-radius: var(--r-md); overflow: hidden; border: 1px solid var(--rule); }
.lux-split-left  { padding: 1.5rem 1.6rem; background: var(--noir); color: var(--bone); }
.lux-split-right { padding: 1.5rem 1.6rem; background: var(--bone-soft); }
.lux-split-left .lux-eye { color: rgba(245,240,232,0.65); }
.lux-split-left .lux-h3, .lux-split-left h3 { color: var(--bone); }
.lux-split-left .lux-prose-sm { color: rgba(245,240,232,0.78); }
@media (min-width: 720px) { .lux-split { grid-template-columns: 1fr 1fr; } }

/* Newsletter colour variants */
.lux-split--ink   .lux-split-left { background: #1a1612; }
.lux-split--plum  .lux-split-left { background: #3a2e5c; }
.lux-split--forest .lux-split-left { background: #1f3d2e; }
.lux-split--burgundy .lux-split-left { background: #4a1f24; }
.lux-split--midnight .lux-split-left { background: #1c2438; }

/* Plum splitout — purple-harmonised internals.
   The CSS-variable override re-resolves any inline `var(--acc)`
   inside the right column to the lavender, so eyebrow + dots
   pick it up automatically. */
.lux-split--plum .lux-split-right {
  --acc: #6e5ea6;
  background: #ede8f5;
}
.lux-split--plum .lux-split-right .lux-eye { color: #4d3f88; }

.lux-split--plum .lux-split-left .lux-pill {
  background: rgba(220, 210, 245, 0.95);
  color: #1e1535;
  border-color: rgba(220, 210, 245, 0.6);
}
.lux-split--plum .lux-split-left .lux-pill:hover {
  background: #fff;
  border-color: rgba(255, 255, 255, 0.85);
  color: #1e1535;
}
.lux-split--plum .lux-split-left .lux-pill .lux-ic { color: #1e1535; }
.lux-split--plum .lux-split-left .lux-pill--ghost {
  background: transparent;
  border-color: rgba(220, 210, 245, 0.45);
  color: #d6c8f0;
}
.lux-split--plum .lux-split-left .lux-pill--ghost:hover {
  background: rgba(220, 210, 245, 0.1);
  border-color: rgba(220, 210, 245, 0.8);
  color: #fff;
}
.lux-split--plum .lux-split-left .lux-pill--ghost .lux-ic { color: #d6c8f0; }

/* Midnight splitout — indigo-harmonised internals (newsletter colour).
   Mirrors the plum block: the right column re-resolves var(--acc) to the
   indigo mid so the eyebrow + bullet dots pick it up automatically. */
.lux-split--midnight .lux-split-right {
  --acc: #4f5bd5;
  background: #e5e7f6;
}
.lux-split--midnight .lux-split-right .lux-eye { color: #2e3a78; }
/* !important throughout: the global `html body .lux-pill { …!important }`
   layer forces a warm-cream pill site-wide, so the tinted pills here only
   win with !important (same approach as the newsletter page). */
.lux-split--midnight .lux-split-left .lux-pill {
  background: rgba(212, 216, 242, 0.95) !important;
  color: #161d33 !important;
  border-color: rgba(212, 216, 242, 0.6) !important;
}
.lux-split--midnight .lux-split-left .lux-pill:hover {
  background: #fff !important;
  border-color: rgba(255, 255, 255, 0.85) !important;
  color: #161d33 !important;
}
.lux-split--midnight .lux-split-left .lux-pill .lux-ic { color: #161d33 !important; }
.lux-split--midnight .lux-split-left .lux-pill--ghost {
  background: transparent;
  border-color: rgba(212, 216, 242, 0.45);
  color: #c7cdf2;
}
.lux-split--midnight .lux-split-left .lux-pill--ghost:hover {
  background: rgba(212, 216, 242, 0.1);
  border-color: rgba(212, 216, 242, 0.8);
  color: #fff;
}
.lux-split--midnight .lux-split-left .lux-pill--ghost .lux-ic { color: #c7cdf2; }

/* 17b. Hamburger + fullscreen menu (Apple-inspired)
   ─────────────────────────────────────────────────
   Two horizontal bars that flip into an X when active. Sits at the
   right of the nav, with the App pill immediately before it. Tap opens
   a fullscreen scrollable sheet that covers the page below the nav. */
.lux-nav-right {
  display: flex; align-items: center; gap: 0.85rem;
}
.lux-menu-toggle {
  position: relative;
  width: 36px; height: 36px;
  display: inline-flex;
  align-items: center; justify-content: center;
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: var(--ink);
  -webkit-tap-highlight-color: transparent;
}
.lux-menu-toggle span {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 22px; height: 1.5px;
  background: currentColor;
  border-radius: 2px;
  transform-origin: 50% 50%;
  margin-left: -11px;
  /* Force a GPU compositing layer so iOS Safari uses the accelerated
     path for transform changes instead of repainting (which it
     otherwise skips/snaps to the end state). backface-visibility +
     translate3d in the transform are the two standard nudges. */
  will-change: transform;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  /* Both vendor-prefixed and unprefixed transition for older WebKit. */
  -webkit-transition: -webkit-transform 0.32s cubic-bezier(0.65, 0, 0.35, 1);
  transition: transform 0.32s cubic-bezier(0.65, 0, 0.35, 1),
              -webkit-transform 0.32s cubic-bezier(0.65, 0, 0.35, 1);
}
/* Two parallel bars 5.5px apart in the rest state. Both initial and open
   transforms use translate3d + rotate (matching function lists) so iOS
   Safari can interpolate between them without dropping the transition. */
.lux-menu-toggle span:first-child {
  -webkit-transform: translate3d(0, -4.5px, 0) rotate(0deg);
  transform: translate3d(0, -4.5px, 0) rotate(0deg);
}
.lux-menu-toggle span:last-child {
  -webkit-transform: translate3d(0, 3px, 0) rotate(0deg);
  transform: translate3d(0, 3px, 0) rotate(0deg);
}
/* Smoothly converge to the centre, then rotate into the X. */
.lux-menu-toggle.is-open span:first-child {
  -webkit-transform: translate3d(0, 0, 0) rotate(45deg);
  transform: translate3d(0, 0, 0) rotate(45deg);
}
.lux-menu-toggle.is-open span:last-child {
  -webkit-transform: translate3d(0, 0, 0) rotate(-45deg);
  transform: translate3d(0, 0, 0) rotate(-45deg);
}

/* Fullscreen menu drawer — apple.com mega-menu feel.
   The drawer animation uses transform: translate3d() instead of height,
   which is GPU-accelerated by mobile WebKit and stays smooth at 60fps
   on iOS. (Height/max-height transitions trigger layout every frame and
   are notoriously jerky on iOS Safari.) The drawer is full-height and
   lives translated -100% (above the viewport) when closed; toggling
   .is-open animates it down to translate3d(0,0,0). The items inside
   use opacity-only transitions for the staggered cascade — opacity is
   also GPU-accelerated and cheap to animate concurrently. */
.lux-menu {
  position: fixed;
  /* Anchor to all four edges of the visible viewport. Using
     `bottom: 0` instead of `height: calc(100vh - var(--nav-h))`
     because mobile Safari's 100vh is keyed to the largest possible
     viewport (URL bar collapsed). When the URL bar is showing the
     menu would otherwise stop short of the actual bottom edge and
     the page behind would bleed through. With four-edge anchoring
     the menu always covers the live visible area. */
  top: var(--nav-h); left: 0; right: 0; bottom: 0;
  /* Same frosted-glass treatment as .lux-nav so the menu reads as
     an extension of the bar above. Slightly more solid translucent
     paper so the menu items have decent contrast. */
  background: rgba(245, 243, 238, 0.55);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
          backdrop-filter: saturate(160%) blur(14px);
  z-index: 49;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  /* Closed: slid up out of view. visibility removes it from the
     accessibility tree until the open animation kicks in. */
  -webkit-transform: translate3d(0, -100%, 0);
  transform: translate3d(0, -100%, 0);
  visibility: hidden;
  pointer-events: none;
  -webkit-transition:
    -webkit-transform 0.36s cubic-bezier(0.4, 0, 0.2, 1),
    visibility 0s linear 0.36s;
  transition:
    transform 0.36s cubic-bezier(0.4, 0, 0.2, 1),
    -webkit-transform 0.36s cubic-bezier(0.4, 0, 0.2, 1),
    visibility 0s linear 0.36s;
  will-change: transform;
}
body.is-menu-open { overflow: hidden; }
/* Browsers without backdrop-filter get a more opaque background so
   menu items stay legible — same fallback pattern as the nav. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .lux-menu { background: rgba(245, 243, 238, 0.97); }
}
.lux-menu.is-open {
  -webkit-transform: translate3d(0, 0, 0);
  transform: translate3d(0, 0, 0);
  visibility: visible;
  pointer-events: auto;
  -webkit-transition:
    -webkit-transform 0.36s cubic-bezier(0.4, 0, 0.2, 1),
    visibility 0s linear 0s;
  transition:
    transform 0.36s cubic-bezier(0.4, 0, 0.2, 1),
    -webkit-transform 0.36s cubic-bezier(0.4, 0, 0.2, 1),
    visibility 0s linear 0s;
}
.lux-menu-inner {
  max-width: var(--container);
  margin: 0 auto;
  padding: 1.4rem var(--container-pad) calc(2rem + env(safe-area-inset-bottom));
}
/* Sections don't have a divider between them — each section's eyebrow is
   the only visual separator. */
.lux-menu-section + .lux-menu-section { margin-top: 1.4rem; }
.lux-menu-eye {
  font-size: 10.5px; letter-spacing: 0.22em; text-transform: uppercase;
  /* Sits between --stone (medium-light) and --ink (very dark) so it
     reads as a clear section label without competing with the menu
     links right below it. */
  color: var(--ink-mid); font-weight: 500;
  display: block; margin-bottom: 0.15rem;
}
/* When an eyebrow appears mid-level (e.g. the 'Connect' eyebrow in the
   root list), give it some breathing room above — but keep it close to
   the link directly below. Match both the link sibling (legacy) and the
   group sibling (current single-level menu where parents are wrapped in
   .lux-menu-group). */
.lux-menu-link + .lux-menu-eye,
.lux-menu-group + .lux-menu-eye { margin-top: 1.6rem; }
.lux-menu-link {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.5rem 0;
  font-size: clamp(1.35rem, 4vw, 1.7rem);
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-decoration: none;
  background: none; border: 0;
  text-align: left;
  width: 100%;
  cursor: pointer;
  font-family: inherit;
  transition: color 0.15s ease, padding 0.15s ease;
  /* iOS — kill the grey/blue tap rectangle that flashes over the link
     for ~1s after a tap. */
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
}
/* Hover styles are scoped to (hover: hover) so iOS Safari doesn't keep
   them stuck after a tap (touch devices report hover: none). Without
   this, tapping a parent item left it indented + terracotta even after
   the submenu closed. */
@media (hover: hover) {
  .lux-menu-link:hover { color: var(--acc); padding-left: 4px; }
  .lux-menu-link:hover .lux-menu-link-chev { color: var(--acc); transform: translateX(3px); }
}
/* Right-side chevron for parent items (those that open a sub-level).
   Inline SVG, sized large for prominence but with a thin (1.5px)
   non-scaling stroke so the line weight matches the hamburger bars
   regardless of display size. The viewBox is 24×24 with the chevron
   path drawn with stroke-linecap/linejoin rounded for a soft tip. */
.lux-menu-link-chev {
  flex-shrink: 0;
  width: 1.7rem;
  height: 1.7rem;
  color: var(--stone);
  margin-left: 12px;
  display: inline-block;
  transition: color 0.15s ease, transform 0.15s ease;
}
.lux-menu-link-chev path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
/* Hide any stray arrow markup left over from earlier markup. */
.lux-menu-link-arrow { display: none; }

/* Single-level menu with inline expandable submenu groups. Tapping a parent
   item reveals its sub-items inline, indented and slightly smaller. The
   parent's row stays put; the items below it slide downward to make room
   while each sub-item fades into view in sequence. */
.lux-menu-list { position: relative; display: block; }

.lux-menu-group { display: block; }

.lux-menu-parent .lux-menu-link-chev { transition: color 0.15s ease, transform 0.25s ease; }
.lux-menu-parent.is-open .lux-menu-link-chev { transform: rotate(90deg); color: var(--acc); }

/* Top-level menu items — opacity-only fade-in for the apple.com cascade.
   Per-item transition-delay is set inline by JS (calc(var(--i)…) in
   CSS isn't reliably honoured on mobile WebKit). Opacity is the
   cheapest property to animate — GPU-composited, no layout impact. */
.lux-menu-list > .lux-menu-link,
.lux-menu-list > .lux-menu-group,
.lux-menu-list > .lux-menu-eye {
  opacity: 0;
  -webkit-transition: opacity 0.22s ease;
  transition: opacity 0.22s ease;
}
.lux-menu.is-open .lux-menu-list > .lux-menu-link,
.lux-menu.is-open .lux-menu-list > .lux-menu-group,
.lux-menu.is-open .lux-menu-list > .lux-menu-eye {
  opacity: 1;
}

/* Submenu drawer — max-height transition is unavoidable here because we
   need the items below the parent button to physically slide down to
   make room. Mobile WebKit can be jerky on max-height, but it's a
   small panel (one open at a time, short content) so the cost is
   bounded. CSS transition (browser-optimised) instead of WAAPI. */
.lux-menu-sub {
  max-height: 0;
  overflow: hidden;
  -webkit-transition: max-height 0.28s cubic-bezier(0.4, 0, 0.2, 1);
  transition: max-height 0.28s cubic-bezier(0.4, 0, 0.2, 1);
}
.lux-menu-sub-inner { display: block; }

.lux-menu-sublink {
  display: block;
  padding: 0.32rem 0 0.32rem 1.4rem;
  font-size: clamp(0.95rem, 2.6vw, 1.1rem);
  font-weight: 400;
  letter-spacing: -0.01em;
  color: var(--ink-mid);
  text-decoration: none;
  font-family: inherit;
  opacity: 0;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  -webkit-transition: opacity 0.22s ease, color 0.15s ease, padding 0.15s ease;
  transition: opacity 0.22s ease, color 0.15s ease, padding 0.15s ease;
}
@media (hover: hover) {
  .lux-menu-sublink:hover { color: var(--acc); padding-left: calc(1.4rem + 4px); }
}
.lux-menu-sub.is-open .lux-menu-sublink { opacity: 1; }

/* Sub-section eyebrow INSIDE a megamenu submenu (e.g. 'All residents',
   'Owners' inside Helpful resources). Mirrors the root-level
   .lux-menu-eye 'Connect' divider, but smaller and a lighter grey
   (--stone) so it reads as a quiet grouping label sitting above the
   sublinks rather than competing with them. Indented to 1.4rem to line
   up with the sublink text. Fades in with the submenu (opacity tied to
   .lux-menu-sub.is-open); theme.js also gives it a staggered delay
   alongside the sublinks. */
.lux-menu-eye--sub {
  display: block;
  padding: 0.5rem 0 0.2rem 1.4rem;
  margin-top: 0.3rem;
  font-size: 9.5px; letter-spacing: 0.18em; text-transform: uppercase;
  font-weight: 600; color: #4B4742;
  opacity: 0;
  -webkit-transition: opacity 0.22s ease;
  transition: opacity 0.22s ease;
}
.lux-menu-sub-inner > .lux-menu-eye--sub:first-child { margin-top: 0; }
.lux-menu-sub.is-open .lux-menu-eye--sub { opacity: 1; }

/* Black 'New' pill on a megamenu sublink — used to mark recently added
   pages (e.g. SAT charge allocation dispute). Sits inline after the link
   text in two contexts: small sublinks in the megamenu, and larger row
   names on the homepage. Both use vertical-align: middle, which aligns
   the pill's mathematical centre to the parent's x-height centre – that
   lands slightly low next to mixed-case text, so we nudge the pill up
   1px so it reads as optically centred against the cap-height of the
   surrounding word. */
.lux-menu-new {
  display: inline-block;
  font-size: 9px; font-weight: 700; letter-spacing: 0.09em;
  text-transform: uppercase;
  padding: 2px 6px;
  background: var(--ink);
  color: var(--paper);
  border-radius: 3px;
  margin-left: 8px;
  vertical-align: middle;
  transform: translateY(-1px);
  line-height: 1.3;
}

@media (prefers-reduced-motion: reduce) {
  /* Just the chevron rotation transition — the menu drawer + item
     cascades intentionally keep animating because they're small
     purposeful UI feedback, not vestibular-disturbing motion. */
  .lux-menu-parent .lux-menu-link-chev {
    transition: none !important;
  }
}

/* 18. Nav — transparent frosted glass. The low alpha + heavy backdrop blur
   lets content scroll visibly underneath while keeping the nav text legible. */
.lux-nav {
  position: sticky;
  top: 0;
  z-index: 50;
  height: var(--nav-h);
  background: rgba(245, 243, 238, 0.22);
  -webkit-backdrop-filter: saturate(160%) blur(10px);
          backdrop-filter: saturate(160%) blur(10px);
  border-bottom: 1px solid rgba(45, 40, 36, 0.06);
  display: flex;
  align-items: center;
}
/* Browsers without backdrop-filter support get a slightly more solid bg so
   text stays legible. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .lux-nav { background: rgba(245, 243, 238, 0.85); }
}
.lux-nav-inner { width: 100%; max-width: var(--container); margin: 0 auto; padding: 0 var(--container-pad); display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.lux-nav-logo { font-weight: 600; font-size: 1rem; letter-spacing: -0.022em; color: var(--ink); text-decoration: none; }
.lux-nav-logo small { font-family: var(--font-mono); font-weight: 400; font-size: 0.62rem; letter-spacing: 0.16em; color: var(--stone); margin-left: 7px; vertical-align: middle; }
.lux-nav-links { display: flex; align-items: center; gap: 1.4rem; }
.lux-nav-link { font-size: 0.82rem; font-weight: 500; color: var(--ink-mid); text-decoration: none; letter-spacing: -0.005em; transition: color 0.15s ease; }
.lux-nav-link:hover { color: var(--acc); }
/* Nav pill — primary CTA. Always orange with bone text so it reads as the
   main action even when the user can't hover (touch). Hover deepens the
   tone but keeps the writing light. */
.lux-nav-link--pill {
  padding: 7px 14px;
  border-radius: 100px;
  background: var(--acc);
  border: 1px solid var(--acc);
  color: var(--bone);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.lux-nav-link--pill:hover { background: var(--acc-deep); border-color: var(--acc-deep); color: var(--bone); }
/* The App pill is a PWA install / open-the-app prompt – only useful on
   mobile (phones/tablets) where you can add the site to the home screen.
   We hide it on desktop only, using a width breakpoint (>=768px, matching
   the pocket card). NOTE: this previously used
   `(hover: hover) and (pointer: fine)` to mean "desktop", but that query
   misfires on many phones (which report hover/fine), wrongly hiding the
   App pill on mobile. Width is the reliable signal. */
@media (min-width: 768px) {
  .lux-nav-link--pill { display: none; }
}
/* Settings cog – a label-less icon button that ONLY appears when the
   site is launched as an installed PWA. We hide it everywhere else
   (browser tabs, desktop) because settings only make sense for the
   home-screen experience. */
.lux-nav-cog {
  display: none;
  width: 36px; height: 36px;
  align-items: center; justify-content: center;
  border-radius: 50%;
  color: var(--ink-mid);
  text-decoration: none;
  background: transparent;
  border: 0;
  transition: color 0.15s ease, background 0.15s ease;
}
.lux-nav-cog:hover { color: var(--acc); background: var(--bone-dark); }
.lux-nav-cog svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
@media (display-mode: standalone) {
  .lux-nav-cog { display: inline-flex; }
  /* In a PWA, the App pill is redundant – the user is already in the
     installed app. Hide it so the cog has room to breathe. */
  .lux-nav-link--pill { display: none; }
}
/* iOS Safari uses navigator.standalone instead of display-mode. */
html.lux-pwa .lux-nav-cog { display: inline-flex; }
html.lux-pwa .lux-nav-link--pill { display: none; }
@media (max-width: 560px) {
  .lux-nav-link[data-hide-sm] { display: none; }
  .lux-nav-links { gap: 0.85rem; }
}

/* 19. Crumbs */
.lux-crumbs { display: flex; align-items: center; gap: 0.45rem; flex-wrap: wrap; font-size: 0.78rem; color: var(--stone); margin-bottom: 1.5rem; }
.lux-crumbs a { color: var(--stone); text-decoration: none; }
.lux-crumbs a:hover { color: var(--ink); }
.lux-crumbs-sep { color: var(--rule); }

/* 20. Hero — bone-dark at top fading down to the page canvas, so the hero
   feels distinct without abruptly ending at the next section. Image hero
   overrides via its own bg below. */
.lux-hero {
  padding: var(--hero-py) 0 calc(var(--hero-py) * 0.7);
  background: linear-gradient(180deg, var(--bone-dark) 0%, var(--canvas) 100%);
}
.lux-hero h1 { font-family: var(--font-sans); font-weight: 500; font-size: var(--fz-h1); letter-spacing: -0.02em; line-height: 1.05; margin: 0 0 14px -0.025em; }
/* Description fills the standard column — the container's own padding
   provides the comfortable reading inset. Previously capped at 56ch,
   which sat noticeably short of the 720px narrow column on desktop. */
.lux-hero-sub { font-size: 1rem; color: var(--ink-mid); line-height: 1.6; }

/* Hero with image (home page) — day/night swap */
.lux-hero--image {
  position: relative;
  min-height: 440px;
  display: flex;
  align-items: flex-end;
  background-color: #26201a;
  overflow: hidden;
  padding: var(--hero-py) 0 calc(var(--hero-py) * 0.8);
}
.lux-hero-bg {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center 40%;
  transition: opacity 1.5s ease;
}
.lux-hero-toggle {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 50px;
  background: transparent;
  border: 0;
  cursor: default;
  z-index: 5;
  padding: 0; margin: 0;
  -webkit-tap-highlight-color: transparent;
}
.lux-hero--image::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(38,32,26,0.12) 0%, rgba(38,32,26,0.38) 40%, rgba(38,32,26,0.82) 72%, rgba(38,32,26,0.94) 100%);
  z-index: 1;
  transition: background 1.5s ease;
}
.lux-hero--image.is-night::before {
  background: linear-gradient(to bottom, rgba(0,0,0,0) 0%, rgba(0,0,0,0.27) 40%, rgba(0,0,0,0.7) 72%, rgba(0,0,0,0.7) 100%);
}
.lux-hero--image .lux-container { position: relative; z-index: 2; width: 100%; }
.lux-hero--image h1 { color: #f0ece4; }
.lux-hero--image .lux-eye { color: rgba(240,236,228,0.82); }
.lux-hero--image .lux-hero-sub { color: rgba(240,236,228,0.78); }

/* 21. TOC chips */
.lux-toc { display: flex; flex-wrap: wrap; gap: 0.45rem; margin-top: 1.5rem; }
.lux-toc a {
  font-size: 0.82rem;
  font-weight: 500;
  letter-spacing: -0.005em;
  padding: 9px 16px;
  border-radius: 100px;
  background: rgba(var(--pill-bg-rgb), 0.55);
  -webkit-backdrop-filter: blur(12px) saturate(180%);
          backdrop-filter: blur(12px) saturate(180%);
  border: 1px solid rgba(45, 40, 36, 0.16);
  color: var(--ink);
  text-decoration: none;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.lux-toc a:hover { background: rgba(var(--pill-bg-rgb), 0.85); border-color: var(--acc); color: var(--acc); }

/* 21b. Precinct-in-pocket card — promotes the home-screen PWA. Sits inline
   in the homepage flow. Two-part: dark/image hero on top, neutral card on
   the bottom with a feature list and the Get-the-app CTA.

   Visibility:
   - Mobile browsers: shown (this is who the prompt is for).
   - Installed PWA (display-mode: standalone): hidden, the user already
     has the home-screen app.
   - Desktop (width ≥ 768px): hidden, the prompt only makes sense on
     mobile where you can actually add to the home screen.
   - The .is-pocket-dismissed body class (set by JS when the user taps
     "Not interested" on the top card and stored in localStorage) hides
     #lux-pocket-top across reloads. */
.lux-pocket {
  border-radius: var(--r-md);
  overflow: hidden;
  border: 1px solid var(--rule);
}
@media (display-mode: standalone) {
  .lux-pocket { display: none !important; }
}
@media (min-width: 768px) {
  .lux-pocket { display: none !important; }
}
body.is-pocket-dismissed #lux-pocket-top { display: none !important; }
/* Also hide the wrapper section so the spacing collapses cleanly. */
body.is-pocket-dismissed #lux-pocket-top-wrap { display: none !important; }
.lux-pocket-top {
  position: relative;
  background: #2e2b27 url('/imagery/Precinct_Facade.webp') center/cover;
  padding: 1.5rem 1.4rem 1.6rem;
  isolation: isolate;
}
/* Pulled from the v1 card: a top-down black wash for type contrast,
   layered over a 135° pink → purple → blue colour wash that gives the
   photo its signature 'colourful' feel. */
.lux-pocket-top::before {
  content: '';
  position: absolute; inset: 0;
  z-index: 0;
  background:
    linear-gradient(to bottom, rgba(0, 0, 0, 0.10) 0%, rgba(0, 0, 0, 0.55) 100%),
    linear-gradient(135deg, rgba(236, 72, 153, 0.72) 0%, rgba(147, 51, 234, 0.75) 50%, rgba(59, 130, 246, 0.70) 100%);
}
.lux-pocket-top > * { position: relative; z-index: 1; }
.lux-pocket-eye {
  font-size: 10.5px; letter-spacing: 0.22em; text-transform: uppercase;
  color: rgba(245, 240, 232, 0.85); font-weight: 500;
  margin-bottom: 8px; display: block;
}
/* Headline matches the image-promo title size. The em ('in your pocket.')
   stays inline so the headline reads as one phrase, but never breaks
   mid-phrase — if it can't fit on the same line, the whole em wraps to
   the next line as a unit. */
.lux-pocket-headline {
  font-family: var(--font-sans);
  font-size: var(--promo-h-fz);
  font-weight: 500;
  letter-spacing: -0.025em;
  line-height: 1.04;
  color: var(--bone);
  text-wrap: balance;
}
.lux-pocket-headline .lux-em {
  display: inline;
  white-space: nowrap;
  color: var(--bone);
}
.lux-pocket-sub {
  font-size: 0.9rem; line-height: 1.55;
  color: rgba(245, 240, 232, 0.85);
  margin-top: 12px;
}
@media (min-width: 720px) {
  .lux-pocket-headline { font-size: 1.75rem; }
}
.lux-pocket-bottom {
  background: var(--paper);
  padding: 1.1rem 1.4rem 1.25rem;
}
.lux-pocket-features {
  display: flex; flex-direction: column;
  margin: 0 0 1rem;
  padding: 0;
  list-style: none;
  font-size: 0.85rem; color: var(--ink-mid);
  line-height: 1.6;
}
.lux-pocket-features li { padding: 2px 0; list-style: none; }
.lux-pocket-features li strong { color: var(--ink); font-weight: 600; }
.lux-pocket-channels {
  font-size: 0.78rem; color: var(--stone);
  margin-left: 0.65rem;
}
.lux-pocket-actions {
  display: flex; align-items: center; gap: 1rem;
  flex-wrap: wrap;
}
.lux-pocket-cta {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 16px; border-radius: 999px;
  background: var(--ink); color: var(--bone);
  font-size: 0.82rem; font-weight: 500; letter-spacing: 0.02em;
  text-decoration: none;
  transition: background 0.15s ease;
}
.lux-pocket-cta:hover { background: var(--noir); color: var(--bone); }
.lux-pocket-dismiss {
  font-size: 0.78rem; font-weight: 400;
  color: var(--stone); background: none; border: 0;
  padding: 0; cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
  transition: color 0.15s ease;
  font-family: inherit;
}
.lux-pocket-dismiss:hover { color: var(--ink-mid); }

/* ---------- Pocket card: expand in place ----------
   Tapping "Get the app" fades out the simple feature list and
   fades in (a) a compact icon-led feature LIST – no card frames,
   no dividers, just stacked rows – and (b) install steps with
   the iOS/Android switcher. The CTA flips to "Close", which
   plays the same animation in reverse: the expanded items fade
   out and the summary list fades back in. All transitions are
   transition-based (not @keyframes) so reversing is symmetric
   and respects in-flight state. */
.lux-pocket-features[data-pocket-summary] {
  opacity: 1;
  transition: opacity 0.22s ease;
}
.lux-pocket-features[data-pocket-summary].is-fading-out {
  opacity: 0;
  pointer-events: none;
}
.lux-pocket-features[data-pocket-summary].is-fading-in {
  opacity: 0;
}
.lux-pocket.is-expanded .lux-pocket-features[data-pocket-summary] {
  display: none;
}
/* Dismiss button fades in/out alongside the summary – avoids it
   popping in suddenly at the end of the close animation. */
[data-pocket-dismiss] {
  opacity: 1;
  transition: opacity 0.22s ease;
}
.lux-pocket.is-expanded [data-pocket-dismiss],
.lux-pocket.is-collapsing [data-pocket-dismiss] {
  opacity: 0;
  pointer-events: none;
}
.lux-pocket-expanded {
  display: none;
  flex-direction: column;
  gap: 0.9rem;
  margin: 0 0 1rem;
}
.lux-pocket.is-expanded .lux-pocket-expanded {
  display: flex;
}
.lux-pocket-expanded > * {
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.22s ease, transform 0.22s ease;
}
/* Top-level children fade up in sequence using their --i. The feats
   container is --i:0 so it appears immediately; the install panel
   is given a higher index in JS so it cascades in AFTER the rolling
   list of items finishes (otherwise it'd appear under them while
   they're still rolling in). */
.lux-pocket.is-expanded:not(.is-collapsing) .lux-pocket-expanded > * {
  opacity: 1;
  transform: translateY(0);
  transition-delay: calc(var(--i, 0) * 60ms);
}
/* Collapsing: every visible expanded child fades out at the same
   time. Duration matches FADE_OUT_MS in theme.js so the height
   shrink (started simultaneously) is perfectly aligned. */
.lux-pocket.is-collapsing .lux-pocket-expanded > * {
  opacity: 0;
  transform: translateY(2px);
  transition-duration: 0.18s;
  transition-delay: 0ms;
}

/* Compact feature list — list items only, no card chrome, no
   horizontal dividers between them. */
.lux-pocket-x-feats {
  display: flex; flex-direction: column;
  gap: 2px;
  padding: 0; margin: 0;
  list-style: none;
}
.lux-pocket-x-feat {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 6px 0;
  background: transparent;
  border: 0;
  /* Stagger fade for individual feature items – each child gets
     its own --i index. The is-collapsing rule above already
     reverses the parent fade; individual rows reverse via this
     rule's symmetry. */
  opacity: 0;
  transform: translateY(3px);
  transition: opacity 0.18s ease, transform 0.18s ease;
}
.lux-pocket.is-expanded:not(.is-collapsing) .lux-pocket-x-feat {
  opacity: 1;
  transform: translateY(0);
  /* 75ms per item gives a clearly perceptible "rolling list" feel
     without dragging the whole entrance out. With six items the
     last one finishes around 75 × 5 + 220 (the fade duration) = 595ms. */
  transition-delay: calc(var(--i, 0) * 75ms);
}
.lux-pocket.is-collapsing .lux-pocket-x-feat {
  opacity: 0;
  transform: translateY(2px);
  transition-duration: 0.18s;
  transition-delay: 0ms;
}
.lux-pocket-x-feat .lux-chip {
  width: 28px; height: 28px; flex: 0 0 28px;
  margin-top: 1px;
}
.lux-pocket-x-feat .lux-chip svg { width: 14px; height: 14px; }
.lux-pocket-x-fbody { min-width: 0; }
.lux-pocket-x-fname {
  display: block;
  font-size: 0.88rem; font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.012em;
  line-height: 1.3;
}
.lux-pocket-x-fdesc {
  display: block;
  font-size: 0.8rem; color: var(--ink-mid);
  line-height: 1.5;
  margin-top: 2px;
}
.lux-pocket-x-installhead {
  display: block;
  font-size: 0.78rem; font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.005em;
  margin: 4px 0 8px;
}
.lux-pocket-x-install .lux-steps { gap: 0.7rem; margin-top: 0.6rem; }
.lux-pocket-x-install .lux-step-num { width: 26px; height: 26px; font-size: 0.74rem; }
.lux-pocket-x-install .lux-step-text { font-size: 0.85rem; line-height: 1.5; }
.lux-pocket-x-install .lux-osswitch { margin-bottom: 0.4rem; }
.lux-pocket-x-install .lux-osswitch button { padding: 5px 14px; font-size: 0.74rem; }
.lux-pocket-x-tip {
  margin-top: 0.7rem;
  font-size: 0.78rem; color: var(--ink-mid);
  line-height: 1.5;
  padding: 0.65rem 0.8rem;
  background: var(--bone-soft);
  border: 1px solid var(--rule);
  border-radius: 8px;
}

/* 21c. Upcoming events list — softly tinted card with day-tag dates. */
.lux-events {
  background: rgba(200, 236, 230, 0.18);
  border: 1px solid rgba(15, 110, 86, 0.18);
  border-radius: var(--r-md);
  overflow: hidden;
}
.lux-events-list { display: flex; flex-direction: column; }
.lux-events-item {
  display: flex; align-items: flex-start; gap: 14px;
  padding: 0.95rem 1.1rem;
  border-bottom: 1px solid rgba(15, 110, 86, 0.12);
}
.lux-events-item:last-child { border-bottom: 0; }
.lux-events-date {
  flex-shrink: 0;
  width: 50px; min-width: 50px;
  text-align: center;
  background: rgba(15, 110, 86, 0.18);
  border-radius: 6px;
  padding: 7px 4px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  min-height: 56px;
}
.lux-events-date-day { font-size: 1.2rem; font-weight: 600; color: #08503f; line-height: 1; }
.lux-events-date-mon { font-size: 10px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: #0f6e56; margin-top: 4px; }
.lux-events-date-tba { font-size: 1.05rem; font-weight: 600; color: #08503f; line-height: 1; letter-spacing: 0.04em; }
.lux-events-body { flex: 1; min-width: 0; padding-top: 1px; }
.lux-events-title { font-size: 0.92rem; font-weight: 600; color: #08503f; margin-bottom: 4px; letter-spacing: -0.01em; }
.lux-events-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 4px; }
.lux-events-pill {
  display: inline-block;
  font-size: 0.72rem; font-weight: 500;
  color: #0f6e56;
  background: rgba(15, 110, 86, 0.14);
  border: 1px solid rgba(15, 110, 86, 0.22);
  border-radius: 4px;
  padding: 2px 7px;
}
.lux-events-time { font-size: 0.8rem; font-weight: 500; color: #0a4840; }
.lux-events-loc { display: flex; align-items: flex-start; gap: 5px; margin-bottom: 4px; }
.lux-events-loc-icon { width: 12px; height: 12px; flex-shrink: 0; fill: none; stroke: #0a4840; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; margin-top: 3px; }
.lux-events-loc-text { font-size: 0.8rem; font-weight: 500; color: #0a4840; }
.lux-events-desc { font-size: 0.8rem; line-height: 1.55; color: #156d63; }
.lux-events-desc-row { padding: 1px 0; }
/* "More info" link pill — sits below the description and opens the
   event's provided URL in a new tab. Sage family, matching the
   "Add to calendar" pill so the two read as siblings. */
/* Contact block — organiser details from the sheet's Contact column,
   shown as name + clickable email/phone. Sits below the description,
   above the "More info" pill. */
.lux-events-contact {
  display: flex; align-items: flex-start; gap: 5px;
  margin-top: 6px;
  font-size: 0.8rem; line-height: 1.5; color: #156d63;
}
.lux-events-contact-icon {
  width: 13px; height: 13px; flex-shrink: 0; margin-top: 2px;
  fill: none; stroke: #0a4840; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
.lux-events-contact-bits { display: inline; }
.lux-events-contact-name { font-weight: 600; color: #0a4840; }
.lux-events-contact-link { color: #0f6e56; text-decoration: underline; text-underline-offset: 2px; }
.lux-events-contact-link:hover { color: #0a4840; }
.lux-events-contact-sep { margin: 0 6px; color: #8fb7ad; }
.lux-events--past .lux-events-contact,
.lux-events--past .lux-events-contact-name,
.lux-events--past .lux-events-contact-link { color: var(--ink-mid); }
.lux-events--past .lux-events-contact-icon { stroke: var(--ink-mid); }

.lux-events-actions { margin-top: 7px; }
.lux-events-url {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 0.72rem; font-weight: 600;
  color: var(--tone-sage);
  background: var(--chip-sage);
  border: 1px solid rgba(79, 102, 73, 0.45);
  border-radius: 999px;
  padding: 3px 9px;
  text-decoration: none;
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
  -webkit-tap-highlight-color: transparent;
}
.lux-events-url:hover {
  background: #DEE4D2;
  border-color: rgba(79, 102, 73, 0.65);
  color: #3A4D34;
}
.lux-events-url svg {
  width: 12px; height: 12px;
  stroke: currentColor; fill: none; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.lux-events--past .lux-events-url { color: var(--ink-mid); background: var(--bone); border-color: var(--rule); }
.lux-events-empty { padding: 1.1rem 1.25rem; font-size: 0.85rem; color: #156d63; text-align: center; }
.lux-events-more {
  display: inline-flex; align-items: center; gap: 6px;
  margin-top: 0.85rem;
  font-size: 0.82rem; font-weight: 500;
  color: var(--ink-mid);
  text-decoration: none;
  letter-spacing: -0.005em;
  transition: color 0.15s ease, padding 0.15s ease;
}
.lux-events-more:hover { color: var(--acc); padding-left: 4px; }
/* Past events get a quieter neutral palette */
.lux-events--past { background: var(--canvas); border-color: var(--rule-faint); }
.lux-events--past .lux-events-item { border-bottom-color: var(--rule-faint); }
.lux-events--past .lux-events-date { background: var(--bone-dark); }
.lux-events--past .lux-events-date-day,
.lux-events--past .lux-events-date-mon,
.lux-events--past .lux-events-date-tba { color: var(--ink-mid); }
.lux-events--past .lux-events-title { color: var(--ink); }
.lux-events--past .lux-events-pill { color: var(--ink-mid); background: var(--bone); border-color: var(--rule); }
.lux-events--past .lux-events-time,
.lux-events--past .lux-events-loc-text,
.lux-events--past .lux-events-loc-icon { color: var(--ink-mid); stroke: var(--ink-mid); }
.lux-events--past .lux-events-desc { color: var(--ink-mid); }

/* 22. Missing / Get-in-touch panel — even more washed than the page bg, with
   a faint border to keep it card-like without being heavy. */
.lux-missing {
  background: rgba(245, 240, 232, 0.4);
  border: 1px solid var(--rule-faint);
  border-radius: var(--r-md);
  padding: 1.6rem 1.75rem;
  text-align: center;
}

/* 22b. App card — chip + name + tag at top, description / note in the
   middle, action pills always pinned to the bottom of the card so adding
   prose never pushes them out of place. */
.lux-app {
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  padding: 1.1rem 1.25rem 1.2rem;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}
.lux-app-head {
  display: flex; align-items: center; gap: 12px;
  flex-wrap: wrap;
}
.lux-app-head .lux-chip { width: 36px; height: 36px; }
.lux-app-name {
  font-weight: 600; font-size: 1.05rem;
  letter-spacing: -0.018em; color: var(--ink);
  flex: 1; min-width: 0;
  display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.lux-app-btns {
  display: flex; gap: 6px; flex-wrap: wrap;
  justify-content: flex-end;
  margin-top: auto;
  padding-top: 0.4rem;
}
/* Action pill — true rounded pill, used for iOS/Android downloads, the
   COO Q&A "Read" pill, and "Visit X" portal links at the bottom of cards.
   Warm pale-cream tone, ink text. */
.lux-app-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 13px; border-radius: 999px;
  background: rgba(232, 222, 202, 0.55);
  border: 1px solid rgba(160, 140, 95, 0.22);
  color: var(--ink);
  font-size: 0.74rem; font-weight: 500;
  letter-spacing: 0.04em;
  text-decoration: none;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.lux-app-btn:hover { background: rgba(232, 222, 202, 0.85); border-color: rgba(160, 140, 95, 0.4); color: var(--acc); }
.lux-app-btn svg { width: 12px; height: 12px; flex-shrink: 0; fill: currentColor; stroke: none; }
.lux-app-btn svg path { fill: currentColor; stroke: none; }
/* Outline globe for "Web" pills — overrides the filled-icon defaults above
   so the stroked glyph (circle + equator + meridian) renders cleanly. */
.lux-app-btn svg.lux-globe,
.lux-app-btn svg.lux-globe * { fill: none !important; stroke: currentColor !important; stroke-width: 2; stroke-linecap: round; }
.lux-app-desc { font-size: 0.92rem; color: var(--ink-mid); line-height: 1.6; }
.lux-app-note { font-size: 0.82rem; color: var(--stone); line-height: 1.55; font-style: italic; }
.lux-app-note a { color: var(--acc); text-decoration: underline; text-underline-offset: 2px; }

/* 22c. Feature tiles (homepage-styled, used on /v2/app and elsewhere) */
.lux-feat-grid {
  display: grid; grid-template-columns: 1fr; gap: 8px;
}
@media (min-width: 540px) { .lux-feat-grid { grid-template-columns: 1fr 1fr; gap: 10px; } }
.lux-feat {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 0.85rem 1rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
}
.lux-feat .lux-chip { width: 34px; height: 34px; }
.lux-feat-body { min-width: 0; }
.lux-feat-name { display: block; font-weight: 600; font-size: 0.96rem; color: var(--ink); letter-spacing: -0.015em; line-height: 1.25; }
.lux-feat-desc { display: block; font-size: 0.83rem; color: var(--ink-mid); line-height: 1.55; margin-top: 3px; }

/* 22d. Step list — palette matches the guide subpages
   (bone-soft circle, rule border, terracotta digit) */
.lux-steps { display: flex; flex-direction: column; gap: 1rem; margin-top: 0.5rem; }
.lux-step { display: flex; align-items: flex-start; gap: 14px; }
.lux-step-num {
  flex: 0 0 auto; width: 32px; height: 32px;
  border-radius: 50%;
  background: var(--bone-soft);
  border: 1px solid var(--rule);
  display: flex; align-items: center; justify-content: center;
  font-size: 0.82rem; font-weight: 600; color: var(--acc);
  margin-top: 1px;
}
.lux-step-text { flex: 1; font-size: 0.92rem; color: var(--ink-mid); line-height: 1.6; }
.lux-step-text strong { color: var(--ink); font-weight: 600; }
.lux-step-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px;
  vertical-align: middle;
  color: var(--ink);
}
.lux-step-icon svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }

/* 22e. Segmented OS switcher — animated slider sits behind the active button
   and slides between options. */
.lux-osswitch {
  position: relative;
  display: inline-flex;
  background: var(--bone-soft);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 3px;
  margin-bottom: 1rem;
  isolation: isolate;
}
.lux-osswitch-slider {
  position: absolute; top: 3px; left: 3px;
  height: calc(100% - 6px);
  background: var(--ink);
  border-radius: 999px;
  z-index: 0;
  transform: translate3d(0, 0, 0);
  transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1),
              width 0.25s cubic-bezier(0.4, 0, 0.2, 1);
  pointer-events: none;
  will-change: transform, width;
  -webkit-backface-visibility: hidden;
          backface-visibility: hidden;
}
.lux-osswitch button {
  position: relative; z-index: 1;
  background: transparent; border: 0; cursor: pointer;
  padding: 6px 16px; border-radius: 999px;
  font-size: 0.78rem; font-weight: 500; color: var(--ink-mid);
  font-family: inherit;
  white-space: nowrap;
  transition: color 0.2s ease;
}
.lux-osswitch button.is-active { color: var(--bone); }

/* 22e-bis. Off/On toggle — a two-position variant of the segmented
   OS switcher above. Same animation grammar (sliding dark pill behind
   two buttons). Tuning notes:
     • The slider has NO transition by default. JS adds .is-armed
       after the initial position is laid out, so a toggle that
       starts ON doesn't visibly slide in from the left on page
       load. Subsequent user taps animate normally.
     • The buttons disable text selection and the iOS tap highlight
       so a quick double-tap doesn't paint a blue selection box or
       leave a grey square behind.
     • touch-action: manipulation removes the 300ms tap delay. */
.lux-toggle {
  position: relative;
  display: inline-flex;
  background: var(--bone-soft);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 3px;
  isolation: isolate;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.lux-toggle-slider {
  position: absolute; top: 3px; left: 3px;
  height: calc(100% - 6px);
  background: var(--ink);
  border-radius: 999px;
  z-index: 0;
  transform: translate3d(0, 0, 0);
  transition: none;
  pointer-events: none;
  will-change: transform, width;
  -webkit-backface-visibility: hidden;
          backface-visibility: hidden;
}
.lux-toggle.is-armed .lux-toggle-slider {
  transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1),
              width 0.28s cubic-bezier(0.4, 0, 0.2, 1),
              background 0.22s ease;
}
.lux-toggle.is-on .lux-toggle-slider {
  background: #0BDA51;
}
.lux-toggle button {
  position: relative; z-index: 1;
  background: transparent; border: 0; cursor: pointer;
  padding: 6px 16px; border-radius: 999px;
  font-size: 0.78rem; font-weight: 500; color: var(--ink-mid);
  font-family: inherit;
  white-space: nowrap;
  transition: color 0.2s ease;
  min-width: 48px;
  -webkit-tap-highlight-color: transparent;
  -webkit-user-select: none;
          user-select: none;
  touch-action: manipulation;
  outline: 0;
}
.lux-toggle button:focus { outline: 0; }
.lux-toggle button:focus-visible {
  /* Keyboard-only focus ring – preserves accessibility without
     showing a tap-induced ring on touch. */
  outline: 2px solid var(--acc);
  outline-offset: 2px;
}
.lux-toggle button.is-active { color: var(--bone); }

/* Settings page rows */
.lux-set-list { display: flex; flex-direction: column; gap: 12px; }
.lux-set-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px;
  padding: 1rem 1.1rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
}
.lux-set-row-body { min-width: 0; flex: 1; }
.lux-set-row-name {
  display: block;
  font-weight: 600; font-size: 0.96rem;
  color: var(--ink); letter-spacing: -0.012em;
  line-height: 1.3;
}
.lux-set-row-desc {
  display: block;
  font-size: 0.82rem; color: var(--ink-mid);
  line-height: 1.5;
  margin-top: 4px;
}
.lux-set-row-note {
  display: block;
  font-size: 0.78rem; color: var(--stone);
  line-height: 1.45;
  margin-top: 6px;
  font-style: italic;
}
.lux-set-row-control { flex: 0 0 auto; }
.lux-set-empty {
  padding: 1.4rem 1.5rem;
  background: var(--bone-soft);
  border: 1px dashed var(--rule);
  border-radius: var(--r-md);
  font-size: 0.88rem; color: var(--ink-mid);
  text-align: center;
}

/* 22f. Info / tip callout — solid card with rounded corners and a left-edge
   accent bar that follows the card's curvature smoothly. The accent uses
   the section colour when scoped inside a tinted section, terracotta otherwise. */
.lux-tip {
  position: relative;
  background: var(--bone-soft);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  padding: 0.95rem 1.1rem 0.95rem 1.4rem;
  font-size: 0.9rem; color: var(--ink-mid); line-height: 1.6;
  overflow: hidden;
}
.lux-tip::before {
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: 4px;
  background: var(--section-text, var(--acc));
}
.lux-tip strong { color: var(--ink); font-weight: 600; }
.lux-tip a { color: var(--acc); text-decoration: underline; text-underline-offset: 2px; }
[class*="lux-band--tint-"] .lux-tip {
  background: rgba(255, 255, 255, 0.55);
  border-color: var(--section-rule);
}

/* 23. Footer — dark band, light writing. Same one-line meta on every page. */
.lux-footer {
  margin-top: auto;
  padding: 1.4rem var(--container-pad) calc(1.4rem + env(safe-area-inset-bottom));
  border-top: 0;
  background: var(--noir);
  text-align: center;
  font-size: 0.78rem;
  color: rgba(245, 240, 232, 0.62);
  /* Clip the giant wordmark's overflow so the T/t spill is hidden
     cleanly at the page edges and doesn't introduce horizontal scroll. */
  overflow: hidden;
}
.lux-footer-meta { font-size: 0.78rem; line-height: 1.55; color: rgba(245, 240, 232, 0.62); }
.lux-footer-meta a { color: rgba(245, 240, 232, 0.78); text-decoration: none; }
.lux-footer-meta a:hover { color: var(--bone); }
.lux-footer-meta .sep { margin: 0 0.55rem; opacity: 0.45; }

/* Giant 'The Precinct' wordmark — Marcellus, sat below the meta line.
   Scoped via :has() to the homepage footer (only one with the
   wordmark element inside). The footer gets extra padding-bottom to
   reserve room for the absolutely-positioned wordmark, which sits
   anchored to the footer's bottom with a small overhang so its
   baseline drops past the footer's edge (overflow:hidden clips it).
   The wordmark is centred via left:50%+translateX(-50%), which works
   regardless of the footer's side padding and gives symmetric T/t
   spill past the page edges. */
.lux-footer:has(.lux-footer-wordmark) {
  position: relative;
  /* 32px gap (between meta line and wordmark top) + visible wordmark
     height (= font-size minus the bottom clip overhang). Keep these
     three values in sync if you tune the wordmark: padding-bottom =
     32px + (font-size - bottom_offset). */
  padding-bottom: calc(32px + 13.75vw);
}
.lux-footer-wordmark {
  position: absolute;
  /* Drop bottom 4.25vw past the footer's outer edge so the baseline
     pokes past it and the bottom of each letter gets clipped. */
  bottom: -4.25vw;
  /* Centre on the viewport horizontally, regardless of footer padding. */
  left: 50%;
  transform: translateX(-50%);
  display: block;
  white-space: nowrap;
  font-family: 'Marcellus', serif;
  font-weight: 400;
  font-size: 18vw;
  line-height: 1;
  letter-spacing: -0.01em;
  color: #2c2926;
  margin: 0;
}

/* 24. Stagger fade-in (residents guide) */
@keyframes lux-fade-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
.lux-fade {
  opacity: 0;
  animation: lux-fade-in 0.5s ease-out forwards;
  animation-delay: var(--d, 0s);
}
@media (prefers-reduced-motion: reduce) { .lux-fade { animation: none; opacity: 1; } }

/* 25. Utility */
.lux-flex { display: flex; }
.lux-flex-wrap { flex-wrap: wrap; }
.lux-items-center { align-items: center; }
.lux-justify-between { justify-content: space-between; }
.lux-gap-1 { gap: 0.5rem; }
.lux-gap-2 { gap: 0.85rem; }
.lux-mt-1 { margin-top: 0.85rem; }
.lux-mt-2 { margin-top: 1.4rem; }
.lux-text-center { text-align: center; }

/* ───────────────────────────────────────────────────────────────────
   26. v2-* compatibility layer — maps the older v2-* class system to
   the same visual language as the lux-* system above so legacy pages
   pick up the new aesthetic without a full HTML rewrite.
   ─────────────────────────────────────────────────────────────────── */

/* Nav */
.v2-nav {
  position: sticky; top: 0; z-index: 100;
  background: rgba(245, 243, 239, 0.85);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  border-bottom: 1px solid var(--rule);
  height: var(--nav-h);
}
.v2-nav-inner {
  max-width: var(--container);
  margin: 0 auto; padding: 0 var(--container-pad);
  height: 100%;
  display: flex; align-items: center; justify-content: space-between;
}
.v2-nav-logo {
  font-family: var(--font-italic); font-style: italic;
  font-size: 1.1rem; font-weight: 400;
  color: var(--ink); text-decoration: none; letter-spacing: -0.01em;
}
.v2-nav-logo small {
  font-family: var(--font-sans); font-style: normal;
  font-size: 9.5px; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--stone); margin-left: 6px; vertical-align: middle;
}
.v2-nav-links { display: flex; align-items: center; gap: 8px; }
.v2-nav-link {
  font-size: 0.82rem; font-weight: 500;
  color: var(--ink-mid); text-decoration: none;
  padding: 6px 10px; border-radius: 999px;
  transition: color 0.15s ease, background 0.15s ease;
}
.v2-nav-link:hover { color: var(--ink); background: rgba(0, 0, 0, 0.04); }
.v2-nav-pill {
  background: var(--ink); color: var(--bone);
  padding: 7px 14px; font-weight: 500;
}
.v2-nav-pill:hover { background: var(--acc); color: var(--bone); }

/* Container */
.v2-container { max-width: var(--container); margin: 0 auto; padding: 0 var(--container-pad); }
.v2-container--narrow { max-width: var(--container-narrow); }

/* Hero / band */
.v2-hero {
  padding: clamp(2rem, 5vw, 3.5rem) 0 clamp(1.4rem, 3vw, 2rem);
  background: var(--bone);
}
.v2-hero--bone { background: var(--bone); }
.v2-hero-content { max-width: var(--container-narrow); margin: 0 auto; padding: 0 var(--container-pad); }
.v2-hero-sub {
  font-size: 1.05rem; line-height: 1.55;
  color: var(--ink-mid); margin-top: 0.6rem; max-width: 60ch;
}
.v2-band { padding: clamp(2rem, 5vw, 3rem) 0; }
/* Legacy v2-band variants now share the page canvas (matches lux-band). */
.v2-band--bone  { background: transparent; }
.v2-band--paper { background: transparent; }
.v2-band--soft  { background: transparent; }
.v2-band--sm    { padding: clamp(1.4rem, 4vw, 2.2rem) 0; }

/* Eyebrow + headings — matched to .lux-eye / .lux-h2 used on the home page */
.v2-eyebrow {
  display: inline-block;
  font-size: 10.5px; font-weight: 500; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--stone);
  margin-bottom: 11px;
}
.v2-eyebrow--ondark { color: rgba(245,240,232,0.85); }
.v2-h-md {
  font-family: var(--font-sans); font-weight: 500;
  font-size: var(--fz-h2);
  letter-spacing: -0.02em; line-height: 1.08; color: var(--ink);
  text-wrap: balance;
}
.v2-h-sm {
  font-size: 1.1rem; font-weight: 600;
  letter-spacing: -0.02em; line-height: 1.25; color: var(--ink);
}
.v2-emph { font-family: var(--font-italic); font-style: italic; font-weight: 400; color: var(--acc); font-size: 1.06em; }
.v2-emph--dark { color: var(--ink); }
.v2-prose { font-size: 0.96rem; line-height: 1.65; color: var(--ink-mid); }
.v2-prose p { margin-bottom: 0.85rem; }
.v2-prose p:last-child { margin-bottom: 0; }
.v2-prose strong { color: var(--ink); font-weight: 600; }
.v2-prose a { color: var(--acc); text-decoration: underline; text-underline-offset: 2px; }
.v2-prose-sm { font-size: 0.88rem; line-height: 1.6; color: var(--ink-mid); }

/* Crumbs */
.v2-crumbs {
  display: flex; align-items: center; gap: 6px;
  font-size: 0.78rem; color: var(--stone); margin-bottom: 0.85rem;
}
.v2-crumbs a { color: var(--ink-mid); text-decoration: none; }
.v2-crumbs a:hover { color: var(--acc); }
.v2-crumbs-sep { opacity: 0.5; }

/* Cards */
.v2-card {
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  padding: 1.25rem 1.4rem;
}
.v2-card--bone { background: var(--bone-soft); }
.v2-card-eyebrow {
  display: inline-block;
  font-size: 9.5px; font-weight: 500; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--stone);
  margin-bottom: 4px;
}

/* Buttons */
.v2-btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 9px 16px;
  border-radius: 999px;
  font-size: 0.85rem; font-weight: 500;
  text-decoration: none; cursor: pointer;
  border: 1px solid var(--rule);
  background: var(--paper); color: var(--ink);
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}
.v2-btn:hover { transform: translateY(-1px); }
.v2-btn--accent { background: var(--acc); border-color: var(--acc); color: var(--bone); }
.v2-btn--accent:hover { background: var(--acc-deep); border-color: var(--acc-deep); }
.v2-btn--ink { background: var(--ink); border-color: var(--ink); color: var(--bone); }
.v2-btn--ink:hover { background: #000; }
.v2-btn--ghost { background: transparent; border-color: var(--rule); color: var(--ink); }
.v2-btn--ghost:hover { background: rgba(0,0,0,0.04); }
.v2-btn--small { padding: 6px 12px; font-size: 0.78rem; }

/* Pills */
.v2-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px;
  font-size: 0.74rem; font-weight: 500;
  letter-spacing: 0.02em;
  border-radius: 999px;
  background: rgba(var(--pill-bg-rgb), 0.7);
  border: 1px solid rgba(45, 40, 36, 0.14);
  color: var(--ink);
}
.v2-pill--accent { background: var(--acc); color: var(--bone); border-color: var(--acc); }
.v2-pill--blue { background: #d8e3ee; color: #2a3f5b; border-color: #c0cfde; }

/* Grids */
.v2-grid { display: grid; gap: 14px; grid-template-columns: 1fr; }
.v2-grid--2 { grid-template-columns: 1fr; }
@media (min-width: 720px) { .v2-grid--2 { grid-template-columns: 1fr 1fr; } }

/* List rows */
.v2-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; padding: 1.05rem 0;
  border-bottom: 1px solid var(--rule-faint);
  text-decoration: none; color: inherit;
}
.v2-row:last-child { border-bottom: 0; }
.v2-row-name { font-weight: 600; font-size: 1.02rem; letter-spacing: -0.02em; color: var(--ink); }
.v2-row-desc { font-size: 0.85rem; color: var(--ink-mid); line-height: 1.5; margin-top: 4px; }
.v2-row-arrow { color: var(--stone); flex-shrink: 0; transition: color 0.15s ease, transform 0.15s ease; }
.v2-row:hover .v2-row-arrow { color: var(--acc); transform: translateX(3px); }

/* Accordions */
.v2-acc { border-bottom: 1px solid var(--rule-faint); }
.v2-acc:first-child { border-top: 1px solid var(--rule-faint); }
.v2-acc-head {
  width: 100%;
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 1rem 0;
  background: transparent; border: 0; cursor: pointer;
  text-align: left; color: var(--ink);
  font-family: inherit;
}
.v2-acc-title { font-weight: 600; font-size: 1rem; letter-spacing: -0.015em; flex: 1; }
.v2-acc-tag {
  font-size: 9.5px; font-weight: 500; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--acc);
  padding: 3px 9px; border-radius: 999px;
  background: rgba(184, 92, 30, 0.1);
}
.v2-acc-tag--stone { color: var(--stone); background: rgba(0,0,0,0.04); }
.v2-acc-chev { color: var(--stone); flex-shrink: 0; transition: transform 0.2s ease; }
.v2-acc[open] .v2-acc-chev, .v2-acc.is-open .v2-acc-chev { transform: rotate(90deg); color: var(--acc); }
.v2-acc-body { padding: 0 0 1.25rem; color: var(--ink-mid); line-height: 1.65; font-size: 0.94rem; }
.v2-acc-body p { margin-bottom: 0.7rem; }
.v2-acc-body p:last-child { margin-bottom: 0; }
.v2-acc-body a { color: var(--acc); }

/* App cards */
.v2-app-card {
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  padding: 1.25rem 1.4rem;
}
.v2-app-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 0.5rem; }
.v2-app-name { font-weight: 600; font-size: 1.05rem; letter-spacing: -0.02em; color: var(--ink); }
.v2-app-desc { font-size: 0.9rem; line-height: 1.6; color: var(--ink-mid); margin-bottom: 0.95rem; }
.v2-app-btns { display: flex; gap: 8px; flex-wrap: wrap; }
.v2-app-btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 14px; border-radius: 8px;
  background: var(--ink); color: var(--bone);
  font-size: 0.82rem; font-weight: 500;
  text-decoration: none;
}
.v2-app-btn:hover { background: #000; }
.v2-app-note { font-size: 0.8rem; color: var(--stone); margin-top: 0.6rem; }

/* OS switch (segmented control) */
.v2-osswitch {
  display: inline-flex;
  background: var(--bone-soft);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 3px;
  position: relative;
}
.v2-osswitch button {
  background: transparent; border: 0; cursor: pointer;
  padding: 6px 16px; border-radius: 999px;
  font-size: 0.78rem; font-weight: 500; color: var(--ink-mid);
  font-family: inherit;
}
.v2-osswitch button.is-active, .v2-osswitch button[aria-selected="true"] { background: var(--ink); color: var(--bone); }
.v2-osswitch-slider { display: none; }

/* Events */
.v2-event {
  display: flex; gap: 14px;
  padding: 1.1rem 0;
  border-bottom: 1px solid var(--rule-faint);
}
.v2-event:last-child { border-bottom: 0; }
.v2-event-date {
  flex: 0 0 auto; width: 56px; text-align: center;
  padding: 0.5rem 0; border-radius: var(--r);
  background: var(--bone-soft); border: 1px solid var(--rule);
}
.v2-event-day { font-size: 1.4rem; font-weight: 700; letter-spacing: -0.03em; color: var(--ink); line-height: 1; }
.v2-event-mon { font-size: 9.5px; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; color: var(--stone); margin-top: 4px; }
.v2-event-body { flex: 1; min-width: 0; }
.v2-event-title { font-weight: 600; font-size: 1.02rem; letter-spacing: -0.02em; color: var(--ink); margin-bottom: 4px; }
.v2-event-desc { font-size: 0.88rem; color: var(--ink-mid); line-height: 1.55; }
.v2-event-desc-row { display: flex; align-items: center; gap: 6px; margin-top: 5px; }
.v2-event-loc { font-size: 0.78rem; color: var(--stone); display: inline-flex; align-items: center; gap: 5px; }
.v2-event-loc-icon { width: 12px; height: 12px; flex-shrink: 0; }
.v2-event-meta { font-size: 0.78rem; color: var(--stone); }
.v2-event-pill {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; font-size: 0.7rem; font-weight: 500;
  letter-spacing: 0.04em; border-radius: 999px;
  background: rgba(184, 92, 30, 0.1); color: var(--acc);
}
.v2-event-tba { color: var(--stone); font-style: italic; }
.v2-event-empty { padding: 2rem 0; text-align: center; color: var(--stone); font-size: 0.92rem; }

/* Promo */
.v2-promo-grid { display: grid; grid-template-columns: 1fr; gap: 12px; }
@media (min-width: 720px) { .v2-promo-grid { grid-template-columns: 1fr 1fr; gap: 14px; } }
.v2-promo {
  display: block;
  position: relative;
  aspect-ratio: 4/5;
  background-size: cover; background-position: center;
  border-radius: var(--r-md); overflow: hidden;
  text-decoration: none; color: var(--bone);
  isolation: isolate;
}
.v2-promo::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background: linear-gradient(180deg,
    rgba(0,0,0,0) 0%, rgba(0,0,0,0) 10%,
    rgba(0,0,0,0) 34%,
    rgba(0,0,0,0.56) 66%, rgba(0,0,0,0.78) 100%);
}
.v2-promo-inner {
  position: absolute; left: 18px; right: 18px; bottom: 18px; z-index: 1;
  color: var(--bone);
}
.v2-promo-inner h3 {
  font-family: var(--font-sans); font-weight: 700;
  font-size: 1.5rem; letter-spacing: -0.025em; line-height: 1.1;
  margin: 4px 0 14px;
}
.v2-promo-inner h3 .v2-emph,
.v2-promo-inner h3 .v2-emph--dark { color: var(--bone); }
.v2-promo-cta {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; font-size: 0.78rem; font-weight: 500;
  background: rgba(255,255,255,0.16); backdrop-filter: blur(10px) saturate(160%);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
  border: 1px solid rgba(255,255,255,0.24); border-radius: 999px;
  color: var(--bone);
}

/* Steps */
.v2-steps { display: flex; flex-direction: column; gap: 1rem; }
.v2-step { display: flex; gap: 14px; align-items: flex-start; }
.v2-step-icon, .v2-step-num {
  flex: 0 0 auto; width: 32px; height: 32px;
  border-radius: 50%; background: var(--bone-soft);
  border: 1px solid var(--rule);
  display: flex; align-items: center; justify-content: center;
  font-size: 0.82rem; font-weight: 600; color: var(--acc);
}
.v2-step-text { flex: 1; }
.v2-step-text strong { color: var(--ink); font-weight: 600; }
.v2-step-text p { font-size: 0.92rem; color: var(--ink-mid); line-height: 1.6; margin-top: 3px; }

/* Next step — contact card(s) shown beneath a template as the call to action */
.v2-next { margin-top: 1.75rem; padding-top: 1.5rem; border-top: 1px solid var(--rule); }
.v2-next-eye {
  display: block; font-family: "JetBrains Mono", monospace;
  font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--acc); margin-bottom: 0.9rem;
}
.v2-next-note { font-size: 0.86rem; color: var(--ink-mid); line-height: 1.6; margin-top: 0.9rem; }
.v2-next-note strong { color: var(--ink); font-weight: 600; }

/* Features */
.v2-feat-list { display: grid; grid-template-columns: 1fr; gap: 14px; margin-top: 1rem; }
@media (min-width: 720px) { .v2-feat-list { grid-template-columns: 1fr 1fr; } }
.v2-feat {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 1rem 1.2rem;
  background: var(--paper);
  border: 1px solid var(--rule); border-radius: var(--r-md);
}
.v2-feat-icon {
  flex: 0 0 auto; width: 36px; height: 36px;
  border-radius: 8px; background: rgba(184, 92, 30, 0.1);
  display: flex; align-items: center; justify-content: center;
  color: var(--acc);
}
.v2-feat-icon svg { width: 18px; height: 18px; }
.v2-feat-name { font-weight: 600; font-size: 0.98rem; letter-spacing: -0.015em; color: var(--ink); }
.v2-feat-desc { font-size: 0.86rem; color: var(--ink-mid); line-height: 1.55; margin-top: 3px; }

/* Detail rows (key-value) */
.v2-detail-row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; padding: 0.7rem 0;
  border-bottom: 1px solid var(--rule-faint);
}
.v2-detail-row:last-child { border-bottom: 0; }
.v2-detail-label { font-size: 9.5px; font-weight: 500; letter-spacing: 0.22em; text-transform: uppercase; color: var(--stone); flex: 0 0 auto; }
.v2-detail-value { font-size: 0.94rem; color: var(--ink); text-align: right; flex: 1; min-width: 0; }

/* Price list */
.v2-price-list { border-top: 1px solid var(--rule-faint); }
.v2-price-row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; padding: 0.85rem 0;
  border-bottom: 1px solid var(--rule-faint);
  font-size: 0.94rem; color: var(--ink);
}
.v2-price-row strong { color: var(--ink); font-weight: 600; }

/* Letter / appeal example */
.v2-letter {
  background: var(--paper);
  border: 1px solid var(--rule); border-radius: var(--r-md);
  padding: 1.5rem 1.6rem;
  position: relative;
}
.v2-letter-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; margin-bottom: 0.85rem;
  padding-bottom: 0.7rem; border-bottom: 1px solid var(--rule-faint);
}
.v2-letter-tlabel {
  font-size: 9.5px; font-weight: 500; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--stone);
}
.v2-letter-copy {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px; font-size: 0.76rem; font-weight: 500;
  background: transparent; border: 1px solid var(--rule); border-radius: 999px;
  color: var(--ink-mid); cursor: pointer;
  font-family: inherit;
}
.v2-letter-copy:hover { background: rgba(184, 92, 30, 0.06); color: var(--acc); border-color: var(--acc); }
.v2-letter-subject {
  font-size: 0.9rem; color: var(--ink); line-height: 1.5;
  padding-bottom: 0.85rem; margin-bottom: 0.95rem;
  border-bottom: 1px solid var(--rule-faint);
}
.v2-letter-subhead {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; margin-bottom: 5px;
}
.v2-letter-slabel {
  font-size: 9.5px; font-weight: 500; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--stone);
}
.v2-letter-copy--xs { padding: 3px 9px; font-size: 0.7rem; }
.v2-letter-subject-text { display: block; }
.v2-letter-body { font-size: 0.95rem; line-height: 1.7; color: var(--ink); }
.v2-letter-body p { margin-bottom: 0.7rem; }
.v2-letter-body p:last-child { margin-bottom: 0; }
.v2-letter-ph { background: rgba(184, 92, 30, 0.12); padding: 1px 5px; border-radius: 3px; color: var(--acc); font-weight: 500; }

/* TOC */
.v2-toc {
  background: var(--bone-soft);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  padding: 1.1rem 1.3rem;
}
.v2-toc ol, .v2-toc ul { list-style: none; counter-reset: toc; }
.v2-toc li { counter-increment: toc; padding: 6px 0; font-size: 0.9rem; }
.v2-toc li::before { content: counter(toc, decimal-leading-zero) "  "; color: var(--stone); font-variant-numeric: tabular-nums; font-size: 0.8rem; }
.v2-toc a { color: var(--ink); text-decoration: none; }
.v2-toc a:hover { color: var(--acc); }

/* Section count */
.v2-section-count {
  font-size: 9.5px; font-weight: 500; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--stone);
}

/* Tip callout */
.v2-tip {
  background: rgba(184, 92, 30, 0.06);
  border-left: 3px solid var(--acc);
  border-radius: 0 var(--r) var(--r) 0;
  padding: 0.95rem 1.15rem;
  font-size: 0.92rem; line-height: 1.6; color: var(--ink-mid);
}
.v2-tip strong { color: var(--ink); font-weight: 600; }

/* Missing/empty state — match the SAT 'Something missing' card */
.v2-missing {
  background: var(--bone-soft);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  padding: 1.6rem 1.75rem;
  text-align: center;
  color: var(--ink);
  font-size: 0.92rem;
}

/* Footer (legacy v2-* layer) — same dark single-line treatment as lux-footer */
.v2-footer {
  border-top: 0;
  padding: 1.4rem var(--container-pad) calc(1.4rem + env(safe-area-inset-bottom));
  margin-top: auto;
  background: var(--noir);
  text-align: center;
  font-size: 0.78rem; color: rgba(245, 240, 232, 0.62);
}
.v2-footer-row { display: none; }
.v2-footer a { color: rgba(245, 240, 232, 0.78); text-decoration: none; }
.v2-footer a:hover { color: var(--bone); }
.v2-footer .sep { margin: 0 0.55rem; opacity: 0.45; }

/* Utility */
.v2-flex { display: flex; }
.v2-flex-wrap { flex-wrap: wrap; }
.v2-items-center { align-items: center; }

/* =================================================================
   VIEW TRANSITIONS — opt into Chromium's cross-document view
   transitions for same-origin nav. Browsers without support ignore
   this rule and just navigate normally. We exclude the banner,
   PTR indicator, and toasts/tooltips from the transition by giving
   them their own view-transition-name so they don't fade in/out
   each navigation. */
@view-transition { navigation: auto; }
.lux-conn-banner   { view-transition-name: lux-banner; }
.lux-ptr           { view-transition-name: lux-ptr; }
.lux-conn-toast    { view-transition-name: lux-toast; }
.lux-share-fab     { view-transition-name: lux-share; }
.lux-progress      { view-transition-name: lux-progress; }

/* =================================================================
   CONNECTION UI — banner, dim states, dot + tooltip, toast, PTR
   -----------------------------------------------------------------
   The whole system uses existing tokens (bone, ink, stone, rule)
   and animates only on transform/opacity so it feels native on
   iOS WebKit.
   ================================================================= */

/* ---------- Banner ----------
   Fixed at viewport top with the iOS safe-area inset baked into a
   single explicit height. Body padding-top and the sticky nav's
   `top` use the same value, so banner and nav butt up cleanly with
   no 1px gap or clip. */
:root {
  /* Tall enough for the longest message ("You're offline. Get the app…")
     to sit on two lines on a phone. Body padding + nav top derive from
     this same value, so they follow automatically. */
  --conn-banner-h: 54px;
  --conn-banner-total: calc(var(--conn-banner-h) + env(safe-area-inset-top, 0px));
}
.lux-conn-banner {
  position: fixed; left: 0; right: 0; top: 0;
  z-index: 60;
  box-sizing: border-box;
  height: var(--conn-banner-total);
  padding: env(safe-area-inset-top, 0px) 16px 0;
  display: flex; align-items: center; justify-content: center; gap: 10px;
  font-size: 0.86rem; line-height: 1.25;
  background: var(--bone-dark); color: var(--ink);
  /* No border. The transform-translate above the viewport hides the
     edge entirely when collapsed; no need for a 1px line that can
     misalign with the nav border. */
  transform: translateY(-100%);
  transition: transform 0.34s cubic-bezier(0.4, 0, 0.2, 1), background 0.3s ease, color 0.3s ease;
  text-align: center;
  /* Let long messages wrap onto a second line rather than clip. The
     banner height above leaves room for two lines centred vertically. */
  white-space: normal;
  text-wrap: balance;
  overflow: hidden;
}
.lux-conn-banner.is-visible { transform: translateY(0); }

/* Connecting and back-online states: a washed-out tint of #0BDA51
   with the same dark text colour as the offline banner. The dot is
   the loud signal — it lights up bright green and pulses. */
.lux-conn-banner.is-connecting,
.lux-conn-banner.is-back {
  background: #DCF7E5; /* washed-out #0BDA51 */
  color: var(--ink);
}

.lux-conn-banner-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--stone);
  flex: 0 0 8px;
}
.lux-conn-banner.is-connecting .lux-conn-banner-dot {
  background: #0BDA51;
  box-shadow: 0 0 10px rgba(11, 218, 81, 0.5);
  animation: lux-conn-pulse 0.55s ease-in-out infinite;
}
.lux-conn-banner.is-back .lux-conn-banner-dot {
  background: #0BDA51;
  box-shadow: 0 0 10px rgba(11, 218, 81, 0.45);
  animation: none;
}
@keyframes lux-conn-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.25; } }

.lux-conn-banner-ic {
  width: 16px; height: 16px; flex: 0 0 16px;
  stroke: currentColor; fill: none; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}

/* When the banner is shown, push body and nav by the same exact
   distance — no clipping, no seam. The nav keeps its frosted-glass
   look (don't override the backdrop-filter) so the banner-to-nav
   transition reads as one continuous panel. */
body.is-conn-banner-shown {
  padding-top: var(--conn-banner-total);
  transition: padding-top 0.34s cubic-bezier(0.4, 0, 0.2, 1);
}
body.is-conn-banner-shown .lux-nav {
  top: var(--conn-banner-total);
  transition: top 0.34s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Megamenu drops down from below the nav. When banner is shown the
   nav has shifted, so the menu's anchor must shift too — otherwise
   the top of the menu sits hidden behind the nav. */
body.is-conn-banner-shown .lux-menu {
  top: calc(var(--conn-banner-total) + var(--nav-h));
  height: calc(100vh - var(--conn-banner-total) - var(--nav-h));
}
@media (max-width: 480px) {
  .lux-conn-banner { font-size: 0.82rem; padding-left: 12px; padding-right: 12px; }
}

/* ---------- Dim state: notification-bubble badge + tap tooltip ----------
   The badge is a small red error glyph (filled circle with a centred
   white "!" SVG) that pokes out of the top-right corner like an iOS
   app notification badge. Two implementation notes:

   1. The "!" is rendered as an inline SVG via background-image rather
      than a text glyph. Text glyphs are not horizontally centred at
      their pixel-box centre (the "!" stem sits a touch left of centre
      in most fonts) and centring tricks like flex/text-align are
      affected by font metrics. The SVG is dead-centre by construction.

   2. We deliberately DON'T apply filter:grayscale to the parent here.
      Filter is inherited by descendants including pseudo-elements,
      which made the badge red look different on channel cards
      (parent grayscale 0.45) vs other items (parent grayscale 0.7).
      Opacity alone is enough visual signal that the link is offline.
*/
:root {
  --err:        #DA1E28;
  --err-deep:   #B91C20;
}

/* The actual glyph is encoded as an SVG data URI: a centred bang
   (vertical line + dot) in white, viewBox 0 0 24 24 so the geometric
   centre is x=12. Stroke-width 3.5 gives it weight at small sizes. */

a.lux-needs-online {
  position: relative;
  opacity: 0.6;
  transition: opacity 0.25s ease;
  -webkit-tap-highlight-color: transparent;
}
a.lux-needs-online::after {
  content: '';
  position: absolute;
  top: -5px; right: -5px;
  width: 16px; height: 16px;
  border-radius: 50%;
  background-color: var(--err);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round'><line x1='12' y1='6' x2='12' y2='13'/><circle cx='12' cy='17.5' r='1.4' fill='white' stroke='none'/></svg>");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 70% 70%;
  box-shadow: 0 0 0 2px var(--bone), 0 1px 3px rgba(20, 18, 16, 0.28);
  pointer-events: none;
  z-index: 2;
}

/* Channel and promo cards: hide the card-level badge and surface it
   on the inner action pill instead. */
a.lux-channel.lux-needs-online,
a.lux-promo.lux-needs-online {
  opacity: 0.75;
}
a.lux-channel.lux-needs-online::after,
a.lux-promo.lux-needs-online::after {
  display: none;
}
a.lux-channel.lux-needs-online .lux-pill,
a.lux-promo.lux-needs-online .lux-pill {
  position: relative;
}
a.lux-channel.lux-needs-online .lux-pill::after,
a.lux-promo.lux-needs-online .lux-pill::after {
  content: '';
  position: absolute;
  top: -5px; right: -5px;
  width: 16px; height: 16px;
  border-radius: 50%;
  background-color: var(--err);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round'><line x1='12' y1='6' x2='12' y2='13'/><circle cx='12' cy='17.5' r='1.4' fill='white' stroke='none'/></svg>");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 70% 70%;
  box-shadow: 0 0 0 2px var(--bone), 0 1px 3px rgba(20, 18, 16, 0.28);
  pointer-events: none;
  z-index: 2;
}

/* Newsletter post cards (.lux-news-mag) have overflow:hidden for
   their image animation, which clips a negative-offset badge, AND
   their ::after is already used for the dark gradient overlay. We
   suppress the link-level ::after badge here and put it on ::before
   instead, positioned INSIDE the card so it isn't clipped. */
a.lux-news-mag.lux-needs-online {
  opacity: 0.85;
}
a.lux-news-mag.lux-needs-online::after {
  /* keep the existing gradient — restore by overriding the badge rule */
  content: '';
  background: linear-gradient(180deg,
    rgba(20, 17, 15, 0) 35%,
    rgba(20, 17, 15, 0.55) 75%,
    rgba(20, 17, 15, 0.82) 100%);
  inset: 0;
  top: 0; right: 0;
  width: auto; height: auto;
  border-radius: 0;
  box-shadow: none;
  z-index: 0;
}
a.lux-news-mag.lux-needs-online::before {
  content: '';
  position: absolute;
  top: 12px; right: 12px;
  width: 22px; height: 22px;
  border-radius: 50%;
  background-color: var(--err);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round'><line x1='12' y1='6' x2='12' y2='13'/><circle cx='12' cy='17.5' r='1.4' fill='white' stroke='none'/></svg>");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 70% 70%;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.85), 0 2px 6px rgba(20, 18, 16, 0.35);
  pointer-events: none;
  z-index: 3;
}

/* Megamenu drawer links – we replace the corner badge entirely with
   a small dark-grey pill on the right that says "Needs internet".
   Far more legible than a tiny coloured dot in the corner of a long
   row, and matches how iOS / Android list rows convey "unavailable". */
.lux-menu-link.lux-needs-online,
.lux-menu-sublink.lux-needs-online {
  position: relative;
  padding-right: 9.5rem; /* room for the pill on the right */
}
.lux-menu-link.lux-needs-online::after,
.lux-menu-sublink.lux-needs-online::after {
  content: 'Needs internet';
  position: absolute;
  top: 50%;
  right: 14px;
  transform: translateY(-50%);
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--ink-mid);
  color: var(--bone);
  font-family: var(--font-sans), -apple-system, sans-serif;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.3;
  width: auto; height: auto;
  background-image: none;
  box-shadow: none;
  white-space: nowrap;
  pointer-events: none;
  z-index: 2;
}

/* Non-anchor buttons opting in via [data-needs-online]. */
button.lux-needs-online,
[role="button"].lux-needs-online {
  opacity: 0.55;
  pointer-events: none;
  position: relative;
}

/* ---------- Tap tooltip ----------
   Anchored to the link being tapped. The previous version used
   transform-based positioning (translate(-50%) for centring, plus
   translateY for the gap) which combined with the arrow's own
   transform was a recipe for edge-case bugs. The current version
   uses plain top/left positioning calculated entirely in JS, with
   transform reserved for the scale-in entrance animation only. */
.lux-conn-tooltip {
  position: fixed;
  z-index: 80;
  background: var(--ink); color: var(--bone);
  padding: 7px 11px; border-radius: 8px;
  font-size: 0.8rem; line-height: 1.3; font-weight: 500;
  max-width: 260px;
  pointer-events: none;
  opacity: 0;
  transform: scale(0.96);
  transform-origin: 50% 100%;
  transition: opacity 0.18s ease, transform 0.22s cubic-bezier(0.2, 0.7, 0.3, 1);
  box-shadow: 0 8px 24px rgba(20, 18, 16, 0.22);
}
.lux-conn-tooltip.is-visible {
  opacity: 1;
  transform: scale(1);
}
.lux-conn-tooltip.is-below {
  transform-origin: 50% 0%;
}

/* Arrow: a 12px square rotated 45° with `bottom: -6px` so the top
   half overlaps the tooltip body (same colour, blends seamlessly)
   and the bottom half pokes out as the tip. JS sets --lux-arrow-x
   to the link's centre relative to the tooltip's left edge, so the
   arrow always points at the link even when the body is clamped to
   the viewport. */
.lux-conn-tooltip::after {
  content: '';
  position: absolute;
  left: var(--lux-arrow-x, 50%);
  bottom: -6px;
  width: 12px; height: 12px;
  background: var(--ink);
  transform: translateX(-50%) rotate(45deg);
  border-radius: 2px;
}
/* When the tooltip flips below its anchor, mirror the arrow to the
   top edge so it points UP at the link beneath. */
.lux-conn-tooltip.is-below::after {
  top: -6px;
  bottom: auto;
}

/* ---------- Toasts ----------
   Generic toast component. We use one node per message so multiple
   toasts can stack briefly without fighting each other. */
.lux-conn-toast {
  position: fixed; z-index: 70;
  bottom: calc(20px + env(safe-area-inset-bottom, 0px));
  right: 20px;
  display: flex; align-items: center; gap: 10px;
  padding: 11px 14px;
  background: var(--ink); color: var(--bone);
  border-radius: 10px;
  font-size: 0.86rem; line-height: 1.35;
  box-shadow: 0 6px 24px rgba(20, 18, 16, 0.22);
  opacity: 0; transform: translateY(10px);
  transition: opacity 0.32s ease, transform 0.32s ease;
  pointer-events: none;
  max-width: calc(100vw - 40px);
}
.lux-conn-toast.is-visible { opacity: 1; transform: translateY(0); }
.lux-conn-toast-ic {
  width: 16px; height: 16px; flex: 0 0 16px;
  stroke: currentColor; fill: none; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
@media (max-width: 600px) {
  .lux-conn-toast {
    left: 16px; right: 16px;
    bottom: calc(16px + env(safe-area-inset-bottom, 0px));
    justify-content: center;
  }
}

/* ---------- Pull-to-refresh ----------
   The page itself translates during the pull (body transform). The
   PTR indicator sits on documentElement so it isn't affected by
   the body transform. The indicator is positioned ABOVE where the
   nav and offline banner sit normally (negative top), so as the
   page pulls down it appears in the freshly-revealed white space
   between the viewport edge and the page content — never sitting
   over the nav or banner. The icon parallaxes at ~50% of the page
   rate so it feels grounded under the moving page. */
.lux-ptr {
  position: fixed; left: 0; right: 0;
  /* Sit above the natural top of the page. As body translates down
     by the pull amount, the gap between viewport-top and where the
     page content begins is filled by this indicator. */
  top: calc(env(safe-area-inset-top, 0px) + 14px);
  z-index: 30;
  pointer-events: none;
  display: flex; align-items: flex-start; justify-content: center;
  height: 60px;
  opacity: 0;
}
/* The icon + label sit inside a pill that matches the rest of the
   design system (paper-tone, rounded, soft shadow). Without this
   container the indicator floats on raw white space and looks
   detached from the page – particularly noticeable when the
   offline banner is showing. */
.lux-ptr-inner {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 14px 8px 12px;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 999px;
  box-shadow: 0 6px 18px rgba(20, 18, 16, 0.10),
              0 1px 2px rgba(20, 18, 16, 0.04);
  color: var(--ink-mid);
  transition: color 0.18s ease, background 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
  will-change: transform, color;
}
.lux-ptr-icon {
  width: 16px; height: 16px;
  stroke: currentColor; fill: none; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
  flex: 0 0 16px;
}
.lux-ptr-label {
  font-family: 'Mulish', var(--font-sans), system-ui, sans-serif;
  font-size: 0.78rem; font-weight: 500;
  letter-spacing: 0.01em;
  color: inherit;
  white-space: nowrap;
}
/* When the user pulls past the trigger threshold, the pill flips
   to a filled-ink state so it reads "ready to release". The label
   text content is updated by JS in tandem (Pull → Release → Refreshing). */
.lux-ptr.is-ready .lux-ptr-inner {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--bone);
  box-shadow: 0 8px 22px rgba(20, 18, 16, 0.18),
              0 1px 2px rgba(20, 18, 16, 0.06);
}
.lux-ptr.is-refreshing .lux-ptr-icon {
  animation: lux-ptr-spin 0.7s linear infinite;
}
@keyframes lux-ptr-spin { to { transform: rotate(360deg); } }

/* The page gets translated during the pull. In wrapper mode the
   transform is on .lux-scroll; in fallback mode it's on body. The
   classes (is-ptr-pulling / is-ptr-snapping) live on body in both
   cases, so we target both transform-receivers under those
   classes. */
body.is-ptr-pulling,
body.is-ptr-pulling .lux-scroll { will-change: transform; }
body.is-ptr-snapping,
body.is-ptr-snapping .lux-scroll {
  transition: transform 0.32s cubic-bezier(0.4, 0, 0.2, 1);
}

/* ---------- Share FAB ----------
   Floating action button on guide / contact / resource pages.
   Terracotta on bone — pulls from the existing accent colour so it
   feels like part of the design system, not an injected control. */
.lux-share-fab {
  position: fixed; z-index: 45;
  right: 18px;
  bottom: calc(18px + env(safe-area-inset-bottom, 0px));
  width: 46px; height: 46px;
  border-radius: 50%;
  background: var(--acc);
  color: var(--paper);
  border: none;
  box-shadow: 0 6px 18px rgba(184, 92, 30, 0.32), 0 2px 6px rgba(20, 18, 16, 0.12);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  transform: translateY(8px); opacity: 0;
  transition: opacity 0.3s ease, transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), background 0.2s ease, box-shadow 0.2s ease;
}
.lux-share-fab.is-visible { opacity: 1; transform: translateY(0); }
.lux-share-fab:hover {
  background: var(--acc-deep);
  box-shadow: 0 8px 22px rgba(184, 92, 30, 0.42), 0 2px 6px rgba(20, 18, 16, 0.14);
}
.lux-share-fab:active { transform: translateY(0) scale(0.94); }
.lux-share-fab svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
/* When PTR is active or banner is shown, FAB stays put. No special
   adjustments needed. */

/* ---------- Reading progress bar ----------
   Thin progress strip under the banner/nav for long guide pages. */
.lux-progress {
  position: fixed; left: 0; right: 0;
  top: var(--nav-h);
  height: 2px;
  background: rgba(184, 92, 30, 0.15); /* terracotta-tinted track */
  z-index: 48;
  pointer-events: none;
}
body.is-conn-banner-shown .lux-progress {
  top: calc(var(--conn-banner-total) + var(--nav-h));
}
.lux-progress-bar {
  height: 100%;
  width: 0%;
  background: var(--acc);
  transition: width 0.08s linear;
  transform-origin: left center;
}

/* ---------- Add to calendar pill ----------
   Tinted with the same green family as the connection banner —
   slightly more saturated so it reads as a foreground action
   rather than an ambient state. */
/* Status / calendar pills now flow inline in the .lux-events-headrow
   inside the body, so the item no longer needs to be a positioning
   ancestor for them. Left intentionally non-positioned. */
/* Card header row — sits at the top of the card body. When the
   event has a status pill, the row holds [status][add]. When it
   doesn't, the title takes the left slot and the row holds
   [title flex-1][add]. align-items:flex-start so the Add pill
   stays pinned to the top even when the title wraps to multiple
   lines. */
.lux-events-headrow {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  min-height: 0;
}
.lux-events-headrow:empty { display: none; }
.lux-events-headrow:not(:empty) { margin-bottom: 6px; }
/* The Add pill always shoves itself to the right edge of the row,
   regardless of whether status or title is to its left. */
.lux-events-headrow .lux-events-cal { margin-left: auto; }
/* When the title is sharing the headrow (no status pill case),
   let it grow to fill all the space the Add pill leaves. Wrapping
   keeps the Add pill at the top because of the align-items above. */
.lux-events-headrow .lux-events-title {
  flex: 1 1 auto;
  min-width: 0;
  margin-bottom: 0;
}

/* Status & Add pills share a uniform pill shape so they read as
   the same family. Only the colours differ.
     .lux-events-status--live  → blue, currently happening
     .lux-events-status--soon  → amber, about to wrap up
     .lux-events-cal           → green, "Add to calendar" action */
.lux-events-status,
.lux-events-cal {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
  flex-shrink: 0;
  white-space: nowrap;
  line-height: 1.2;
}
.lux-events-status { pointer-events: none; }
.lux-events-status--live {
  background: rgba(55, 138, 221, 0.20);
  color: #0C447C;
  border: 1px solid rgba(24, 95, 165, 0.50);
}
.lux-events-status--soon {
  background: rgba(239, 159, 39, 0.24);
  color: #7a4708;
  border: 1px solid rgba(186, 117, 23, 0.55);
}

/* Add pill — overrides only colour & interaction state; sizing
   inherits from the shared .lux-events-status, .lux-events-cal
   block above so it reads as the same family. Tinted with the
   sage palette (--tone-sage / --chip-sage) so it sits in the
   same family as the rest of the sage tones on the site rather
   than the punchier emerald it used to be. */
.lux-events-cal {
  background: var(--chip-sage);
  color: var(--tone-sage);
  border: 1px solid rgba(79, 102, 73, 0.45);
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
  -webkit-tap-highlight-color: transparent;
}
.lux-events-cal:hover {
  background: #DEE4D2;
  border-color: rgba(79, 102, 73, 0.65);
  color: #3A4D34;
}
.lux-events-cal svg {
  width: 11px; height: 11px;
  stroke: currentColor; fill: none; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
@media (max-width: 480px) {
  .lux-events-status,
  .lux-events-cal { font-size: 0.58rem; padding: 2px 7px; }
}

/* ---------- Shake-report sheet ----------
   Bottom-centred card prompting the user to email an issue report.
   Triggered by a strong shake gesture; auto-dismisses if not
   actioned. The exclamation icon uses a soft red palette so it
   reads as "alert" without being alarming. */
.lux-shake-sheet {
  position: fixed; z-index: 75;
  left: 50%;
  bottom: calc(20px + env(safe-area-inset-bottom, 0px));
  display: flex; align-items: center; gap: 14px;
  background: var(--paper);
  border: 1px solid var(--rule-soft);
  border-radius: 14px;
  padding: 14px 16px;
  box-shadow: 0 10px 30px rgba(20, 18, 16, 0.18);
  max-width: calc(100vw - 28px);
  opacity: 0;
  transform: translate(-50%, 14px);
  transition: opacity 0.3s ease, transform 0.32s cubic-bezier(0.4, 0, 0.2, 1);
}
.lux-shake-sheet.is-visible {
  opacity: 1;
  transform: translate(-50%, 0);
}
.lux-shake-icon {
  width: 36px; height: 36px; flex-shrink: 0;
  border-radius: 50%;
  background: var(--safety-bg-soft, #F5E6E0);
  color: var(--safety-text, #9A2810);
  display: flex; align-items: center; justify-content: center;
}
.lux-shake-icon svg {
  width: 18px; height: 18px;
  stroke: currentColor; fill: none; stroke-width: 2.4;
  stroke-linecap: round; stroke-linejoin: round;
}
.lux-shake-text {
  font-size: 0.95rem; font-weight: 500;
  color: var(--ink);
}
.lux-shake-action {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 0.78rem; font-weight: 500;
  padding: 7px 14px; border-radius: 999px;
  background: var(--acc); color: var(--paper);
  text-decoration: none;
  transition: background 0.18s ease, transform 0.12s ease;
  white-space: nowrap;
}
.lux-shake-action:hover { background: var(--acc-deep); }
.lux-shake-action:active { transform: scale(0.96); }
.lux-shake-close {
  width: 30px; height: 30px; flex-shrink: 0;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  color: var(--ink-mid);
  background: transparent;
  border: none;
  transition: background 0.18s ease, color 0.18s ease;
}
.lux-shake-close:hover { background: var(--bone); color: var(--ink); }
.lux-shake-close svg {
  width: 14px; height: 14px;
  stroke: currentColor; fill: none; stroke-width: 2.2;
  stroke-linecap: round; stroke-linejoin: round;
}
@media (max-width: 420px) {
  .lux-shake-sheet { gap: 10px; padding: 12px 14px; }
  .lux-shake-text { font-size: 0.88rem; }
  .lux-shake-icon { width: 32px; height: 32px; }
}


/* =================================================================
   ANTHROPIC PALETTE REFRESH — May 2026
   Promotion of the /mockup design to production. All site-wide
   tokens, surface colours, text colours, megamenu and offline banner
   styling, plus the Marcellus display font for the nav logo and
   hero, live in this single block so the previous theme above is
   untouched and easy to revert if needed.
   ================================================================= */

:root {
  /* Palette — Anthropic warm cream + dark ink. */
  --canvas:      #F0EEE6;
  --bone:        #F0EEE6;
  --bone-soft:   #FAF7F0;
  --bone-dark:   #E5E2D8;
  --paper:       #FAF9F5;
  --panel-bg:    #EAE5D8;

  --ink:         #141413;
  --ink-mid:     #2A2826;
  --stone:       #2A2826;

  --rule:        rgba(20, 20, 19, 0.12);
  --rule-soft:   rgba(20, 20, 19, 0.08);
  --rule-faint:  rgba(20, 20, 19, 0.05);

  /* Pill body — neutral cream (was 232,230,228 cool stone, then a
     too-yellow 222,215,197). 222,218,208 is the same warm-cream
     family with the yellow drained out. */
  --pill-bg-rgb: 229, 226, 216;

  /* 0..1 fraction of the nav strip currently overlapping a dark
     section. Read by the color-mix rules below; written each
     animation frame by the adaptive-nav script in theme.js. */
  --nav-tone-darkness: 0;
}

/* Display font — Marcellus for the brand wordmark and the home hero. */
html body .lux-nav-logo,
html body .lux-hero--image h1 {
  /* Marcellus is reserved for the brand wordmark + the homepage
     hero title only. Subpage heroes (.lux-hero without --image)
     stay on the v2 sans (Mulish). */
  font-family: 'Marcellus', Georgia, 'Times New Roman', serif !important;
  font-weight: 400 !important;
  letter-spacing: -0.01em !important;
}
html body .lux-nav-logo { font-size: 1.5rem !important; line-height: 1 !important; font-weight: 400 !important; }
html body .lux-hero--image h1 { font-size: 3rem !important; line-height: 1.04 !important; }

/* Pill / card / panel surfaces in the warm-cream family. */
html body .lux-pill {
  background: #E5E2D8 !important;
  border-color: rgba(20, 20, 19, 0.10) !important;
  color: #141413 !important;
}
html body .lux-pill:hover {
  background: #D8D4C8 !important;
  border-color: rgba(20, 20, 19, 0.18) !important;
}
html body .lux-pill .lux-ic { color: #141413 !important; }

html body .lux-pill--section {
  background: #A09A90 !important;
  border-color: #8A847A !important;
  color: #FAF9F5 !important;
}
html body .lux-pill--section:hover {
  background: #8A847A !important;
  border-color: #6F6A60 !important;
}

html body .lux-card { background: #FAF9F5 !important; border-color: rgba(20,20,19,0.08) !important; }
html body .lux-card--bone { background: #E5E2D8 !important; }
html body .lux-channels-band { background: #F0EEE6 !important; }

/* Body / title / subtitle / eyebrow text → Anthropic ink. The hero h1
   sits over its own image and keeps its own light colour from the v2
   theme above. */
html body,
html body .lux-h1, html body .lux-h2, html body .lux-h3,
html body .lux-prose, html body .lux-prose-sm,
html body .lux-row-desc, html body .lux-row-arrow,
html body .lux-card-eye, html body .lux-eye,
html body .lux-channel-desc, html body .lux-channel-name,
html body .lux-section-eye {
  color: #141413 !important;
}

/* Megamenu text → Anthropic ink. The drawer's translucent cream bg
   is unchanged; just the contents flip colour. */
html body .lux-menu-link,
html body .lux-menu-sublink,
html body .lux-menu-eye,
html body .lux-menu-link-chev { color: #141413 !important; }
html body .lux-menu-link-chev path { stroke: #141413 !important; }

/* Offline / connection banner — Anthropic dark with cream icon + text.
   The connecting and back-online states use the same dark treatment;
   only the dot keeps #0BDA51 to signal connectivity. */
html body .lux-conn-banner,
html body .lux-conn-banner.is-connecting,
html body .lux-conn-banner.is-back {
  background: #141413 !important;
  color: #F0EEE6 !important;
}
html body .lux-conn-banner-ic { stroke: #F0EEE6 !important; }

/* During pull-to-refresh (body.is-ptr-pulling / is-ptr-snapping), the
   body itself gets a transform that drags position:fixed children with
   it on WebKit. Fade the banner out so it doesn't ride down into view. */
body.is-ptr-pulling   .lux-conn-banner,
body.is-ptr-snapping  .lux-conn-banner {
  opacity: 0 !important;
  transition: opacity 0.15s ease !important;
}

/* Adaptive nav text — continuous luminance fade.
   Theme.js writes 0..1 into --nav-tone-darkness based on how much
   of the nav strip is currently sitting on top of a dark section
   (anything tagged data-nav-tone="dark"). The rules below
   color-mix between dark ink and Anthropic ivory using that value
   so the brand mark, settings cog, and hamburger fade smoothly
   instead of snapping at a threshold. */
html body .lux-nav-logo,
html body .lux-nav-cog {
  color: color-mix(in srgb,
                   #F0EEE6 calc(var(--nav-tone-darkness, 0) * 100%),
                   #141413) !important;
  transition: color 0.35s ease;
}
html body .lux-nav-cog svg { stroke: currentColor; }
html body .lux-menu-toggle span {
  background: color-mix(in srgb,
                        #F0EEE6 calc(var(--nav-tone-darkness, 0) * 100%),
                        #141413) !important;
  transition: background 0.35s ease;
}
@supports not (color: color-mix(in srgb, red, blue)) {
  html body .lux-nav-logo,
  html body .lux-nav-cog { color: #141413 !important; transition: color 0.35s ease; }
  html body .lux-menu-toggle span { background: #141413 !important; transition: background 0.35s ease; }
  .lux-nav.is-on-dark .lux-nav-logo,
  .lux-nav.is-on-dark .lux-nav-cog { color: #F0EEE6 !important; }
  .lux-nav.is-on-dark .lux-menu-toggle span { background: #F0EEE6 !important; }
}


/* Hero eyebrow + subtitle on the image-backed hero need to stay light
   (they sit over the photo). The "Resident community" eyebrow in
   particular was reading too dark after the refresh because .lux-eye
   was forced to ink. Restore the light tone for hero context only. */
/* Light hero text only over the IMAGE-backed homepage hero. Subpage
   heroes use plain .lux-hero on cream backgrounds, so they need to
   keep their dark eyebrow + subtitle text. */
html body .lux-hero--image .lux-eye {
  color: #f0ece4 !important;
  opacity: 0.85;
}
html body .lux-hero--image .lux-hero-sub {
  color: #f0ece4 !important;
  opacity: 0.92;
}
/* Subpage heroes — make sure the subtitle stays on the dark Anthropic
   ink rather than inheriting --ink-mid that some other page-level
   override may have dimmed. */
html body .lux-hero:not(.lux-hero--image) .lux-hero-sub,
html body .lux-hero:not(.lux-hero--image) .lux-eye {
  color: #141413 !important;
  opacity: 1;
}


/* Dark-context exemptions — must come AFTER the forced-ink list earlier
   in this refresh block so it wins source-order at equal specificity.
   Anything inside a dark-bg surface keeps its light text colour. */
html body .lux-split-left,
html body .lux-split-left .lux-h2,
html body .lux-split-left .lux-h3,
html body .lux-split-left h2,
html body .lux-split-left h3,
html body .lux-split-left p,
html body .lux-split-left .lux-em,
html body .lux-split-left .lux-prose,
html body .lux-split-left .lux-row-desc,
html body .lux-split-left .lux-row-arrow {
  color: var(--bone) !important;
}
html body .lux-split-left .lux-eye {
  color: rgba(245, 240, 232, 0.65) !important;
}
html body .lux-split-left .lux-prose-sm {
  color: rgba(245, 240, 232, 0.78) !important;
}

/* Pocket CTA + on-dark + promo helpers — same story. */
html body .on-dark,
html body .on-dark .lux-h1, html body .on-dark .lux-h2, html body .on-dark .lux-h3,
html body .on-dark .lux-prose, html body .on-dark .lux-prose-sm,
html body .on-dark .lux-eye,
html body .lux-promo,
html body .lux-promo .lux-h1, html body .lux-promo .lux-h2, html body .lux-promo .lux-h3,
html body .lux-promo .lux-prose, html body .lux-promo .lux-prose-sm,
html body .lux-promo .lux-eye,
html body .lux-promo-h, html body .lux-promo-h .lux-em,
html body .lux-pocket-cta {
  color: var(--bone) !important;
}
html body .lux-pocket .lux-prose-sm,
html body .lux-pocket .lux-eye {
  color: rgba(245, 240, 232, 0.78) !important;
}


/* Glass pills on dark / image cards — restore. The .lux-pill override
   earlier in this refresh forces an opaque cream bg + ink text, which
   was beating the v2 .on-dark/.lux-promo translucent treatment. Re-
   assert the glassy pill here so any pill nested inside an image-bg
   card or a promo band reads as light glass over the photo again. */
html body .on-dark .lux-pill,
html body .lux-promo .lux-pill {
  background: rgba(245, 240, 232, 0.14) !important;
  border-color: rgba(255, 255, 255, 0.20) !important;
  color: var(--bone) !important;
}
html body .on-dark .lux-pill:hover,
html body .lux-promo .lux-pill:hover {
  background: rgba(245, 240, 232, 0.28) !important;
  border-color: rgba(255, 255, 255, 0.36) !important;
}
html body .on-dark .lux-pill .lux-ic,
html body .lux-promo .lux-pill .lux-ic {
  color: var(--bone) !important;
}


/* =================================================================
   PAGE-SCOPED REVERTS — May 2026
   - Newsletter page: pinned to the v2 palette / pill colours, so it
     reads exactly as it did before the Anthropic refresh.
   ================================================================= */

/* ─── Newsletter: full revert to v2 ─── */
body.legacy-refresh-revert {
  --canvas:      #faf9f5;
  --bone:        #f5f3ef;
  --bone-soft:   #F8F4ED;
  --bone-dark:   #eceae5;
  --paper:       #FFFFFF;
  --panel-bg:    #f1efea;
  --ink:         #1a1916;
  --ink-mid:     #4B4742;
  --stone:       #8A847C;
  --rule:        #d4d0ca;
  --rule-soft:   #e2ddd3;
  --rule-faint:  rgba(45, 35, 25, 0.06);
  --pill-bg-rgb: 232, 230, 228;
  background: #faf9f5;
  color: #1a1916;
}
/* Undo the forced-ink rules from the refresh inside this body. */
body.legacy-refresh-revert,
body.legacy-refresh-revert .lux-h1,
body.legacy-refresh-revert .lux-h2,
body.legacy-refresh-revert .lux-h3,
body.legacy-refresh-revert .lux-prose,
body.legacy-refresh-revert .lux-prose-sm,
body.legacy-refresh-revert .lux-row-desc,
body.legacy-refresh-revert .lux-row-arrow,
body.legacy-refresh-revert .lux-card-eye,
body.legacy-refresh-revert .lux-eye,
body.legacy-refresh-revert .lux-channel-desc,
body.legacy-refresh-revert .lux-channel-name,
body.legacy-refresh-revert .lux-section-eye {
  color: var(--ink) !important;
}
/* Pills + sections back to v2. */
body.legacy-refresh-revert .lux-pill {
  background: rgba(232, 230, 228, 0.55) !important;
  border-color: rgba(45, 40, 36, 0.22) !important;
  color: var(--ink) !important;
}
body.legacy-refresh-revert .lux-pill:hover {
  background: rgba(232, 230, 228, 0.80) !important;
  border-color: rgba(45, 40, 36, 0.32) !important;
}
body.legacy-refresh-revert .lux-pill--section {
  background: #9c8e78 !important;
  border-color: #8a7d68 !important;
  color: var(--paper) !important;
}
body.legacy-refresh-revert .lux-pill--section:hover {
  background: #847864 !important;
  border-color: #6f6453 !important;
}
body.legacy-refresh-revert .lux-card        { background: var(--paper) !important; border-color: var(--rule) !important; }
body.legacy-refresh-revert .lux-card--bone  { background: var(--bone-dark) !important; }
body.legacy-refresh-revert .lux-channels-band { background: var(--bone) !important; }
body.legacy-refresh-revert .lux-menu-link,
body.legacy-refresh-revert .lux-menu-sublink,
body.legacy-refresh-revert .lux-menu-eye,
body.legacy-refresh-revert .lux-menu-link-chev { color: var(--ink) !important; }
body.legacy-refresh-revert .lux-menu-link-chev path { stroke: var(--ink) !important; }
/* Restore pill icon colours on this page. */
body.legacy-refresh-revert .lux-pill .lux-ic { color: var(--acc) !important; }
/* Connection banner back to v2 cream. */
body.legacy-refresh-revert .lux-conn-banner,
body.legacy-refresh-revert .lux-conn-banner.is-connecting,
body.legacy-refresh-revert .lux-conn-banner.is-back {
  background: var(--bone-dark) !important;
  color: var(--ink) !important;
}
body.legacy-refresh-revert .lux-conn-banner-ic { stroke: var(--ink) !important; }
/* Nav text back to ink — disable the color-mix fade on this page. */
body.legacy-refresh-revert .lux-nav-logo,
body.legacy-refresh-revert .lux-nav-cog { color: var(--ink) !important; }
body.legacy-refresh-revert .lux-menu-toggle span { background: var(--ink) !important; }

/* ─── Safety guide h2: keep the standard .lux-h2 treatment ─── */
/* Previously the safety page's h2 subtitles were stripped down to a
   small label. They now use the full .lux-h2 size + weight to match
   other pages (resident guide, utility tracking, lighting, etc.).
   Only the .lux-em colour override is kept so the emphasis token
   picks up the safety-text colour instead of the global accent. */
html body.safety-page .lux-h2 .lux-em {
  color: var(--safety-text) !important;
}


/* ─── Nav anchoring + frozen-body scroll architecture ─────────
   The nav is position:fixed at top:0. To stop iOS Safari from
   jittering the nav on URL-bar transitions and dragging it with
   overscroll bounces, body itself does not scroll – instead all
   page content lives inside a .lux-scroll wrapper that handles
   scrolling. Because the body never scrolls, iOS never triggers
   URL-bar transitions, and position:fixed elements (the nav, the
   offline banner, the PTR pill, the share FAB) stay rock-solid.

   The wrapper is created at runtime by setupScrollWrapper() in
   theme.js. The body.has-scroll-wrapper class is added once the
   wrapper exists; until then (or if JS fails) the page falls
   back to normal body scroll using the same padding values.

   Anything that needs to remain fixed lives outside .lux-scroll
   – the bootstrap leaves .lux-nav, .lux-conn-banner, .lux-ptr,
   .lux-menu, etc. as direct children of body. */

html body .lux-nav {
  position: fixed !important;
  top: 0; left: 0; right: 0;
}

/* Fallback (no wrapper – JS not run yet, or disabled): body
   scrolls and pads the top to clear the fixed nav. */
html body { padding-top: var(--nav-h); }
body.is-conn-banner-shown {
  padding-top: calc(var(--nav-h) + var(--conn-banner-total)) !important;
}

/* Wrapper case: body is frozen (overflow hidden, viewport-sized).
   The wrapper inside it does the scrolling and carries the
   nav-clearance padding. */
html, body { height: 100%; }
body.has-scroll-wrapper {
  overflow: hidden !important;
  /* No top padding – the wrapper's padding-top handles nav
     clearance, and is-conn-banner-shown's body padding rule
     above is forced to 0 here too. */
  padding-top: 0 !important;
  /* Lock the body's transform context so PTR can transform the
     wrapper without dragging the nav along. (Body has no
     transform of its own in the wrapper architecture.) */
  position: relative;
}
body.has-scroll-wrapper.is-conn-banner-shown {
  padding-top: 0 !important;
}

.lux-scroll {
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  /* Clear the fixed nav. The offline-banner case adds the
     banner's height + safe-area inset on top. */
  padding-top: var(--nav-h);
  /* Stop scroll from chaining out to the (frozen) body and
     causing iOS to re-engage URL-bar transitions. */
  overscroll-behavior: contain;
  /* Anchor scroll position when content above the viewport
     changes height – stops layout shift on dynamic content
     (events list, etc.). */
  overflow-anchor: auto;
}
body.is-conn-banner-shown .lux-scroll {
  padding-top: calc(var(--nav-h) + var(--conn-banner-total));
}

/* When the menu is open, lock the wrapper instead of the body. */
body.has-scroll-wrapper.is-menu-open .lux-scroll {
  overflow: hidden;
}


/* Html backdrop colour — visible only in iOS Safari's overscroll
   zones and behind the bottom URL bar (body covers it everywhere
   inside the visible page area thanks to min-height: 100dvh and an
   opaque --canvas background). Set to --noir so the strip behind
   the URL bar reads as one continuous colour with the footer.
   Side effect: top pull-to-refresh now exposes noir instead of
   cream — the PTR pill is light, so the contrast is fine. */
html { background: var(--noir); }


/* =================================================================
   VISUAL EXPLAINERS — timeline + flow diagram components
   -----------------------------------------------------------------
   Generic, tint-aware (they read --section-rule/--section-text set
   by the lux-band--tint-* wrappers). Used on AGMs-explained
   (timeline) and the install/utility pages (flow), reusable
   anywhere.
   ================================================================= */

/* Vertical timeline — numbered nodes on a hairline spine. */
.lux-tl { position: relative; margin: 1.3rem 0 0.4rem; padding: 0; list-style: none; }
.lux-tl::before {
  content: '';
  position: absolute; left: 17px; top: 16px; bottom: 16px;
  width: 1px; background: var(--section-rule, var(--rule));
}
.lux-tl li { position: relative; display: flex; gap: 0.95rem; padding: 0.65rem 0; }
.lux-tl-node {
  position: relative; z-index: 1;
  width: 35px; height: 35px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--paper);
  border: 1px solid var(--section-rule, var(--rule));
  font-family: var(--font-mono);
  font-size: 0.78rem; font-weight: 600;
  color: var(--section-text, var(--ink-mid));
}
.lux-tl-meta {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.64rem; font-weight: 500;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--section-text, var(--stone));
  margin-bottom: 3px;
}
.lux-tl-title { font-weight: 600; font-size: 0.95rem; color: var(--ink); letter-spacing: -0.01em; }
.lux-tl-desc { font-size: 0.88rem; color: var(--ink-mid); line-height: 1.55; margin-top: 2px; }

/* Step-flow — same spine, used for "how to" walkthroughs (PWA
   install pages). Bigger gap, supports a small illustration row. */
.lux-flow { position: relative; margin: 1.2rem 0 0; padding: 0; list-style: none; }
.lux-flow::before {
  content: '';
  position: absolute; left: 17px; top: 18px; bottom: 18px;
  width: 1px; background: var(--rule-soft);
}
.lux-flow li { position: relative; display: flex; gap: 0.95rem; padding: 0.8rem 0; }
.lux-flow .lux-tl-node { background: var(--bone-soft); }
.lux-flow-vis {
  margin-top: 0.55rem;
  border: 1px solid var(--rule-soft);
  border-radius: var(--r-md);
  background: var(--paper);
  padding: 0.6rem 0.8rem;
  display: flex; align-items: center; gap: 0.6rem;
  font-size: 0.8rem; color: var(--ink-mid);
}
.lux-flow-vis .lux-ic { width: 16px; height: 16px; color: var(--tone-slate); }

/* Inline UI glyphs inside install steps — show the actual icon the
   user is being told to tap (iOS share, add-to-home, ⋮ menu). */
.lux-step-glyph {
  display: inline-block;
  width: 15px; height: 15px;
  vertical-align: -2.5px;
  margin: 0 1px 0 3px;
  stroke: currentColor; fill: none;
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}
.lux-step-glyph--fill { fill: currentColor; stroke: none; }


/* =================================================================
   HOME RESTRUCTURE — quick actions, band tints, event clamp
   ================================================================= */

/* Quick actions — four compact tiles directly under the hero for the
   things residents actually open the site to do. */
.lux-qa-band { padding: 1rem 0 0.1rem; }
.lux-qa { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.55rem; }
.lux-qa a {
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  text-decoration: none; text-align: center;
  padding: 0.85rem 0.25rem 0.75rem;
  background: var(--paper);
  border: 1px solid var(--rule-soft);
  border-radius: var(--r-lg);
  box-shadow: 0 1px 2px rgba(45, 40, 36, 0.04);
}
.lux-qa-label {
  font-size: 0.68rem; font-weight: 600; letter-spacing: 0.01em;
  color: var(--ink-mid); line-height: 1.15;
}
@media (min-width: 720px) {
  .lux-qa { gap: 0.8rem; }
  .lux-qa a { padding: 1.1rem 0.5rem 1rem; }
  .lux-qa-label { font-size: 0.78rem; }
}

/* Home band tints — gentle section colour (borrowed from the
   residents-guide palette) to break the cream-card monotony. */
.lux-band--home-parchment {
  background: var(--tint-parchment);
  --section-rule: var(--tint-parchment-rule);
  --section-text: var(--tint-parchment-text);
  --section-soft: var(--tint-parchment);
}
.lux-band--home-aqua {
  background: var(--tint-aqua);
  --section-rule: var(--tint-aqua-rule);
  --section-text: var(--tint-aqua-text);
  --section-soft: var(--tint-aqua);
}

/* Home: event descriptions display in full — no line clamp, so
   multi-line text is never truncated with an ellipsis. */


/* =================================================================
   MOTION PASS — scroll reveals, tap states, hero depth
   -----------------------------------------------------------------
   .lux-rv is added by JS (luxReveal in theme.js) only to elements
   below the fold at init, so no-JS and reduced-motion users never
   see hidden content. JS removes the class once the reveal has
   finished, returning the element to its natural styles (so later
   transforms — tap scaling etc. — aren't fighting a stale
   transition-delay).
   ================================================================= */

/* Scroll reveal — settle up + fade. --rv-d is the per-element
   stagger delay set by JS (0 / 70 / 140 / 210ms within a batch). */
.lux-rv {
  opacity: 0;
  transform: translateY(14px);
  transition:
    opacity 0.55s cubic-bezier(0.22, 0.61, 0.36, 1),
    transform 0.6s cubic-bezier(0.22, 0.61, 0.36, 1);
  transition-delay: var(--rv-d, 0s);
}
.lux-rv.is-in {
  opacity: 1;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  .lux-rv { opacity: 1; transform: none; transition: none; }
}

/* Tap press state — coarse pointers only. .lux-tap is added by JS
   to card-level links (rows, channels, promos, app buttons). The
   slow ease-out on release makes the card feel like it springs
   back rather than snapping. */
@media (hover: none) and (pointer: coarse) {
  .lux-tap {
    transition: transform 0.28s cubic-bezier(0.2, 0.7, 0.3, 1);
  }
  .lux-tap:active {
    transform: scale(0.982);
    transition-duration: 0.09s;
  }
}

/* Springy pill press — all pointer types.
   Two layers work together:
   1. :active gives an immediate scale-down while the finger/mouse is
      held (covers slow presses and hovers).
   2. .is-springing (added by JS on pointerdown) plays a full
      down → overshoot → settle keyframe. Because it fires on
      pointerdown — before a link's navigation on release — the
      spring is actually felt even on pills that change the page,
      which plain :active can't deliver.
   transform-origin centre keeps inline pills from drifting. */
.lux-pill,
.lux-app-btn,
.lux-pocket-cta,
.lux-pocket-dismiss,
.lux-toc a {
  transform-origin: center;
  transition: transform 0.34s cubic-bezier(0.34, 1.56, 0.64, 1),
              background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.lux-pill:active,
.lux-app-btn:active,
.lux-pocket-cta:active,
.lux-pocket-dismiss:active,
.lux-toc a:active {
  transform: scale(0.93);
  transition-duration: 0.05s;
}
@keyframes lux-press-spring {
  0%   { transform: scale(1); }
  28%  { transform: scale(0.91); }
  60%  { transform: scale(1.035); }
  100% { transform: scale(1); }
}
.lux-pill.is-springing,
.lux-app-btn.is-springing,
.lux-pocket-cta.is-springing,
.lux-pocket-dismiss.is-springing,
.lux-toc a.is-springing {
  animation: lux-press-spring 0.4s cubic-bezier(0.34, 1.4, 0.5, 1);
}
@media (prefers-reduced-motion: reduce) {
  .lux-pill, .lux-app-btn, .lux-pocket-cta, .lux-pocket-dismiss, .lux-toc a {
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
  }
  .lux-pill:active, .lux-app-btn:active, .lux-pocket-cta:active,
  .lux-pocket-dismiss:active, .lux-toc a:active { transform: none; }
  .lux-pill.is-springing, .lux-app-btn.is-springing, .lux-pocket-cta.is-springing,
  .lux-pocket-dismiss.is-springing, .lux-toc a.is-springing { animation: none; }
}

/* Hero depth — slow Ken Burns drift on the hero photo. Uses the
   standalone `scale` property so it never collides with the
   parallax translate that JS writes to `transform`. */
@keyframes lux-kenburns {
  from { scale: 1; }
  to   { scale: 1.07; }
}
.lux-hero--image .lux-hero-bg {
  animation: lux-kenburns 26s ease-in-out infinite alternate;
  transform-origin: 60% 30%;
  will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
  .lux-hero--image .lux-hero-bg { animation: none; }
}

/* Day/night toggle — was an invisible 50px strip across the top of
   the hero; now a small frosted button in the hero's top-right so
   the nicest detail on the site is actually discoverable. */
.lux-hero-toggle {
  top: 14px; left: auto; right: 14px; bottom: auto;
  width: 38px; height: 38px;
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(20, 16, 12, 0.32);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
          backdrop-filter: blur(10px) saturate(160%);
  border: 1px solid rgba(240, 236, 228, 0.28);
  color: rgba(240, 236, 228, 0.92);
  transition: background 0.2s ease, transform 0.25s cubic-bezier(0.2, 0.7, 0.3, 1);
}
.lux-hero-toggle:active { transform: scale(0.92); }
.lux-hero-toggle .lux-ic { width: 17px; height: 17px; stroke-width: 1.5; }
/* Show the icon for the mode you'd switch TO. */
.lux-hero-toggle .i-sun { display: none; }
.lux-hero-toggle .i-moon { display: block; }
.lux-hero--image.is-night .lux-hero-toggle .i-sun { display: block; }
.lux-hero--image.is-night .lux-hero-toggle .i-moon { display: none; }
