/* ==========================================================================
   Sanctuary v2, page-scoped styles: about.html. Loads AFTER styles.css and
   only extends it; the locked foundation is never overridden destructively.
   Every value traces to design/brands/sanctuary.md (the kit) or to a locked
   value already in styles.css. Inner pages are CALM: static world-light,
   no world flips, no pinned stacks (kit: the signature is home only).
   House rule: no em or en dashes anywhere in this file.
   ========================================================================== */

/* ---- Page hero: calm centered stack (system vocabulary from the home hero) ---- */
.page-hero {
  padding: 96px 48px 64px;   /* kit: section pads {76, 96, 128}; page gutter 48 (locked styles.css) */
  text-align: center;
}
.page-eyebrow {
  font-size: 24px;           /* locked system: hero eyebrow 24px (styles.css .hero-eyebrow) */
  font-weight: 400;
  opacity: .82;              /* locked system: eyebrow sits quieter than the h1 */
}
.page-h1 {
  font-size: 80px;           /* kit: hero h1 80px (ref typeScale) */
  line-height: 1.1;          /* kit: ref h1 88px at 80 = 1.1 */
  letter-spacing: -2px;      /* kit: ref h1 letter-spacing -2px */
  font-weight: 400;          /* kit: hierarchy by SIZE at weight 400 */
  max-width: 1000px;         /* derived: holds the tagline to two lines, inside the ref 1344 content box */
  margin: 20px auto 0;
}
.page-lead {
  max-width: 760px;          /* derived: calm lead measure inside the ref 1344 content box */
  margin: 32px auto 0;       /* kit: spacing base 16, two steps */
  font-size: 20px;           /* derived: one step over body 16 (locked sheet-row 20 is the same step) */
  line-height: 1.6;
}

/* ---- Fact chips: locked .chip vocabulary, real facts only ---- */
.fact-band {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;                 /* locked system: nav-right gap 12 (styles.css) */
  padding: 48px 48px 76px;   /* kit: page gutter 48; section pad 76; 48 top so the pills breathe under the hero (2026-07-12) */
}

/* ---- Backing statement: quiet centered band (home disclosure vocabulary) ---- */
.backing {
  padding: 76px 48px;        /* kit: section pad 76 */
  display: flex;
  justify-content: center;
}
.backing p {
  max-width: 900px;          /* derived: ref measured line length ~1060 max; kept narrower for calm */
  text-align: center;
  font-size: 26px;           /* locked system: card caption scale 26 (styles.css .card-cap) */
  line-height: 1.4;          /* derived: caption leading step (locked .card-cap 1.3, opened slightly for a full band) */
}

/* ---- Shared section frame ---- */
.vm, .values, .team {
  padding: 76px 48px 0;      /* kit: section pad 76; page gutter 48 */
}
.vm .display, .values .display, .team .display {
  margin-bottom: 48px;       /* kit: footer card pad 48 reused as the head-to-grid step */
}

/* ---- Vision and mission cards ---- */
.vm-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 32px;                 /* locked system: card gap 32 (styles.css .track) */
  max-width: 1344px;         /* kit: ref widest content box 1344 */
  margin: 0 auto;
}
.vm-card {
  border-radius: 32px;       /* kit: cards flat filled, radius 32, border NONE, shadow NONE */
  padding: 48px;             /* locked system: footer card pad 48 */
  display: flex;
  flex-direction: column;
  gap: 24px;                 /* kit: radius scale member 24 reused as the label-to-text step */
  min-height: 300px;         /* derived: holds the two cards level, about half a ref card height 571 */
}
.vm-label {
  font-size: 16px;           /* kit: body 16 */
  color: var(--muted-ink);   /* locked system: muted labels (styles.css .col-head) */
}
.vm-text {
  font-size: 32px;           /* locked system: mobile display step 32 reused as card display type */
  line-height: 1.3;          /* locked system: caption leading (styles.css .card-cap) */
  letter-spacing: -0.8px;    /* locked system: mobile display tracking (styles.css) */
  max-width: 520px;          /* derived: keeps the statement to a calm measure inside the card */
}

