/* ===========================================================================
   MEMORIAL DIYO — centred at the top of the homepage hero
   Component: src/components/DiyoMemorial.astro (read its header first)
   ===========================================================================

   NO FIELD OF ITS OWN. This block sits inside `.hero-grid`, and `.hero` already
   paints a photograph under a `rgba(3,12,28,.72)` scrim in BOTH themes. So the
   memorial paints inks only — no background, no border — and inherits a dark
   room that is constant by day and by night.

   That is why there is no theme-flip logic below and no `[data-theme]` block:
   there is nothing here that should change between themes. An earlier version
   declared its own always-dark field and had to be written up as an exception
   to docs/04 §5.1. Moving the lamp into the hero deleted the exception rather
   than documenting it, which is the better outcome.

   Measured against the hero scrim (≈ #0B1120):
     --mem-ink      #F4F0E8  → 16.4:1
     --mem-ink-soft #D3D8E2  → 12.3:1
     --mem-accent   #F0A97A  →  9.5:1

   ── TWO CASCADE FACTS THAT COST A DEFECT EACH ─────────────────────────────

   1. EVERY SELECTOR IS DOUBLED as `.memorial .memorial__x`. The homepage body
      carries `page-course`, which brings
        `.page-course main h1, .page-course main h2, …{color:var(--course-ink)}`
      — one class, which beats a bare `.memorial__x` on the class component.
      The first build rendered the memorial heading in `--course-ink`: a
      near-white in dark mode, where nothing looked wrong, and navy #13234B on
      the dark hero in LIGHT mode, at about 1.2:1. Invisible, and invisible only
      by day. Two classes beat one, so the doubling stays.

   2. FONT SIZES CARRY `!important`, which is not decoration either.
        `body.page-course main h2                { font-size: … !important }`
        `body.page-course main :is(p, li, dd)    { font-size: … !important }`
      Both are `!important` in ice-design-system.css, so specificity alone
      cannot win: the memorial's label and caption steps rendered at full body
      size until these matched. Same pattern `body.page-inquiry` already uses.

   Verify any change here in BOTH themes, computed — not in whichever theme
   your OS happens to be in. That is exactly what hid defect 1.

   ── THERE IS NO KICKER, AND THERE MUST NOT BE ─────────────────────────────

   An uppercase `10 BHADRA 2083 · NATIONAL MOURNING` eyebrow sat above the title
   until 2026-08-28. The impeccable craft floor bans the kicker/eyebrow pattern
   with no exception — the heading carries its own weight. Nothing was lost: the
   date is in the first sentence and the mourning is in the second.
   =========================================================================== */

/* The hero grid spaces three children rather than two now, and its own 40px gap
   is tuned for the pair. Closing it here keeps the memorial from pushing the
   college's h1 a full screen down. Scoped with :has() so no other hero on the
   site is touched, and harmless where :has() is unsupported — the layout just
   keeps the wider gap. */
.hero-grid:has(.memorial) { row-gap: clamp(22px, 3vw, 32px); }

.memorial {
  --mem-ink: #F4F0E8;
  --mem-ink-soft: #D3D8E2;
  --mem-accent: #F0A97A;
  /* The same local Devanagari stack ice-tools.css uses. No @font-face and no
     download: PRODUCT.md forbids self-hosted faces, and a memorial has no
     business blocking the critical path of the page it opens. */
  --mem-devanagari: "Noto Sans Devanagari", "Nirmala UI", Mangal, sans-serif;
  /* Fast attack, slow relax — a gust hits and eases off. Symmetric ease-in-out
     on every segment is what makes scripted motion read as a pendulum. */
  --mem-gust-ease: cubic-bezier(.32, .06, .28, .98);

  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  width: 100%;
  max-width: 660px;
  margin: 0 auto;
  color: var(--mem-ink);
}

/* ── The lamp ──────────────────────────────────────────────────────────── */

.memorial .memorial__diyo {
  display: block;
  /* Wider and shorter than the taper it replaced: a diyo's silhouette IS its
     proportion, so the graphic is given room across rather than up. It also
     costs less height above the h1 than the candle did. */
  width: clamp(148px, 30vw, 208px);
  height: auto;
  margin-bottom: 2px;
  /* The halo is drawn inside the viewBox, so nothing bleeds past the hero. */
  overflow: visible;
}

