/* ===================================================================
   KNMS LANDING — clean rebuild
   -------------------------------------------------------------------
   Built from the approved design rather than patched onto the older
   hero styles. Everything is namespaced `kn-` and scoped inside
   `.kn-hero`, so none of the accumulated overrides in app.css reach it
   and nothing here leaks into the rest of the portal.

   Loaded after app.css on the homepage only.
   =================================================================== */

.kn-hero {
    /* Local tokens. Accent colours inherit the admin-tunable theme
       variables, falling back to the design's values. */
    --kn-gold:        var(--knms-accent, #ffc94a);
    --kn-gold-lt:     #ffe08a;
    --kn-gold-dk:     #ffb61f;
    --kn-cyan:        var(--gloss-cyan, #35dcff);
    --kn-cyan-dk:     #12a6e8;
    --kn-violet:      var(--gloss-purple, #8b3ff5);
    --kn-panel-brd:   rgba(255, 214, 130, 0.95);
    --kn-panel-brd-v: rgba(205, 165, 255, 0.95);
    --kn-panel-bg1:   rgba(84, 40, 168, 0.62);
    --kn-panel-bg2:   rgba(44, 19, 92, 0.76);
    --kn-glow:        var(--theme-glow, 1);
    --kn-radius:      12px;
    --kn-max:         1400px;

    /* Backdrop geometry. Declared here, not on .kn-hero__sky, because the
       arcs layer must use the SAME box: both are `cover`-mapped from the same
       viewBox, so if their boxes differ the two artworks stop lining up.
         travel — how far the parallax may shift the sky
         bleed  — extra overhang so the depth-of-field blur never samples past
                  the edge of the artwork and fade a soft border into view */
    --kn-sky-travel:  60px;
    --kn-sky-bleed:   48px;
    --kn-sky-inset-y: calc((var(--kn-sky-travel) + var(--kn-sky-bleed)) * -1);
    --kn-sky-inset-x: calc(var(--kn-sky-bleed) * -1);

    position: relative;
    /* Full-bleed out of the centred .page column. --sbw is the scrollbar width,
       published by app.js: 50vw includes the scrollbar and 50% does not, so
       without that correction the hero overshoots the viewport and the whole
       page drifts sideways on mobile. Defaults to 0 when JS is off. */
    margin: -1.5rem calc(50% - 50vw + var(--sbw, 0px) / 2) 1.6rem;
    padding: 2.2rem max(1rem, calc(50vw - var(--sbw, 0px) / 2 - (var(--kn-max) / 2))) 2rem;
    background: #150a2e;
    color: #fff;
    overflow: hidden;
    isolation: isolate;
}

/* --- Backdrop ---------------------------------------------------- */
.kn-hero__sky {
    position: absolute;
    /* Bled past every edge (see the tokens on .kn-hero) so the scroll parallax
       has room to move and the blur below never samples past the artwork. The
       hero clips, so the overhang never shows. app.js clamps its shift to
       --kn-sky-travel. */
    inset: var(--kn-sky-inset-y) var(--kn-sky-inset-x);
    z-index: 0;
    background: url("../img/hero-backdrop.svg") center 46% / cover no-repeat;
    /* Depth of field. The reference reads photographic because everything
       behind the subject is soft; drawn vector silhouettes are perfectly
       crisp, which is what made this backdrop look flat and illustrated next
       to a sharp portrait. The portrait, arcs and panels stay unblurred, so
       the softness reads as distance rather than as an out-of-focus page. */
    /* Kept modest because hero-backdrop.svg now carries its own distance ramp
       (dofFar/dofMid/dofNear); this is the shared atmospheric haze on top of
       it, not the whole effect. */
    filter: blur(2.4px);
    pointer-events: none;
    will-change: transform;
}
/* Golden sweeps + glint dust. `screen` so it can only add light — over a dark
   sky it glows, and it stays correct if the organisation uploads its own
   backdrop underneath. Scale is tied to --kn-glow so the admin slider fades
   the whole light rig, not just the panels. */
.kn-hero__arcs {
    position: absolute;
    /* MUST match .kn-hero__sky exactly — same box, same cover mapping, or the
       sweeps drift out of register with the scene they were placed against. */
    inset: var(--kn-sky-inset-y) var(--kn-sky-inset-x);
    z-index: 1;                       /* above the vignette, below the content */
    background: url("../img/hero-arcs.svg") center 46% / cover no-repeat;
    mix-blend-mode: screen;
    opacity: calc(0.92 * var(--kn-glow));
    pointer-events: none;
}
/* --- Heritage layer ---------------------------------------------- */
/* The ghosted figures behind the portrait. Screen-blended and desaturated so
   an ordinary photograph reads as a memory in the scene rather than a second
   picture pasted beside the first, and masked on every edge so it has no
   border of its own. Sits above the vignette, below the content. */
.kn-hero__heritage {
    position: absolute;
    z-index: 1;
    left: 0;
    top: 4%;
    width: min(32%, 460px);
    height: 66%;
    background-size: cover;
    background-position: center top;
    background-repeat: no-repeat;
    mix-blend-mode: screen;
    opacity: calc(0.34 * var(--kn-glow));
    filter: saturate(0.5) contrast(0.92);
    -webkit-mask-image: radial-gradient(ellipse 60% 66% at 44% 44%, #000 34%, rgba(0,0,0,0.55) 68%, transparent 100%);
    mask-image:         radial-gradient(ellipse 60% 66% at 44% 44%, #000 34%, rgba(0,0,0,0.55) 68%, transparent 100%);
    pointer-events: none;
}
@media (max-width: 900px) {
    /* Stacked layout puts the portrait centre-stage; a half-width ghost beside
       it just muddies the backdrop, so pull it back further. */
    .kn-hero__heritage { width: 46%; height: 46%; opacity: calc(0.2 * var(--kn-glow)); }
}

/* --- Luminous blooms (NOT spheres) --------------------------------
   Edgeless pools of light. Discrete glossy spheres were removed three times,
   each time reported as "bubbles" — the defined edge and specular highlight
   are what make a shape read as an object sitting on the artwork, regardless
   of how small or faint it is. These have no edge at all: a radial gradient
   that fades to fully transparent well before its box, so it contributes
   depth and colour without ever resolving into a thing.

   No border-radius, no inset shading, no highlight — those all reintroduce
   the object. Blur keeps the falloff smooth on wide gradients. */
.kn-hero__blooms {
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    overflow: hidden;
}
.kn-bloom {
    position: absolute;
    opacity: calc(0.5 * var(--kn-glow));
    background: radial-gradient(circle at 50% 50%,
        var(--kn-bloom-core) 0%,
        var(--kn-bloom-mid) 34%,
        rgba(0,0,0,0) 72%);
    filter: blur(18px);
    mix-blend-mode: screen;
}
.kn-bloom--gold   { --kn-bloom-core: rgba(255,205,110,0.50); --kn-bloom-mid: rgba(255,165,50,0.20); }
.kn-bloom--cyan   { --kn-bloom-core: rgba(120,225,255,0.42); --kn-bloom-mid: rgba(40,170,235,0.17); }
.kn-bloom--violet { --kn-bloom-core: rgba(190,150,255,0.44); --kn-bloom-mid: rgba(120,60,215,0.18); }

/* Slow breathing, no travel — movement across the frame would draw the eye
   to the bloom as an object again. */
@keyframes kn-bloom-breathe {
    0%, 100% { opacity: calc(0.42 * var(--kn-glow)); }
    50%      { opacity: calc(0.62 * var(--kn-glow)); }
}
.kn-hero__blooms--full .kn-bloom { animation: kn-bloom-breathe 15s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
    .kn-hero__blooms--full .kn-bloom { animation: none; }
}
/* Phones: the hero narrows but the blooms do not, so scale them back rather
   than letting them wash over the portrait. */
@media (max-width: 900px) {
    .kn-bloom { scale: 0.7; opacity: calc(0.34 * var(--kn-glow)); }
}
@media (max-width: 600px) {
    .kn-bloom { scale: 0.55; opacity: calc(0.26 * var(--kn-glow)); }
}

.kn-hero__vignette {
    position: absolute;
    inset: 0;
    z-index: 1;
    /* Three layers, and the order matters — the FIRST background layer paints
       on top. The cool edge highlights are listed first so they read over the
       darkened rim rather than being buried by it.

       This completes the brief's gradient run: deep purple base and golden
       centre already came from the backdrop artwork, but there was no
       light-blue at the edges at all — cyan existed only on buttons. */
    background:
        radial-gradient(ellipse 34% 62% at 0% 46%,   rgba(70, 214, 255, 0.20), transparent 72%),
        radial-gradient(ellipse 34% 62% at 100% 46%, rgba(70, 214, 255, 0.17), transparent 72%),
        radial-gradient(ellipse 70% 30% at 50% 100%, rgba(60, 190, 255, 0.10), transparent 74%),
        radial-gradient(ellipse 78% 70% at 50% 48%, transparent 40%, rgba(12, 5, 30, 0.5) 84%, rgba(10, 4, 24, 0.85) 100%);
    pointer-events: none;
}

/* --- Layout ------------------------------------------------------ */
.kn-hero__inner {
    position: relative;
    z-index: 2;
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    gap: 1.6rem;
    align-items: center;
    min-height: 48vh;
}

/* --- Left column: figure + copy ---------------------------------- */
.kn-hero__left {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
}
.kn-figure { position: relative; margin-bottom: 0.4rem; }
/* Legacy halo — a broad radial glow behind the subject. The figure already
   carried drop-shadows, but those hug the silhouette; this is the light the
   portrait sits *in*, which is what makes it read as the centre of the scene
   rather than a cut-out placed on it. Sits behind the image (z-index -1),
   scaled with the admin glow control. */
.kn-figure::before {
    content: '';
    position: absolute;
    left: 50%;
    top: 42%;
    width: 172%;
    aspect-ratio: 1;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background: radial-gradient(circle,
        rgba(255, 214, 130, calc(0.30 * var(--kn-glow))) 0%,
        rgba(255, 172, 56,  calc(0.17 * var(--kn-glow))) 32%,
        rgba(255, 150, 40, calc(0.06 * var(--kn-glow))) 52%,
        transparent 70%);
    filter: blur(26px);
    z-index: -1;
    pointer-events: none;
}
/* Warm pool beneath, so the subject stands in the scene. */
.kn-figure::after {
    content: '';
    position: absolute;
    left: 50%;
    bottom: 0;
    width: 74%;
    height: 11%;
    transform: translateX(-50%);
    border-radius: 50%;
    background: radial-gradient(ellipse, rgba(18, 7, 38, 0.7) 0%, rgba(18, 7, 38, 0.3) 46%, transparent 72%);
    filter: blur(14px);
    z-index: -1;
}
.kn-figure img {
    display: block;
    width: min(430px, 72vw);
    height: auto;
}
/* A real photograph: portrait crop, feathered base, backlit rim.
   Two masks intersected — an elliptical vignette that dissolves the corners
   and side edges, plus a stronger fade at the base so the subject stands in
   the scene. A single vertical gradient (what this was) leaves the left,
   right and top edges hard, which reads as a photo pasted onto the artwork
   as soon as a real portrait is uploaded. */
.kn-figure--photo img {
    aspect-ratio: 4 / 5;
    object-fit: cover;
    object-position: top center;
    /* ONE mask layer on purpose: multiple layers default to mask-composite:add
       (union), which unions straight back to the full rectangle and looks like
       no mask at all.

       The radii are percentages of the BOX, not of the visible edge — they are
       the ellipse's horizontal/vertical radius measured from `at`. Anything
       much above 50%/50% pushes the `transparent` stop outside the element, so
       the visible area never gets past the near-opaque stops and the corners
       stay hard. 58%/68% was picked by rendering 50/62, 58/68, 64/74 and 68/62
       against the real portrait: it dissolves the corners and sides into the
       artwork while keeping the shoulders and hand intact. */
    -webkit-mask-image: radial-gradient(ellipse 58% 68% at 50% 40%, #000 48%, rgba(0,0,0,0.88) 70%, rgba(0,0,0,0.4) 87%, transparent 100%);
    mask-image:         radial-gradient(ellipse 58% 68% at 50% 40%, #000 48%, rgba(0,0,0,0.88) 70%, rgba(0,0,0,0.4) 87%, transparent 100%);
    filter:
        drop-shadow(10px -8px 26px rgba(255, 206, 110, calc(0.8 * var(--kn-glow))))
        drop-shadow(0 0 70px rgba(255, 176, 60, calc(0.5 * var(--kn-glow))))
        drop-shadow(0 18px 44px rgba(0, 0, 0, 0.55));
}
/* The emblem fallback: contained, lit from the sun's side. */
.kn-figure--emblem img {
    aspect-ratio: 1 / 1;
    object-fit: contain;
    filter:
        drop-shadow(-6px 8px 0 rgba(90, 40, 170, 0.32))
        drop-shadow(10px -8px 26px rgba(255, 206, 110, calc(0.85 * var(--kn-glow))))
        drop-shadow(0 0 70px rgba(255, 176, 60, calc(0.55 * var(--kn-glow))))
        drop-shadow(0 20px 48px rgba(0, 0, 0, 0.55));
}
/* Staff prompt when no photograph has been supplied. */
.kn-figure--empty a {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    width: min(320px, 68vw);
    aspect-ratio: 4 / 5;
    padding: 1.4rem 1.2rem;
    border-radius: 16px;
    border: 2px dashed rgba(255, 205, 110, 0.55);
    background: rgba(20, 9, 44, 0.5);
    color: rgba(255, 255, 255, 0.78);
    text-align: center;
    font-size: 0.82rem;
    line-height: 1.5;
}
.kn-figure--empty a:hover { border-color: rgba(255, 205, 110, 0.95); color: #fff; }
.kn-figure--empty .icon { width: 2.4rem; height: 2.4rem; color: var(--kn-gold-lt); }
.kn-figure--empty strong { font-family: 'Baloo 2','Poppins',sans-serif; font-size: 1rem; color: var(--kn-gold-lt); }

/* Copy sits on a soft dark bed — gold on the bright horizon would
   otherwise lose contrast. */
.kn-copy { position: relative; }
.kn-copy::before {
    content: '';
    position: absolute;
    inset: -1.4rem -3rem -1rem;
    z-index: -1;
    border-radius: 50%;
    /* Atmospheric shade, not a slab. This was a near-opaque black ellipse,
       which read as a dark blob pasted over the artwork — the reference has
       no such shape, the copy simply glows against the scene. It still needs
       *some* bed because the title lands on the bright horizon here, so keep
       it faint and blur the edge away. */
    background: radial-gradient(ellipse at 50% 46%,
        rgba(12, 5, 30, 0.58) 0%, rgba(12, 5, 30, 0.40) 44%,
        rgba(12, 5, 30, 0.15) 70%, transparent 88%);
    filter: blur(7px);
}
.kn-title {
    margin: 0 0 0.3rem;
    font-family: 'Baloo 2', 'Poppins', sans-serif;
    font-weight: 700;
    font-size: clamp(1.3rem, 2.7vw, 2.1rem);
    line-height: 1.2;
    color: #ffd45e;
}
/* Gold gradient fill. Guarded like the other clipped headings in app.css so
   an unsupporting browser keeps the flat gold above rather than going
   invisible. The shadow MUST be filter:drop-shadow, not text-shadow — with a
   clipped transparent fill Chrome paints the text-shadow and drops the
   gradient, which rendered this heading as flat grey smudge. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
    .kn-title {
        background: linear-gradient(92deg, #fff2c4, #ffd45e 45%, #ffb628);
        -webkit-background-clip: text;
        background-clip: text;
        -webkit-text-fill-color: transparent;
        color: transparent;
        filter: drop-shadow(0 2px 6px rgba(10, 4, 28, 0.95))
                drop-shadow(0 0 18px rgba(255, 180, 60, calc(0.45 * var(--kn-glow))));
    }
}
.kn-subtitle {
    margin: 0 0 1.1rem;
    font-size: clamp(0.95rem, 1.5vw, 1.08rem);
    color: #fff3d6;
    text-shadow: 0 1px 10px rgba(10, 4, 28, 0.95);
}
.kn-actions { display: flex; gap: 0.9rem; flex-wrap: wrap; justify-content: center; }
.kn-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 168px;
    padding: 0.78rem 1.7rem;
    border-radius: 10px;
    font-family: 'Poppins', sans-serif;
    font-weight: 700;
    font-size: 1.02rem;
    /* box-shadow is in the transition list on purpose: the glow lives there,
       and without it hovering changed the lift but the halo snapped. */
    transition: transform .18s ease, filter .2s ease, box-shadow .28s ease;
}
.kn-btn:hover,
.kn-btn:focus-visible { transform: translateY(-2px); filter: brightness(1.06); }
.kn-btn:active { transform: translateY(0); transition-duration: .06s; }
.kn-btn--gold {
    background: linear-gradient(135deg, var(--kn-gold-lt), var(--kn-gold-dk));
    color: #3a1a02;
    box-shadow: 0 6px 24px rgba(0,0,0,.4),
                0 0 34px rgba(255,190,60, calc(0.95 * var(--kn-glow))),
                0 0 70px rgba(255,150,30, calc(0.5 * var(--kn-glow)));
}
.kn-btn--gold:hover,
.kn-btn--gold:focus-visible {
    color: #3a1a02;
    box-shadow: 0 11px 30px rgba(0,0,0,.46),
                0 0 52px rgba(255,196,70, calc(1 * var(--kn-glow))),
                0 0 104px rgba(255,150,30, calc(0.72 * var(--kn-glow)));
}
.kn-btn--cyan {
    background: linear-gradient(135deg, #5fe0ff, var(--kn-cyan-dk));
    color: #032738;
    box-shadow: 0 6px 24px rgba(0,0,0,.4),
                0 0 34px rgba(60,210,255, calc(0.95 * var(--kn-glow))),
                0 0 70px rgba(20,160,240, calc(0.5 * var(--kn-glow)));
}
.kn-btn--cyan:hover,
.kn-btn--cyan:focus-visible {
    color: #032738;
    box-shadow: 0 11px 30px rgba(0,0,0,.46),
                0 0 52px rgba(90,224,255, calc(1 * var(--kn-glow))),
                0 0 104px rgba(20,160,240, calc(0.72 * var(--kn-glow)));
}
.kn-welcome { margin: 0.9rem 0 0; font-size: 0.9rem; color: rgba(255,255,255,.78); }

/* --- Panels ------------------------------------------------------ */
.kn-rail { display: flex; flex-direction: column; gap: 1.1rem; }
.kn-panel {
    position: relative;
    border-radius: var(--kn-radius);
    padding: 1.25rem 1.35rem 1.35rem;
    background: linear-gradient(155deg, var(--kn-panel-bg1), var(--kn-panel-bg2));
    backdrop-filter: blur(9px) saturate(1.25);
    -webkit-backdrop-filter: blur(9px) saturate(1.25);
    transition: box-shadow .32s ease, transform .22s ease;
}
/* Panels lift into their own glow on hover — the whole card is a link target
   in the bottom row, so it should answer the pointer. */
.kn-panel:hover { transform: translateY(-2px); }
.kn-panel--gold {
    border: 1.5px solid var(--kn-panel-brd);
    box-shadow: 0 0 40px rgba(255,190,70, calc(0.6 * var(--kn-glow))),
                0 0 90px rgba(255,150,40, calc(0.3 * var(--kn-glow))),
                inset 0 0 56px rgba(120,50,210,.4);
}
.kn-panel--gold:hover {
    box-shadow: 0 0 58px rgba(255,198,80, calc(0.82 * var(--kn-glow))),
                0 0 124px rgba(255,150,40, calc(0.44 * var(--kn-glow))),
                inset 0 0 56px rgba(120,50,210,.4);
}
.kn-panel--violet {
    border: 1.5px solid var(--kn-panel-brd-v);
    box-shadow: 0 0 40px rgba(150,80,255, calc(0.7 * var(--kn-glow))),
                0 0 90px rgba(110,50,230, calc(0.34 * var(--kn-glow))),
                inset 0 0 56px rgba(120,50,210,.4);
}
.kn-panel--violet:hover {
    box-shadow: 0 0 58px rgba(168,104,255, calc(0.9 * var(--kn-glow))),
                0 0 124px rgba(110,50,230, calc(0.48 * var(--kn-glow))),
                inset 0 0 56px rgba(120,50,210,.4);
}
/* Corner brackets */
.kn-panel::before, .kn-panel::after {
    content: '';
    position: absolute;
    width: 18px; height: 18px;
    border-style: solid;
    pointer-events: none;
}
.kn-panel--gold::before, .kn-panel--gold::after { border-color: rgba(255,226,150,1); }
.kn-panel--violet::before, .kn-panel--violet::after { border-color: rgba(205,170,255,1); }
.kn-panel::before { top: 6px; left: 6px; border-width: 2px 0 0 2px; border-radius: 4px 0 0 0; }
.kn-panel::after  { bottom: 6px; right: 6px; border-width: 0 2px 2px 0; border-radius: 0 0 4px 0; }

.kn-panel__title {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    margin: 0 0 0.85rem;
    padding-bottom: 0.6rem;
    border-bottom: 1px dashed rgba(232,188,92,.34);
    font-family: 'Poppins', sans-serif;
    font-size: 1.2rem;
    font-weight: 700;
    color: var(--kn-gold-lt);
    text-shadow: 0 0 22px rgba(255,200,80,.7);
}
.kn-panel__title .icon { width: 1.15rem; height: 1.15rem; color: var(--kn-gold); }
.kn-panel__empty { margin: 0 0 .9rem; text-align: center; font-size: .95rem; line-height: 1.6; color: rgba(255,255,255,.75); }

/* Row label with its checkbox marker */
.kn-row-label {
    display: flex;
    align-items: center;
    gap: .45rem;
    margin: .55rem 0 .5rem;
    padding-top: .55rem;
    border-top: 1px dashed rgba(232,188,92,.3);
    font-size: 1rem;
    font-weight: 600;
    color: #fff;
}
.kn-row-label:first-of-type { border-top: none; padding-top: 0; }
.kn-row-label .icon { width: 1.15rem; height: 1.15rem; }

/* Celebrants */
.kn-celebrants { display: flex; flex-wrap: wrap; justify-content: center; margin-bottom: .4rem; }
.kn-celebrant { display: inline-flex; align-items: center; gap: .5rem; padding: 0 .85rem; font-size: 1rem; font-weight: 600; }
.kn-celebrant + .kn-celebrant { border-left: 1px solid rgba(255,205,110,.5); }
.kn-celebrant img, .kn-celebrant .avatar {
    width: 2.9rem; height: 2.9rem; border-radius: 50%; object-fit: cover;
    border: 2px solid rgba(255,214,130,1);
    box-shadow: 0 0 18px rgba(255,196,74, calc(0.9 * var(--kn-glow)));
}
.kn-celebrant span { color: var(--kn-gold-lt); text-shadow: 0 0 12px rgba(255,200,80,.6); }
.kn-more { align-self: center; font-size: .85rem; color: rgba(255,255,255,.75); }

/* Event rows */
.kn-event {
    display: flex; align-items: center; gap: .5rem;
    padding: .62rem 0;
    border-bottom: 1px dashed rgba(255,205,110,.32);
    font-size: .98rem; color: #fff;
}
.kn-event:last-of-type { border-bottom: none; }
.kn-event:hover { color: var(--kn-gold-lt); }
.kn-event .icon { width: 1.15rem; height: 1.15rem; flex-shrink: 0; }
.kn-event__name { font-weight: 600; }
.kn-event__when { margin-left: auto; font-size: .84rem; color: #ffcf72; white-space: nowrap; }

/* Panel buttons */
.kn-pbtn {
    display: block;
    width: fit-content;
    margin: 1rem auto 0;
    padding: .58rem 1.4rem;
    border-radius: 8px;
    font-weight: 700;
    font-size: .94rem;
    text-align: center;
    transition: transform .18s ease, filter .2s ease, box-shadow .28s ease;
}
.kn-pbtn:hover, .kn-pbtn:focus-visible { transform: translateY(-1px); filter: brightness(1.08); }
.kn-pbtn:active { transform: translateY(0); transition-duration: .06s; }
.kn-pbtn--gold { background: linear-gradient(135deg, var(--kn-gold-lt), var(--kn-gold-dk)); color: #3a1a02; box-shadow: 0 0 22px rgba(255,190,60, calc(0.9 * var(--kn-glow))); }
.kn-pbtn--gold:hover, .kn-pbtn--gold:focus-visible { color: #3a1a02; box-shadow: 0 0 34px rgba(255,196,70, calc(1 * var(--kn-glow))), 0 0 68px rgba(255,150,30, calc(0.55 * var(--kn-glow))); }
.kn-pbtn--cyan { background: linear-gradient(135deg, #5fe0ff, var(--kn-cyan-dk)); color: #032738; box-shadow: 0 0 22px rgba(60,210,255, calc(0.9 * var(--kn-glow))); }
.kn-pbtn--cyan:hover, .kn-pbtn--cyan:focus-visible { color: #032738; box-shadow: 0 0 34px rgba(90,224,255, calc(1 * var(--kn-glow))), 0 0 68px rgba(20,160,240, calc(0.55 * var(--kn-glow))); }
.kn-pbtn--blue { background: linear-gradient(135deg, #7f9bff, #3f52e8); color: #fff; box-shadow: 0 0 22px rgba(110,90,255, calc(0.9 * var(--kn-glow))); }
.kn-pbtn--blue:hover, .kn-pbtn--blue:focus-visible { color: #fff; box-shadow: 0 0 34px rgba(140,130,255, calc(1 * var(--kn-glow))), 0 0 68px rgba(90,70,240, calc(0.55 * var(--kn-glow))); }
.kn-pbtn--right { margin-left: auto; margin-right: 0; }

/* --- Bottom row -------------------------------------------------- */
.kn-hero__bottom {
    position: relative;
    z-index: 2;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 2.15fr);
    gap: 1.1rem;
    margin-top: 1.5rem;
}
.kn-about { display: flex; flex-direction: column; }
.kn-about .kn-panel__title, .kn-gallery .kn-panel__title { justify-content: flex-start; font-size: 1.34rem; }
.kn-about__body { margin: 0 0 .9rem; font-size: 1.02rem; line-height: 1.65; color: rgba(255,255,255,.9); }
.kn-about .kn-pbtn { margin-top: auto; margin-left: auto; margin-right: 0; }

.kn-gallery__strip { display: grid; grid-template-columns: repeat(3, 1fr); gap: .7rem; }
.kn-gallery__item {
    display: block; overflow: hidden; border-radius: 8px;
    border: 1.5px solid rgba(255,205,110,.7);
    box-shadow: 0 0 18px rgba(255,180,60,.35), inset 0 0 24px rgba(120,50,210,.3);
    transition: box-shadow .28s ease, border-color .28s ease;
}
.kn-gallery__item:hover,
.kn-gallery__item:focus-visible {
    border-color: rgba(255,225,160,.95);
    box-shadow: 0 0 30px rgba(255,190,70, calc(0.85 * var(--kn-glow))),
                0 0 62px rgba(255,150,40, calc(0.4 * var(--kn-glow))),
                inset 0 0 24px rgba(120,50,210,.3);
}
.kn-gallery__item img { width: 100%; height: 124px; object-fit: cover; display: block; transition: transform .3s ease; }
.kn-gallery__item:hover img { transform: scale(1.06); }
.kn-gallery__links { display: grid; grid-template-columns: repeat(3, 1fr); gap: .6rem; margin-top: .9rem; }
.kn-gallery__links .kn-pbtn { width: 100%; margin: 0; padding: .68rem 1rem; font-size: .94rem; border-radius: 10px; }

/* --- Responsive -------------------------------------------------- */
@media (max-width: 900px) {
    .kn-hero__inner { grid-template-columns: 1fr; gap: 1.3rem; min-height: 0; }
    .kn-hero__bottom { grid-template-columns: 1fr; }
    .kn-about .kn-pbtn { margin-top: .6rem; }
}

/* Tablets. Without this band the layout stacked at 900px but the portrait
   kept its full desktop width until 600px, so on a ~840px screen the figure
   alone filled the viewport and pushed Celebrations and Upcoming Events below
   the fold. Shrink the figure, and use the width that IS there: the two rail
   panels sit side by side and the bottom row stays two-up. */
@media (min-width: 601px) and (max-width: 900px) {
    .kn-figure img { width: min(300px, 40vw); }
    .kn-figure--empty a { width: min(280px, 38vw); }
    .kn-rail { flex-direction: row; align-items: stretch; }
    .kn-rail > .kn-panel { flex: 1 1 0; min-width: 0; }
    .kn-hero__bottom { grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr); }
}

@media (max-width: 600px) {
    .kn-hero { margin-top: -1rem; padding: 1.6rem 1rem 1.4rem; }
    .kn-figure img { width: min(240px, 62vw); }
    .kn-figure--empty a { width: min(230px, 60vw); }
    .kn-btn { min-width: 0; flex: 1 1 44%; padding: .7rem 1rem; font-size: .95rem; }
    .kn-panel__title, .kn-about .kn-panel__title, .kn-gallery .kn-panel__title { font-size: 1.1rem; }
    .kn-about__body { font-size: .95rem; }
    .kn-gallery__item img { height: 86px; }
    .kn-gallery__links { grid-template-columns: 1fr; }
}
/* Colour and glow still change on hover under reduced-motion — only the
   movement is dropped, so the affordance survives. */
@media (prefers-reduced-motion: reduce) {
    .kn-btn:hover, .kn-pbtn:hover, .kn-panel:hover,
    .kn-gallery__item:hover img { transform: none; }
}

/* An uploaded backdrop replaces the drawn SVG scene entirely. */
.kn-hero__sky--image {
    background-image: none;           /* overridden inline by the upload */
    background-position: center center;
    background-size: cover;
    background-repeat: no-repeat;
}

/* --- Entrance -------------------------------------------------------
   Hero content settles in on load rather than appearing all at once. Pure
   CSS, no JS, so it cannot arrive late or leave content stuck invisible if a
   script fails: `both` fill-mode holds the final state, and the
   reduced-motion block below resets opacity outright.

   The figure fades only — no translate. A transform on .kn-figure would make
   it a containing block mid-animation and drag its z-index:-1 halo and floor
   pool into its own stacking context, which flickers. */
@keyframes kn-rise {
    from { opacity: 0; transform: translateY(14px); }
    to   { opacity: 1; transform: none; }
}
@keyframes kn-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}
.kn-figure  { animation: kn-fade 0.85s ease both;                    animation-delay: 0.05s; }
.kn-title   { animation: kn-rise 0.7s cubic-bezier(.22,.7,.3,1) both; animation-delay: 0.20s; }
.kn-subtitle{ animation: kn-rise 0.7s cubic-bezier(.22,.7,.3,1) both; animation-delay: 0.30s; }
.kn-actions { animation: kn-rise 0.7s cubic-bezier(.22,.7,.3,1) both; animation-delay: 0.40s; }
.kn-rail > *:nth-child(1) { animation: kn-rise 0.7s cubic-bezier(.22,.7,.3,1) both; animation-delay: 0.34s; }
.kn-rail > *:nth-child(2) { animation: kn-rise 0.7s cubic-bezier(.22,.7,.3,1) both; animation-delay: 0.44s; }
.kn-hero__bottom > *      { animation: kn-rise 0.7s cubic-bezier(.22,.7,.3,1) both; animation-delay: 0.52s; }

@media (prefers-reduced-motion: reduce) {
    .kn-figure, .kn-title, .kn-subtitle, .kn-actions,
    .kn-rail > *, .kn-hero__bottom > * {
        animation: none;
        opacity: 1;
        transform: none;
    }
}