/* ---- Values grid ---- */
.values-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 32px;                 /* locked system: card gap 32 */
  max-width: 1344px;         /* kit: ref widest content box 1344 */
  margin: 0 auto;
}
.value-card {
  border-radius: 32px;       /* kit: card radius 32, no border, no shadow */
  padding: 40px 32px;        /* derived: card caption pad 32 (locked .card-cap), opened at the top */
  display: flex;
  flex-direction: column;
  gap: 16px;                 /* kit: spacing base 16 */
}
.value-card h3 {
  font-size: 24px;           /* locked system: eyebrow scale 24 reused as card head; weight stays 400 */
  font-weight: 400;
  letter-spacing: -0.5px;    /* derived: light display tracking at the 24 step */
}
.value-card p {
  font-size: 16px;           /* kit: body 16 */
  line-height: 1.5;          /* locked system: body leading (styles.css body) */
}

/* ---- Management team: real headshots on pastel cards ---- */
.team-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 32px;                 /* locked system: card gap 32 */
  max-width: 1344px;         /* kit: ref widest content box 1344 */
  margin: 0 auto;
}
.team-card {
  border-radius: 32px;       /* kit: card radius 32, no border, no shadow */
  padding: 32px;             /* locked system: card pad 32 (styles.css .card-cap) */
  display: flex;
  flex-direction: column;
}
.team-photo {
  display: block;
  width: 100%;
  height: auto;              /* release the width/height attribute hint so aspect-ratio governs the box */
  aspect-ratio: 4 / 5;       /* one uniform portrait crop across the six real seated headshots */
  object-fit: cover;
  object-position: 50% 22%;  /* holds the face high; every source is a centered seated desk portrait */
  border-radius: 24px;       /* kit: radius scale member 24 as the inner radius inside the 32 card */
  background: var(--surface); /* soft cream placeholder while the lazy image loads, no flash */
  margin-bottom: 24px;       /* kit: radius scale member 24 as the photo-to-name step */
}
.team-name {
  font-size: 20px;           /* locked system: sheet-row scale 20 */
}
.team-title {
  font-size: 16px;           /* kit: body 16 */
  color: var(--muted-ink);   /* locked system: muted labels */
  margin-top: 4px;           /* kit: radius scale member 4 as the tightest step */
}
.governance {
  max-width: 780px;          /* derived: calm closing measure, narrower than the grid */
  margin: 64px auto 0;       /* derived: grid-to-line step, two 32 gaps */
  text-align: center;
  font-size: 16px;           /* kit: body 16 */
  line-height: 1.75;         /* locked system: disclosure leading (styles.css .disclosure p) */
}

/* ---- Closing CTA: calm centered stack, primary red pill ---- */
.page-cta {
  padding: 128px 48px;       /* kit: section pad 128 */
  text-align: center;
}
.page-cta .display { margin-bottom: 48px; } /* kit: head-to-action step 48 */
.pill-red {
  background: var(--accent-cta); /* kit: primary pill = accent-cta with white text, 5.86:1 AA */
  color: #FFFFFF;
}
.pill-red:hover {
  background: #AE1217;       /* kit: accent-cta hover state */
  opacity: 1;
}

/* ---- Mobile (locked breakpoint 820; kit: mobile gutter 20, h1 28) ---- */
@media (max-width: 1100px) {
  .values-grid, .team-grid { grid-template-columns: repeat(2, 1fr); } /* derived: two-up before the single column, keeps cards wide enough */
}
@media (max-width: 820px) {
  .page-hero { padding: 56px 20px 40px; } /* kit: mobile gutter 20 (locked mobile pattern) */
  .page-eyebrow { font-size: 16px; }      /* locked system: mobile eyebrow 16 */
  .page-h1 {
    font-size: 28px;         /* kit: mobile h1 28px */
    letter-spacing: -0.7px;  /* locked system: mobile h1 tracking fingerprint, rounded */
  }
  .page-lead { font-size: 16px; margin-top: 20px; } /* kit: body 16 */
  .fact-band { padding: 28px 20px 48px; }
  .backing { padding: 48px 20px; }
  .backing p { font-size: 20px; }         /* locked system: sheet-row scale 20 */
  .vm, .values, .team { padding: 48px 20px 0; }
  .vm .display, .values .display, .team .display { margin-bottom: 32px; }
  .vm-grid, .values-grid, .team-grid { grid-template-columns: 1fr; gap: 16px; } /* kit: spacing base 16 on mobile */
  .vm-card { padding: 32px 24px; min-height: 0; }
  .vm-text { font-size: 24px; }           /* locked system: eyebrow scale 24 */
  .team-photo { margin-bottom: 20px; } /* kit: tighter photo-to-name step for single-column full-width headshots */
  .governance { margin-top: 48px; }
  .page-cta { padding: 76px 20px; }       /* kit: section pad 76 on mobile */
  .page-cta .display { margin-bottom: 32px; }
}