/* The lotus aureole. Low enough to read as light on stone rather than as a
   sticker behind the lamp, and deliberately unanimated — the flame is the one
   authored moment on this page. */
.memorial .memorial__lotus path {
  fill: none;
  stroke: var(--mem-accent);
  stroke-width: 1.1;
  opacity: .17;
}

/* Each animated part leans from its own base, not from the middle of the
   artboard, so the flame sits on the wick. */
.memorial .memorial__glow,
.memorial .memorial__flame-outer,
.memorial .memorial__flame-body,
.memorial .memorial__flame-core {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  will-change: transform, opacity;
}

.memorial .memorial__glow {
  transform-origin: 50% 50%;
  animation: memorial-halo 3.7s ease-in-out infinite;
}

/* ── FLAME MOTION ─────────────────────────────────────────────────────────

   Rewritten 2026-08-28 after the owner: "it jiggiboing up and down rather than
   real wind physics." Measured on the previous version and they were exactly
   right — 11.19px of vertical excursion against 1.7px horizontal. It was a
   vertical pump, because `scaleY` was oscillating +/-13% as its own fast beat
   independent of the lean. That is a bouncing flame, not a windy one.

   What a flame in moving air actually does, and what each rule below is for:

   1. IT LEANS DOWNWIND, it does not bob. All the travel is `skewX` and
      `rotate` about `transform-origin: 50% 100%` — the wick — so the tip moves
      and the base stays welded to the lamp. There is NO `translateX` and no
      `translateY` any more; both moved the base and that is what read as boing.

   2. IT ELONGATES *BECAUSE* IT LEANS. Height is no longer an independent
      oscillation: every keyframe's `scaleY` is tied to that keyframe's skew, so
      the flame stretches as the air draws it out and settles back as it stands
      up. Range cut from 0.88-1.14 to 0.97-1.11.

   3. THE WIND HAS A PREVAILING DIRECTION. The keyframes are asymmetric and
      unevenly spaced: a rightward bias, two gusts further right, a lull back
      toward vertical, and one weak counter-gust. Evenly spaced symmetric
      keyframes are what produce a metronome.

   4. LIGHT AIR MOVES FURTHER THAN HOT GAS. Three separate keyframe sets rather
      than one shared: the soft outer envelope swings hardest (19deg), the body
      follows (13deg), and the dense core nearest the wick barely leans (5deg).
      One shared animation made the core swing as hard as the smoke, which is
      backwards.

   Periods stay mutually indivisible — 2.3 / 1.9 / 1.3, with 7.3 for the gust —
   so no two layers ever repeat the same relative pose. */

.memorial .memorial__flame-outer { animation: memorial-lean-outer 2.3s var(--mem-gust-ease) infinite; }
.memorial .memorial__flame-body  { animation: memorial-lean-body  1.9s var(--mem-gust-ease) infinite; }
.memorial .memorial__flame-core  { animation: memorial-lean-core  1.3s var(--mem-gust-ease) infinite; }

/* The gust: every seven seconds or so the draft nearly takes it and it
   recovers. Opacity on the GROUP, so it composes with the per-layer transforms
   instead of fighting them. */
.memorial .memorial__flame { animation: memorial-gust 7.3s ease-in-out infinite; }

@keyframes memorial-halo {
  0%, 100% { opacity: .78; transform: translateX(1px)   scale(1); }
  34%      { opacity: 1;   transform: translateX(3.5px) scale(1.07); }
  62%      { opacity: .7;  transform: translateX(-1px)  scale(.96); }
}