/* ==========================================================================
   Inner-page revamp (2026-07-11, Thomas verdict: inner pages alive, facts real).
   Catalog components re-tokened to the kit; every effect is JS-gated
   progressive enhancement, so no JS and reduced motion keep the calm page.
   ========================================================================== */

/* ---- catalog 016 AnimatedNumber: numeral slots (JS locks min-width pre-count, no chip jitter) ---- */
/* Round-30b: NOTHING here may change width at ANY point in the roll. Locking a
   minimum and releasing it on settle (Round-30) moved the problem rather than
   solving it: the chips sit in a centre-justified row, so the release re-flowed
   every chip at once. The JS now locks the slot to the FINAL value's own
   natural width, subpixel, and no tabular figures are used at any point, so no
   digit ever sits in a widest-digit slot. A value passing through that is wider
   than the final one simply overflows into the chip's 20px padding.
   Alignment carries the rest: a number that ENDS its label overflows rightward
   into that padding; a number that LEADS its label is right-aligned, so the
   units digit and every glyph after it hold still while the tens digit lands. */
.count {
  display: inline-block;
  white-space: nowrap;
  text-align: right;              /* number LEADS its label ("14+ years"): the units digit and
                                     every glyph after it hold still while the tens digit lands */
}
.count[data-count-tail] {
  text-align: left;               /* number ENDS its label ("Trading since 2011"): pinned after the
                                     words, wider values overflow into the chip's 20px padding.
                                     Marked in the markup because :last-child cannot tell these
                                     apart: each .count is its span's only ELEMENT child. */
}

/* ---- Staggered scroll reveals (JS adds .pre-reveal only to elements still below the fold;
        no-JS never hides anything, and the whole effect lives behind no-preference) ---- */
@media (prefers-reduced-motion: no-preference) {
  .pre-reveal {
    opacity: 0;
    transform: translateY(26px);   /* derived: one step over the 16 base, calm rise */
  }
  .pre-reveal.is-in {
    opacity: 1;
    transform: none;
    transition: opacity .65s var(--ease-house), transform .65s var(--ease-house); /* kit: primary house curve */
  }
}

/* ---- catalog 007 Card Stack: the values deck (JS adds .deck; the grid above is the fallback) ---- */
.values-grid.deck {
  display: block;
  position: relative;
  max-width: 720px;          /* derived: one calm card measure inside the 1344 box */
  height: 400px;             /* derived: holds the longest value statement with air */
  margin: 40px auto 0;       /* derived: headroom for the -32px lift of depth-2 cards */
  touch-action: pan-y;       /* engineering: horizontal drag never steals vertical scroll */
}
.deck .value-card {
  position: absolute;
  inset: 0;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 48px 56px;        /* locked system: footer card pad 48, opened sideways */
  gap: 20px;
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
  will-change: transform;
  /* catalog 007 spring {stiffness 170, damping 26} maps to the house curve at .5s */
  transition: transform .5s var(--ease-house), opacity .35s ease, filter .35s ease;
}
.deck .value-card.dragging { cursor: grabbing; transition: none; }
.deck .value-card h3 {
  font-size: 32px;           /* locked system: mobile display step 32 as deck display type */
  letter-spacing: -0.8px;
}
.deck .value-card p {
  font-size: 18px;           /* derived: one half-step over body 16 for the stage */
  line-height: 1.6;
  max-width: 540px;
}
.deck-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 24px;                 /* kit: radius scale member 24 as the control step */
  margin-top: 40px;
}
.deck-dots { display: flex; gap: 8px; }
.deck-dots span {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--line);   /* kit: secondary fill */
  transition: background-color .3s ease, transform .3s ease;
}
.deck-dots span.on {
  background: var(--accent-cta); /* kit: primary accent-cta marks the live card */
  transform: scale(1.3);
}
.deck-hint {
  text-align: center;
  font-size: 14px;           /* locked system: legal-row scale 14 */
  color: var(--muted-ink);
  margin-top: 16px;          /* kit: spacing base 16 */
}

/* ---- catalog 011 Tilt Card: gentle tilt + cream sheen on the monogram tiles (JS drives the vars) ---- */
.team-card {
  position: relative;
  overflow: hidden;          /* the sheen respects the 32px card radius */
}
.team-card::after {
  /* catalog glare re-toned: cream sheen, never a shadow (kit: cards carry no shadow) */
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 32px;
  background: radial-gradient(circle at var(--glx, 50%) var(--gly, 50%), rgba(255, 255, 255, .40) 0%, rgba(255, 255, 255, 0) 70%);
  opacity: 0;
  transition: opacity .2s ease-out; /* catalog: easeOut .2s */
  pointer-events: none;
}
.team-card.tilting::after { opacity: 1; }

/* ---- catalog 013 Icon Slide In: pill CTA, arrow slides in + fill bubble blooms (pure CSS) ---- */
.pill-slide {
  position: relative;
  overflow: hidden;
}
.pill-slide .pill-label {
  position: relative;
  z-index: 2;
  transition: transform .5s cubic-bezier(.34, 1.08, .64, 1); /* catalog spring {bounce .1, .5s} */
}
.pill-slide .pill-arrow {
  position: absolute;
  z-index: 2;
  top: 50%;
  margin-top: -7px;
  right: -20px;              /* catalog: icon parks offscreen right */
  opacity: 0;
  transition: right .5s cubic-bezier(.34, 1.08, .64, 1), opacity .35s ease;
}
.pill-slide::before {
  /* catalog fill bubble: a circle blooms from bottom center to flood the pill */
  content: "";
  position: absolute;
  z-index: 1;
  left: 50%;
  bottom: -8px;
  width: 8px;
  height: 8px;
  border-radius: 96px;
  transform: translateX(-50%);
  background: var(--pill-bubble, rgba(26, 26, 26, .12));
  transition: width .5s cubic-bezier(.34, 1.08, .64, 1), height .5s cubic-bezier(.34, 1.08, .64, 1), bottom .5s cubic-bezier(.34, 1.08, .64, 1);
}
.pill-slide:hover::before,
.pill-slide:focus-visible::before {
  width: 130%;
  height: 240px;
  bottom: -70px;
}
.pill-slide:hover .pill-arrow,
.pill-slide:focus-visible .pill-arrow { right: 16px; opacity: 1; }
.pill-slide:hover .pill-label,
.pill-slide:focus-visible .pill-label { transform: translateX(-11px); }
.pill-red.pill-slide { --pill-bubble: #AE1217; }   /* kit: accent-cta hover state as the bloom */
.pill-red.pill-slide:hover { background: var(--accent-cta); } /* the bubble carries the hover, not the flat swap */

/* ---- Mobile for the revamp layer ---- */
@media (max-width: 820px) {
  .values-grid.deck { height: 430px; margin-top: 28px; } /* derived: narrow cards run longer lines */
  .deck .value-card { padding: 32px 24px; }
  .deck .value-card h3 { font-size: 24px; letter-spacing: -0.5px; } /* locked system: eyebrow scale 24 */
  .deck .value-card p { font-size: 16px; }
  .deck-controls { margin-top: 32px; }
}

/* ---- Reduced motion: kill every revamp effect (deck, tilt, reveals are JS-gated off;
        the pill states below snap instantly instead of animating) ---- */
@media (prefers-reduced-motion: reduce) {
  .pill-slide .pill-label,
  .pill-slide .pill-arrow,
  .pill-slide::before,
  .team-card::after,
  .deck-dots span,
  .count { transition: none; }
}

/* ==========================================================================
   Richness layer (2026-07-12, Thomas verdict: inner pages too plain, under-use
   the catalog). Catalog components re-tokened to the kit; every effect is
   CSS-keyframe or JS-gated progressive enhancement, so no JS and reduced motion
   keep the calm page. House rule: no em or en dashes anywhere in this file.
   ========================================================================== */

/* ---- catalog 194 Halo Effect: soft blush pools drift behind the page hero.
        Not WebGL (compositor transforms only), so no data-fallback needed; still
        gated so reduced motion and low-data freeze it. Every pool is a LIGHTER
        blush/coral tint on the near-white canvas, behind dark ink, so hero text
        contrast only ever improves. ---- */
.page-hero { position: relative; overflow: hidden; }
.page-hero > *:not(.hero-halo) { position: relative; z-index: 1; }
.hero-halo {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}
.hero-halo i {
  position: absolute;
  display: block;
  width: 46%;
  padding-top: 46%;          /* keeps the pools round without a fixed px size */
  border-radius: 50%;
  filter: blur(64px);        /* catalog: gaussian blur dissolves pools into a wash */
  opacity: .55;
  will-change: transform;
}
.hero-halo .halo-a { top: -8%; left: 8%;  background: var(--card-coral); animation: halo-a 15s var(--ease-house) infinite alternate; }
.hero-halo .halo-b { top: 4%;  left: 44%; background: var(--card-blush); animation: halo-b 21s var(--ease-house) infinite alternate; }
.hero-halo .halo-c { top: -18%; left: 64%; width: 38%; padding-top: 38%; background: var(--card-sand); animation: halo-c 18s var(--ease-house) infinite alternate; }
@keyframes halo-a { from { transform: translate(0, 0); }      to { transform: translate(22%, 26%); } }
@keyframes halo-b { from { transform: translate(0, 0); }      to { transform: translate(-18%, 20%); } }
@keyframes halo-c { from { transform: translate(0, 0); }      to { transform: translate(-14%, 30%); } }

/* ---- catalog 084 Animated Text Reveal: the vision and mission statements
        unblur word by word on scroll into view. JS wraps each word in a span;
        no JS and reduced motion show the full sharp statement. ---- */
.vm-text .word {
  display: inline-block;
  white-space: pre;          /* the trailing space rides with the word, no reflow */
}
@media (prefers-reduced-motion: no-preference) {
  .vm-text.reveal-words .word {
    opacity: .1;             /* catalog initialOpacity */
    filter: blur(3px);       /* catalog initialBlur */
    transition: opacity .2s ease-out, filter .2s ease-out; /* catalog word transition */
  }
  .vm-text.reveal-words .word.lit {
    opacity: 1;
    filter: blur(0);
  }
}

/* ---- Illustration accents on the vision and mission cards (imagery, kit line art).
        Decorative only (aria-hidden), corner-set, low opacity so the statement leads. ---- */
.vm-card { position: relative; overflow: hidden; }
.vm-illo {
  position: absolute;
  right: -18px;
  bottom: -18px;
  width: 168px;
  height: 168px;
  object-fit: contain;
  opacity: .16;              /* a whisper of warm line art, never competes with the text */
  pointer-events: none;
  mix-blend-mode: multiply;  /* the cream line art melts into the pastel fill */
}
.vm-text { position: relative; z-index: 1; }

/* ---- catalog 173 Simple Timeline: the company story. A faithful port of the
        real catalog component (design/components/simple-timeline) to vanilla
        CSS/JS, re-tokened to the Sanctuary kit. This is the component's vertical
        scroll-reveal layout: a gradient rail whose ends fade out, a glowing
        accent fill that grows down to the active event as the section scrolls,
        dots that swell, carry a layered glow and pulse as the fill reaches them,
        and rows that slide in from the left. Color roles map one to one from the
        component (lineColor -> --line, activeDotColor -> --accent-cta, dotColor ->
        cream node, textColor -> --ink). Hierarchy is by SIZE at weight 400.
        Real milestones only; middle slots are honest status labels, no invented
        year past the real 2011 anchor. ---- */
.story {
  position: relative;
  padding: 96px 48px 0;             /* kit: section pad 96; page gutter 48 */
}
.story > * { position: relative; z-index: 1; }   /* content rides above the ambient wash */
.story .display { margin-bottom: 56px; text-align: center; }

.timeline {
  --rail-x: 15px;                   /* single source of truth for the rail centre + dots */
  --tl-gap: 72px;                   /* space between events */
  --tl-fill: 0;                     /* 0..1 fill height, driven by scroll (about.js); 0 without JS */
  position: relative;
  max-width: 720px;
  margin: 0 auto;
  padding-left: 0;
  list-style: none;
}
/* base rail: gradient fade at both ends + a soft accent glow
   (component vertical line: linear-gradient lc00 -> lc -> lc00, boxShadow 0 0 10px adc40) */
.timeline::before {
  content: "";
  position: absolute;
  left: var(--rail-x);
  top: 6px;
  bottom: 6px;
  width: 4px;
  margin-left: -2px;
  border-radius: 4px;
  background: linear-gradient(180deg,
    rgba(250, 222, 222, 0) 0%,
    var(--line) 9%,
    var(--line) 91%,
    rgba(250, 222, 222, 0) 100%);
  box-shadow: 0 0 10px rgba(200, 22, 27, .16);
}
/* glowing active fill: grows in height to the active event
   (component line fill: gradient adc -> adc80, boxShadow 0 0 15px adc60) */
.timeline::after {
  content: "";
  position: absolute;
  left: var(--rail-x);
  top: 6px;
  width: 4px;
  margin-left: -2px;
  height: calc((100% - 12px) * var(--tl-fill));
  border-radius: 4px;
  background: linear-gradient(180deg, var(--accent-cta), rgba(200, 22, 27, .55));
  box-shadow: 0 0 14px rgba(200, 22, 27, .55);
  transition: height .3s linear;    /* tracks the scroll read-line smoothly */
  will-change: height;
}

.tl-event {
  position: relative;
  padding: 0 0 var(--tl-gap) 56px;  /* content clears the rail; --tl-gap between events */
}
.tl-event:last-child { padding-bottom: 0; }

/* the dot: a fixed centred box on the rail; the inner <i> carries the visible
   node, so the reveal-scale and the pulse compose without fighting positioning */
.tl-dot {
  position: absolute;
  left: var(--rail-x);
  top: 3px;
  width: 34px;
  height: 34px;
  margin-left: -17px;               /* centre the box on the rail, size-independent */
  display: grid;
  place-items: center;
  pointer-events: none;
}
.tl-dot i {
  display: block;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--surface);                 /* idle node: cream, reads on the blush world */
  box-shadow: 0 0 0 3px var(--line);          /* the component's dot ring, in --line */
  transition: transform .6s cubic-bezier(.4, 0, .2, 1),
              background-color .6s ease,
              box-shadow .6s ease;
}
/* active (the fill has reached this event): swell + accent fill + layered glow
   (component vertical: dot 20 -> 28, glow 0 0 30px adc80 + 0 0 60px adc40) */