/* Outer envelope — the lightest gas, thrown furthest. */
@keyframes memorial-lean-outer {
  0%   { transform: skewX(5deg)   rotate(2deg)    scaleY(1); }
  9%   { transform: skewX(11deg)  rotate(4.5deg)  scaleY(1.05); }
  17%  { transform: skewX(7deg)   rotate(3deg)    scaleY(1.02); }
  31%  { transform: skewX(19deg)  rotate(8.5deg)  scaleY(1.11); }
  38%  { transform: skewX(14deg)  rotate(6deg)    scaleY(1.07); }
  49%  { transform: skewX(2deg)   rotate(.5deg)   scaleY(.98); }
  57%  { transform: skewX(9deg)   rotate(3.5deg)  scaleY(1.03); }
  68%  { transform: skewX(16.5deg) rotate(7deg)   scaleY(1.09); }
  76%  { transform: skewX(6deg)   rotate(2.5deg)  scaleY(1.01); }
  86%  { transform: skewX(-3.5deg) rotate(-1.5deg) scaleY(.97); }
  93%  { transform: skewX(4deg)   rotate(1.5deg)  scaleY(1); }
  100% { transform: skewX(5deg)   rotate(2deg)    scaleY(1); }
}

/* Body — follows the envelope, damped. */
@keyframes memorial-lean-body {
  0%   { transform: skewX(3.5deg) rotate(1.5deg)  scaleY(1); }
  11%  { transform: skewX(8deg)   rotate(3.2deg)  scaleY(1.035); }
  19%  { transform: skewX(5deg)   rotate(2deg)    scaleY(1.015); }
  33%  { transform: skewX(13deg)  rotate(5.8deg)  scaleY(1.075); }
  41%  { transform: skewX(9.5deg) rotate(4deg)    scaleY(1.05); }
  52%  { transform: skewX(1.5deg) rotate(.4deg)   scaleY(.985); }
  60%  { transform: skewX(6.5deg) rotate(2.6deg)  scaleY(1.02); }
  71%  { transform: skewX(11.5deg) rotate(4.8deg) scaleY(1.06); }
  79%  { transform: skewX(4deg)   rotate(1.8deg)  scaleY(1.005); }
  88%  { transform: skewX(-2.5deg) rotate(-1deg)  scaleY(.98); }
  95%  { transform: skewX(3deg)   rotate(1.2deg)  scaleY(1); }
  100% { transform: skewX(3.5deg) rotate(1.5deg)  scaleY(1); }
}

/* Core — hot, dense, nearest the wick. It barely leans; it mostly brightens. */
@keyframes memorial-lean-core {
  0%   { transform: skewX(1.5deg) rotate(.6deg)  scaleY(1);    opacity: .92; }
  14%  { transform: skewX(3deg)   rotate(1.3deg) scaleY(1.02); opacity: 1; }
  30%  { transform: skewX(5deg)   rotate(2.4deg) scaleY(1.04); opacity: 1; }
  44%  { transform: skewX(3.4deg) rotate(1.5deg) scaleY(1.01); opacity: .88; }
  58%  { transform: skewX(.6deg)  rotate(.2deg)  scaleY(.99);  opacity: .95; }
  73%  { transform: skewX(4.2deg) rotate(1.9deg) scaleY(1.03); opacity: 1; }
  88%  { transform: skewX(-1deg)  rotate(-.4deg) scaleY(.985); opacity: .9; }
  100% { transform: skewX(1.5deg) rotate(.6deg)  scaleY(1);    opacity: .92; }
}

@keyframes memorial-gust {
  0%, 58%, 100% { opacity: 1; }
  66%           { opacity: .68; }
  71%           { opacity: .94; }
  77%           { opacity: .78; }
  85%           { opacity: 1; }
}

@keyframes memorial-sheen {
  0%, 100% { opacity: .42; transform: scaleX(1); }
  45%      { opacity: .62; transform: scaleX(1.12); }
}

/* ── Copy ──────────────────────────────────────────────────────────────── */

/* The Nepali condolence leads; the English follows as its deck. Owner's
   decision, 2026-08-28. Devanagari carries taller ascenders and a shirorekha,
   so it takes a slightly looser line than the Latin step would give it. */
.memorial .memorial__title {
  margin: 0 0 6px;
  color: var(--mem-ink);
  /* `!important` is required, not preferred: `body.page-course main :is(p,li,dd)`
     pins font-family to --ice-font-primary with !important, so specificity alone
     cannot reach this. Naming a Devanagari face here is INSIDE the docs/04 §1
     contract, which allows Noto Sans Devanagari "only for scripts this stack
     cannot set" — the Apple UI stack carries no Devanagari at all. Without it
     the glyphs still render, but via each OS's own default substitute, so the
     condolence looked like a different typeface on every phone. */
  font-family: var(--mem-devanagari) !important;
  font-size: clamp(1.5rem, 1.28rem + .95vw, 2.125rem) !important;
  line-height: 1.42;
  font-weight: 600;
  letter-spacing: 0;
}