.tl-event.in .tl-dot i {
  background: var(--accent-cta);
  box-shadow: 0 0 0 3px var(--line),
              0 0 22px rgba(200, 22, 27, .55),
              0 0 46px rgba(200, 22, 27, .30);
  transform: scale(1.45);                     /* 18 -> ~26 */
}

.tl-body {
  transition: opacity .6s ease, transform .6s cubic-bezier(.4, 0, .2, 1);
}
.tl-date {
  font-size: 16px;                            /* size hierarchy at weight 400 */
  font-weight: 400;
  letter-spacing: .02em;
  color: var(--muted-ink);
  margin-bottom: 10px;
  transition: color .6s ease, text-shadow .6s ease;
}
.tl-event.in .tl-date {
  color: var(--accent-cta);                   /* small saturated moment, on the kit anchor */
  text-shadow: 0 0 12px rgba(200, 22, 27, .22);
}
.tl-title {
  font-size: 28px;                            /* the node's lead, largest at weight 400 */
  font-weight: 400;
  letter-spacing: -.5px;
  line-height: 1.15;
  color: var(--ink);
}
.tl-desc {
  font-size: 16px;                            /* kit: body 16 */
  line-height: 1.55;
  color: var(--muted-ink);
  margin-top: 10px;
  max-width: 520px;
}

/* the pulse begins after the swell settles, from the swollen scale so no jump
   (component: pulse scale 1 -> 1.1 -> 1, 2s ease-in-out, re-based to the swell) */
@keyframes tl-pulse {
  0%, 100% { transform: scale(1.45); }
  50%      { transform: scale(1.6); }
}

/* motion-gated reveal: JS adds .reveal only to events still below the fold, then
   .in as the glowing fill reaches each one. No layout height changes here, so the
   scroll-to-dot sync stays exact. */
@media (prefers-reduced-motion: no-preference) {
  .tl-event.reveal .tl-body { opacity: .32; transform: translateX(-18px); }
  .tl-event.reveal.in .tl-body { opacity: 1; transform: none; }
  .tl-event.in .tl-dot i { animation: tl-pulse 2s ease-in-out .55s infinite; }
}

/* ambient breathe: a faint accent wash pulses behind the timeline on desktop
   (component: breathe radial adc05, opacity 0.3 -> 0.6, 4s). Desktop + motion only. */
@media (min-width: 861px) and (prefers-reduced-motion: no-preference) {
  .story::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background: radial-gradient(circle at 50% 46%, rgba(238, 29, 35, .05) 0%, transparent 60%);
    animation: tl-breathe 4s ease-in-out infinite;
  }
}
@keyframes tl-breathe { 0%, 100% { opacity: .35; } 50% { opacity: .7; } }