.memorial .memorial__subtitle {
  margin: 0 0 12px;
  color: var(--mem-accent);
  font-size: var(--ice-type-h4-size) !important;
  line-height: var(--ice-type-h4-line);
  font-weight: 400;
  letter-spacing: .005em;
}

.memorial .memorial__lede {
  margin: 0 0 8px;
  color: var(--mem-ink);
  font-size: var(--ice-type-body-size) !important;
  line-height: var(--ice-type-body-line);
}

.memorial .memorial__body {
  margin: 0 0 16px;
  color: var(--mem-ink-soft);
  font-size: var(--ice-type-caption-size) !important;
  line-height: var(--ice-type-leading-160);
}

/* ── Actions ───────────────────────────────────────────────────────────── */

.memorial .memorial__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
  margin-bottom: 12px;
}

.memorial .memorial__action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 12px 20px;
  border: 1px solid rgba(244, 240, 232, 0.4);
  border-radius: 4px;
  color: var(--mem-ink);
  background: rgba(11, 17, 32, 0.34);
  text-decoration: none;
  font-size: var(--ice-type-button-size);
  line-height: var(--ice-type-button-line);
  font-weight: var(--ice-type-button-weight);
  letter-spacing: var(--ice-type-button-track);
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}

.memorial .memorial__action--primary {
  background: var(--mem-accent);
  border-color: var(--mem-accent);
  /* Deep navy ink on terracotta — the same pairing as --ice-color-on-accent. */
  color: #0B1225;
}

.memorial .memorial__action:hover {
  background: rgba(244, 240, 232, 0.16);
  border-color: rgba(244, 240, 232, 0.68);
}

.memorial .memorial__action--primary:hover {
  background: #F7C39C;
  border-color: #F7C39C;
  color: #0B1225;
}

.memorial .memorial__action:focus-visible {
  outline: 3px solid var(--mem-ink);
  outline-offset: 3px;
}

/* Pressed. Both actions lead somewhere; neither should feel inert on a tap. */
.memorial .memorial__action:active { transform: translateY(1px); }

/* Below ~420px the two actions cannot share a row. Let them stack at full width
   rather than sit as two ragged pills of different lengths: same height either
   way, but one of them looks designed. */
@media (max-width: 419px) {
  .memorial .memorial__actions { gap: 8px; width: 100%; }
  .memorial .memorial__action { flex: 1 1 100%; }
}

.memorial .memorial__note {
  margin: 0;
  color: var(--mem-ink-soft);
  font-size: var(--ice-type-caption-size) !important;
  line-height: var(--ice-type-caption-line);
}

.memorial .memorial__note a {
  color: var(--mem-accent);
  text-underline-offset: 3px;
}

.memorial .memorial__note a:focus-visible { outline: 3px solid var(--mem-ink); outline-offset: 2px; }

/* A hairline between the memorial and the college's own hero headline, so the
   two do not read as one run of copy. */
.memorial::after {
  content: '';
  width: min(200px, 46%);
  height: 1px;
  margin-top: clamp(16px, 2.2vw, 24px);
  background: linear-gradient(90deg, transparent, rgba(240, 169, 122, 0.42), transparent);
}

/* ── Reduced motion ────────────────────────────────────────────────────────
   The lamp stays LIT. Only the movement stops. A memorial that blanks itself
   for a reader with a vestibular disorder is a memorial that excluded them. */

@media (prefers-reduced-motion: reduce) {
  .memorial .memorial__glow,
  .memorial .memorial__flame,
  .memorial .memorial__flame-outer,
  .memorial .memorial__flame-body,
  .memorial .memorial__flame-core,
  .memorial .memorial__sheen {
    animation: none;
  }
  .memorial .memorial__glow { opacity: .88; }
  .memorial .memorial__action:active { transform: none; }
}