/* reduced motion: the timeline reads completed and calm, no motion at all
   (about.js sets --tl-fill:1 and lights every node; here every transition and
   animation is switched off) */
@media (prefers-reduced-motion: reduce) {
  .timeline::after { transition: none; }
  .tl-dot i, .tl-body, .tl-date { transition: none; }
  .tl-event.in .tl-dot i { animation: none; }
}

/* mobile: single column tightens; vertical layout is intrinsic, so it just scales */
@media (max-width: 820px) {
  .story { padding: 56px 20px 0; }  /* kit: mobile gutter 20 */
  .story .display { margin-bottom: 36px; }
  .timeline { --rail-x: 12px; --tl-gap: 48px; max-width: 100%; }
  .tl-event { padding-left: 44px; }
  .tl-dot { width: 30px; height: 30px; margin-left: -15px; }
  .tl-date { font-size: 14px; margin-bottom: 8px; }
  .tl-title { font-size: 21px; }
  .tl-desc { font-size: 15px; }
}

/* ---- catalog 161 Modern Dot Grid: a faint dot field behind the team, with a
        soft pointer-follow highlight (JS sets --mx/--my, mouse only). Static and
        calm without JS. ---- */
.team { position: relative; }
.team-grid, .team .display, .governance { position: relative; z-index: 1; }
.team-dots {
  position: absolute;
  inset: 0 0 -40px;
  z-index: 0;
  pointer-events: none;
  background-image: radial-gradient(rgba(26, 26, 26, .14) 1.4px, transparent 1.5px);
  background-size: 26px 26px;
  -webkit-mask-image: radial-gradient(320px circle at var(--mx, 50%) var(--my, 40%), #000 0%, rgba(0, 0, 0, .35) 45%, transparent 72%);
          mask-image: radial-gradient(320px circle at var(--mx, 50%) var(--my, 40%), #000 0%, rgba(0, 0, 0, .35) 45%, transparent 72%);
  transition: -webkit-mask-position .2s ease-out;
}

/* ---- Reduced motion for the richness layer: freeze the halo drift (the timeline
        has its own reduced-motion block above). ---- */
@media (prefers-reduced-motion: reduce) {
  .hero-halo i { animation: none; }
}

/* ==========================================================================
   Shared footer support: catalog 058 Hover Text Highlight on the footer link
   columns. The markup is copied verbatim from index.html (shared footer);
   its styling lives in home.css, so it is mirrored here token-for-token so the
   shared footer behaves identically on this page. Pure CSS, no runtime.
   ========================================================================== */
.hl-links a { position: relative; }
.hl-links a::after {
  content: "";
  position: absolute;
  left: 0; bottom: -2px;
  width: 100%; height: 2px;
  border-radius: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .3s var(--ease-house);
}
.hl-links a:hover::after,
.hl-links a:focus-visible::after { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) {
  .hl-links a::after { transition: none; }
}
