/* ============================================================================
   Thrive PUBLIC SITE — shared component system (student portal + marketing).
   Ported from the front-end mockup. Brand colours (--primary, --primary-2,
   --accent, --secondary) are injected per-org at runtime by the site layout
   (App\Support\Theme::cssVars); this file owns structure + the two layout modes:
     <body data-mode="portal">   → dark-chrome, app-like student portal
     <body data-mode="brochure"> → light marketing "business card" + functions
   ============================================================================ */

:root {
    --bg: #f4f5f7;
    --surface: #ffffff;
    --surface-2: #f0f1f4;
    --text: #14161c;
    --text-soft: #5b6472;
    --on-primary: #ffffff;
    --border: rgba(0, 0, 0, .08);
    --radius: 16px;
    --shadow: 0 10px 30px rgba(0, 0, 0, .08);
    --shadow-lg: 0 24px 60px rgba(0, 0, 0, .18);
    --maxw: 1180px;
    /* Colour-emoji fallback so emoji render as glyphs, not tofu boxes, everywhere on the public site. */
    --emoji: "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji", "Twemoji Mozilla", "EmojiOne Color", "Android Emoji";
    --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, Helvetica, Arial, sans-serif, var(--emoji);
}

/* ── Dark theme ──────────────────────────────────────────────────────────────
   Applied via <html data-theme="dark"> (auto by time of day, or the manual
   toggle in the top bar). Overrides both the base vars and the per-mode chrome
   so content + topbar/footer all go dark. */
html[data-theme="dark"],
html[data-theme="dark"] [data-mode="portal"],
html[data-theme="dark"] [data-mode="brochure"] {
    --bg: #0c0d12;
    --surface: #15161d;
    --surface-2: #1c1e27;
    --text: #e7e9ee;
    --text-soft: #9aa1b0;
    --on-primary: #ffffff;
    --border: rgba(255, 255, 255, .10);
    --shadow: 0 10px 30px rgba(0, 0, 0, .5);
    --shadow-lg: 0 24px 60px rgba(0, 0, 0, .7);
    --topbar-bg: #0a0a10; --topbar-fg: #fff; --topbar-border: rgba(255, 255, 255, .10); --topbar-hover: rgba(255, 255, 255, .12);
    --ticker-bg: #161620; --band-bg: #0a0a10; --footer-bg: #0a0a10; --tabbar-bg: #14141c;
}
html[data-theme="dark"] body { background: var(--bg); }
.theme-toggle { width: 32px; height: 32px; border-radius: 50%; border: 1px solid var(--topbar-border, rgba(0,0,0,.12)); background: transparent; color: inherit; cursor: pointer; font-size: 15px; display: inline-grid; place-items: center; transition: background .15s; }
.theme-toggle:hover { background: var(--topbar-hover, rgba(0,0,0,.06)); }

/* ── Layout modes ──────────────────────────────────────────────────────────── */
[data-mode="portal"] {
    --bg: #f4f5f7; --surface: #fff; --surface-2: #f0f1f4; --text: #14161c; --text-soft: #5b6472;
    --topbar-bg: #0c0c12; --topbar-fg: #fff; --topbar-border: rgba(255,255,255,.10); --topbar-hover: rgba(255,255,255,.12);
    --ticker-bg: #1b1b22; --band-bg: #0c0c12; --footer-bg: #0c0c12; --tabbar-bg: #15151c;
}
[data-mode="brochure"] {
    --bg: #f6f8fc; --surface: #fff; --surface-2: #eef2f9; --text: #0f172a; --text-soft: #5b6576;
    --topbar-bg: rgba(255,255,255,.92); --topbar-fg: #0f172a; --topbar-border: rgba(0,0,0,.08); --topbar-hover: #eef2ff;
    --ticker-bg: var(--primary-2); --band-bg: #0f172a; --footer-bg: #0f172a; --tabbar-bg: #15151c;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
/* A page builder lets staff drop any block anywhere, so ONE over-wide element must not be able
   to make the whole document scroll sideways. `clip` rather than `hidden`: it contains the
   overflow without creating a scroll container, so position:sticky and in-page anchor links
   keep working. This is a guard, not a licence — an element that overflows is still a bug. */
html, body { overflow-x: clip; }
body { font-family: var(--font); background: var(--bg); color: var(--text); line-height: 1.45; -webkit-font-smoothing: antialiased; }
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 20px; }
.muted { color: var(--text-soft); }
.center { text-align: center; }

/* ── Buttons ─────────────────────────────────────────────────────────────── */
.btn { display: inline-flex; align-items: center; gap: 8px; padding: 12px 22px; border-radius: 999px; font-weight: 700; font-size: 14px; cursor: pointer; border: none; transition: transform .12s, filter .15s, background .15s; white-space: nowrap; }
.btn:active { transform: scale(.97); }
.btn[disabled] { opacity: .55; cursor: not-allowed; }
.btn-primary { background: var(--primary); color: var(--on-primary); }
.btn-primary:hover { filter: brightness(1.08); }
.btn-ghost { background: transparent; color: var(--text); border: 1px solid var(--border); }
.btn-light { background: rgba(255, 255, 255, .14); color: #fff; backdrop-filter: blur(6px); border: 1px solid rgba(255, 255, 255, .25); }
.btn-outline { background: transparent; color: var(--primary); border: 1.5px solid var(--primary); }
.btn-outline:hover { background: var(--primary); color: var(--on-primary); }
.btn-block { width: 100%; justify-content: center; }
.btn-sm { padding: 8px 16px; font-size: 13px; }
[data-mode="portal"] .topbar .btn-ghost { color: #fff; border-color: rgba(255,255,255,.25); }

.pill { display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px; border-radius: 999px; font-size: 12px; font-weight: 700; background: var(--surface-2); color: var(--text-soft); }
.pill-accent { background: var(--accent); color: #1c1407; }
.pill-live { background: #16a34a; color: #fff; }

/* ── Top bar ─────────────────────────────────────────────────────────────── */
.topbar { position: sticky; top: 0; z-index: 50; background: var(--topbar-bg, var(--surface)); border-bottom: 1px solid var(--topbar-border, var(--border)); backdrop-filter: blur(12px); }
.topbar .wrap { display: flex; align-items: center; gap: 22px; height: 64px; }
/* Custom (builder-designed) headers: the bar supplies surface + vertical padding;
   the 64px flex-bar rule above is for the legacy topbar only and would crush /
   overflow builder containers (which reuse .wrap for boxed width). */
.topbar--custom { padding: 10px 0; }
.topbar--custom .wrap { display: block; height: auto; }
.brand { display: flex; align-items: center; gap: 10px; font-weight: 900; letter-spacing: -.5px; font-size: 18px; color: var(--topbar-fg, var(--text)); text-transform: uppercase; }
.brand .mark { width: 30px; height: 30px; border-radius: 9px; background: linear-gradient(135deg, var(--primary), var(--primary-2)); }
.brand img { height: 34px; width: auto; display: block; }
.brand small { font-weight: 600; opacity: .6; font-size: 11px; letter-spacing: 2px; }
.nav { display: flex; gap: 4px; margin-left: 8px; }
.nav a { padding: 8px 14px; border-radius: 8px; font-size: 14px; font-weight: 600; color: var(--topbar-fg, var(--text)); opacity: .82; }
.nav a:hover, .nav a.active { opacity: 1; background: var(--topbar-hover, var(--surface-2)); }
.nav-burger { display: none; align-items: center; justify-content: center; width: 40px; height: 40px; border: 0; background: transparent; cursor: pointer; font-size: 22px; line-height: 1; color: var(--topbar-fg, var(--text)); border-radius: 9px; user-select: none; }
.nav-burger:hover { background: var(--topbar-hover, var(--surface-2)); }
.topbar .spacer { flex: 1; }
.topbar .actions { display: flex; align-items: center; gap: 10px; }
.avatar { width: 34px; height: 34px; border-radius: 50%; background: linear-gradient(135deg, var(--primary), var(--primary-2)); color: #fff; display: grid; place-items: center; font-weight: 800; font-size: 13px; }
/* Signed-in greeting ("Good afternoon, Ohav") + its hub avatar in the top bar. */
.topbar-greet { font-weight: 800; font-size: 14px; color: var(--topbar-fg, var(--text)); text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 40vw; }
.topbar-greet:hover { color: var(--primary); }
.topbar-ava { width: 32px; height: 32px; border-radius: 50%; background: linear-gradient(135deg, var(--primary), var(--primary-2)); color: #fff; display: inline-grid; place-items: center; font-weight: 800; font-size: 12px; text-decoration: none; flex: none; }
[data-mode="portal"] .topbar .topbar-greet { color: #fff; }

/* ── Live ticker ─────────────────────────────────────────────────────────── */
.ticker { background: var(--ticker-bg, #111); color: #fff; padding: 10px 0; overflow: hidden; white-space: nowrap; font-size: 13px; }
.ticker .wrap { display: flex; gap: 26px; align-items: center; }
.ticker .item { opacity: .85; }
.ticker .item b { color: var(--accent); }

/* ── Stats ───────────────────────────────────────────────────────────────── */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; padding: 36px 0; }
.stat { text-align: center; }
.stat .n { font-size: clamp(28px, 4vw, 46px); font-weight: 900; color: var(--primary); letter-spacing: -1px; }
.stat .l { font-size: 13px; color: var(--text-soft); font-weight: 600; text-transform: uppercase; letter-spacing: .6px; }

/* ── Sections ────────────────────────────────────────────────────────────── */
section { padding: 18px 0; }
/* Builder blocks control their own spacing via the editor's margin/padding
   settings — the legacy section padding above must not add hidden, uncloseable
   gaps (e.g. above a hero). Every builder block renders inside .pb-block. */
.pb-block > section { padding-top: 0; padding-bottom: 0; }
.section-head { display: flex; align-items: center; justify-content: space-between; margin: 28px 0 16px; }
.section-head h2 { font-size: 22px; font-weight: 900; letter-spacing: -.4px; text-transform: uppercase; color: var(--primary); }
.section-head a { font-size: 13px; font-weight: 700; color: var(--text-soft); }
.band { background: var(--band-bg, #0c0c12); color: #fff; padding: 40px 0; }
.band-split { display: grid; grid-template-columns: 1fr 1fr; gap: 30px; align-items: center; }

/* Event flyer — a designed image standing in for the text description. */
.event-flyer { display: block; width: 100%; height: auto; border-radius: 14px; box-shadow: 0 10px 30px rgba(0,0,0,.16); }

/* ── Program / featured hero banner ──────────────────────────────────────── */
/* Hero layout is driven by custom properties so the page editor can set height, text
   position and line spacing per block. Every fallback is the value that was hardcoded
   here before, so a hero with nothing configured renders exactly as it always did. */
.hero-program { position: relative; min-height: var(--hero-h, 460px); display: flex; align-items: var(--hero-y, flex-end); justify-content: var(--hero-jx, flex-start); color: #fff; overflow: hidden; }
.hero-program .bgimg { position: absolute; inset: 0; background-size: cover; background-position: center; }
.hero-program .scrim { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(8,8,14,.35) 0%, rgba(8,8,14,.55) 45%, rgba(8,8,14,.92) 100%); }
.hero-program .wrap { position: relative; z-index: 2; padding: var(--hero-pt, 48px) 20px var(--hero-pb, 32px); text-align: var(--hero-x, left); }
/* Opt-in extra breathing room between the eyebrow, headline, subtext and buttons. At the
   default 0 the elements' own margins do all the spacing, exactly as before. */
.hero-program .wrap > * + * { margin-top: var(--hero-gap, 0); }
.hero-cta { justify-content: var(--hero-cta-x, flex-start); }
.hero-program .eyebrow { display: inline-flex; align-items: center; gap: 8px; background: var(--primary); color: #fff; font-weight: 800; font-size: 12px; letter-spacing: 1px; text-transform: uppercase; padding: 6px 14px; border-radius: 999px; }
.hero-program h1 { font-size: clamp(40px, 7vw, 80px); font-weight: 900; letter-spacing: -2px; line-height: var(--hero-lh, .95); margin: 16px 0 10px; }
/* Optional accent line (hero `headline_accent`) — the org's own brand colour.
   A flat `color-mix(--primary 45%, #fff)` kept it legible on a dark photo but washed
   EVERY brand out to the same pale pink, so the one word an org most wants in its own
   colour was the one word that wasn't. `--primary-lift` is the brand itself whenever
   it already clears large-text contrast on the scrim (a mid crimson does, at ~3.4:1),
   lifted per-brand only when it genuinely doesn't. @see App\Support\Theme::onDark */
.hero-program h1 em { font-style: normal; color: var(--primary-lift, var(--primary)); }
/* margin-inline lets a centred hero centre its subtext rather than leaving a 560px
   column hugging the left edge. */
.hero-program .sub { font-size: 17px; opacity: .92; max-width: 560px; margin-inline: var(--hero-sub-mi, 0); }
.hero-program .meta { display: flex; gap: 22px; flex-wrap: wrap; margin: 18px 0 22px; font-size: 14px; opacity: .9; }
.hero-program .meta span { display: block; opacity: .7; font-size: 12px; text-transform: uppercase; letter-spacing: .5px; }
.hero-program .meta b { display: block; font-size: 18px; }
.hero-cta { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }
/* Instagram follow. Glass over the photo rather than a third solid button, so it reads
   as a secondary invitation and never competes with the primary action. Instagram's own
   gradient belongs on hover, not sitting at full strength over a hero photo. */
.hero-ig {
    display: inline-flex; align-items: center; gap: 8px;
    background: rgba(255, 255, 255, .13); color: #fff;
    border: 1px solid rgba(255, 255, 255, .35);
    -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
    transition: background .18s ease, border-color .18s ease, transform .18s ease;
}
.hero-ig svg { flex: none; }
.hero-ig:hover {
    background: linear-gradient(45deg, #f09433, #dc2743 45%, #bc1888);
    border-color: transparent; color: #fff; transform: translateY(-1px);
}
/* Phones: the buttons already wrap, so the follow link takes the full width under them
   and stays a comfortable tap target instead of a sliver beside a wrapped button. */
@media (max-width: 560px) {
    .hero-cta { gap: 10px; }
    .hero-ig { width: 100%; justify-content: center; }
}
/* Tighten the seam directly under a full-bleed hero — kills the empty white band
   between the banner and the first content section (stats/events/etc.). Targets
   ONLY the element immediately after the hero, so all other section rhythm is
   untouched (covers bare <section>, the .stats block, or a page-builder wrapper). */
.hero-program + section,
.hero-program + .stats,

/* ── Card grid ───────────────────────────────────────────────────────────── */
.cards-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 18px; }
/* Account page: tickets beside your details on a laptop, stacked on a phone. This was
   an inline `grid-template-columns: 1.5fr 1fr` with no media query, so the details card
   simply ran off the right edge of the screen and the tickets column was crushed. An
   inline style can't be media-queried, which is why it needs to be a class. */
.acct-grid { display: grid; grid-template-columns: 1.5fr 1fr; gap: 24px; align-items: start; }
@media (max-width: 860px) { .acct-grid { grid-template-columns: 1fr; gap: 20px; } }
.ticket-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 20px; }
.row-scroll { display: flex; gap: 16px; overflow-x: auto; padding-bottom: 8px; scrollbar-width: thin; }

/* Horizontal scroll-snap feed (events / trips / programs) — like the plugin. Each
   card keeps a roomy width so tickets aren't squooshed. */
/* Generous vertical padding so card box-shadows aren't clipped by the scroller's
   overflow (that clip was the "straight line" cutting across the grid). */
.feed { display: flex; gap: 18px; overflow-x: auto; scroll-snap-type: x mandatory; padding: 14px 4px 26px; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.feed::-webkit-scrollbar { display: none; }
.feed > * { flex: 0 0 auto; scroll-snap-align: start; }
/* Widths capped tighter on mobile (vw) so the NEXT card always peeks in — the
   reader can see there's more to scroll. */
.feed > .olami-ticket { width: min(80vw, 460px); }
.feed > .obp-card { width: min(81vw, 360px); }
.feed > .olami-prog-card-v2 { width: min(80vw, 380px); }
/* On a laptop the rail is the wrong instinct: a 1200px container fits ~2.5 tickets
   and the rest hide behind a sideways scroll desktop visitors don't perform (on the
   homepage that buried everything past the third event). Wrap instead of scroll, so
   the cards flow onto rows.
   Deliberately NOT a grid with `width:auto`: that discards the widths above and
   stretched the 360px boarding pass to ~810px, blowing out its passport fields.
   Wrapping keeps every card at exactly its designed width. */
@media (min-width: 900px) {
    .feed { flex-wrap: wrap; overflow: visible; justify-content: flex-start; padding: 14px 0 26px; }
    .feed > * { scroll-snap-align: none; }
}

/* `is-rail` — an explicit "scroll sideways, never wrap" for sections that ARE a deck you
   browse (trips), opting out of the wrap above. It wins without !important: .feed.is-rail
   is 0,2,0 against .feed's 0,1,0, and a media query adds no specificity.
   The wrap rule exists because a sideways scroll nobody performs hides everything past
   card three — so this variant SHOWS its scrollbar on desktop rather than hiding it, and
   the card widths already let the next one peek in. That's the missing affordance, not a
   reason to give up the rail. */
.feed.is-rail { flex-wrap: nowrap; overflow-x: auto; justify-content: flex-start; }
.feed.is-rail > * { scroll-snap-align: start; }
@media (min-width: 900px) {
    /* TWO rows deep, scrolling sideways. One long line wastes the height a desktop
       has and makes you scroll twice as far for the same events; two rows shows
       roughly six at a glance and still says "there is more" by cutting the next
       column at the edge.

       grid-auto-flow: column fills DOWN then across, so the reading order stays
       chronological down each column. max-content keeps every card at the exact
       width it was designed for — the same reason the wrap rule above refuses to
       use a stretching grid. Phones keep the single line: two rows of a 390px
       screen is one row of half-cards. */
    .feed.is-rail {
        display: grid;
        grid-auto-flow: column;
        grid-template-rows: repeat(2, auto);
        grid-auto-columns: max-content;
        align-items: start;
        padding: 14px 4px 22px;
        scrollbar-width: thin; scrollbar-color: rgba(128,128,128,.45) transparent;
    }
    .feed.is-rail::-webkit-scrollbar { display: block; height: 9px; }
    .feed.is-rail::-webkit-scrollbar-thumb { background: rgba(128,128,128,.45); border-radius: 9px; }
    .feed.is-rail::-webkit-scrollbar-track { background: transparent; }
    /* Snap per COLUMN, not per card: snapping to the second card of a column would
       scroll a row-mate off the screen. */
    .feed.is-rail > * { scroll-snap-align: none; }
    .feed.is-rail > :nth-child(odd) { scroll-snap-align: start; }
    /* An odd count leaves the last column half-empty; the endcap tile fills it. */
    .feed.is-rail > .feed-endcap { align-self: stretch; }
}

/* ── Feature cards (.fc-*) — "what we run" photo cards ────────────────────────
   Standing description in the body, this year's actual names in the footnote, so a
   yearly refresh is a few short edits and no claim goes stale.

   Layout is a real grid so ANY card can be wide, tall or a 2×2 feature — not just
   the first one. Spans collapse to 1×1 below 900px: two columns of a 390px phone is
   not a layout, it's a mistake. */
.fc-sec { margin-top: 4px; }
.fc-grid { display: grid; grid-template-columns: 1fr; gap: 14px; grid-auto-flow: dense; }
.fc-card { background: var(--surface); border: 1px solid var(--border); border-radius: 16px; overflow: hidden;
    display: flex; flex-direction: column; box-shadow: 0 2px 10px rgba(0,0,0,.05); }
.fc-im { height: 150px; flex: none; background-size: cover; background-position: center; background-color: var(--primary);
    transition: transform .45s cubic-bezier(.22,.61,.36,1); }
.fc-bd { padding: 17px 18px 18px; flex: 1; display: flex; flex-direction: column; }
.fc-k { font-size: 10px; font-weight: 900; letter-spacing: 1.4px; text-transform: uppercase; color: var(--primary); margin-bottom: 8px; }
.fc-card h3 { margin: 0 0 9px; font-size: 21px; font-weight: 900; letter-spacing: -.03em; }
.fc-card p { margin: 0; font-size: 14.5px; color: var(--text-soft); line-height: 1.55; }
/* margin-top:auto pins the footnote to the bottom, so cards of unequal body length
   still line their footnotes up across a row. */
.fc-fn { margin-top: auto !important; padding-top: 12px; border-top: 1px solid var(--border); font-size: 13px !important; line-height: 1.55; }
.fc-fn b { color: var(--text); font-weight: 800; }

/* ── Hover motion (set per block in the builder) ──────────────────────────────
   Every option is transform/filter only, so it animates on the compositor and can
   never reflow the grid. Honoured only where a pointer actually hovers — a touch
   device would otherwise stick in the hover state after a tap. */
@media (hover: hover) and (min-width: 900px) {
    .fc-h-lift .fc-card, .fc-h-lift-zoom .fc-card, .fc-h-tilt .fc-card, .fc-h-reveal .fc-card {
        transition: transform .28s cubic-bezier(.22,.61,.36,1), box-shadow .28s; }
    .fc-h-lift .fc-card:hover, .fc-h-lift-zoom .fc-card:hover {
        transform: translateY(-6px); box-shadow: 0 16px 34px rgba(0,0,0,.14); }
    .fc-h-zoom .fc-card:hover .fc-im, .fc-h-lift-zoom .fc-card:hover .fc-im { transform: scale(1.07); }
    .fc-h-tilt .fc-card:hover { transform: perspective(900px) rotateX(2deg) rotateY(-2deg) translateY(-4px);
        box-shadow: 0 18px 38px rgba(0,0,0,.16); }
    /* Reveal: the footnote is the "this year" line, so it can start hidden and slide in. */
    .fc-h-reveal .fc-fn { max-height: 0; opacity: 0; padding-top: 0; border-top-color: transparent; overflow: hidden;
        transition: max-height .3s ease, opacity .25s ease, padding-top .3s ease; }
    .fc-h-reveal .fc-card:hover { transform: translateY(-4px); box-shadow: 0 14px 30px rgba(0,0,0,.13); }
    .fc-h-reveal .fc-card:hover .fc-fn { max-height: 140px; opacity: 1; padding-top: 12px; border-top-color: var(--border); }
}
@media (prefers-reduced-motion: reduce) {
    .fc-card, .fc-im, .fc-fn { transition: none !important; }
    .fc-card:hover { transform: none !important; }
    .fc-card:hover .fc-im { transform: none !important; }
    /* Never hide content from someone who asked for less motion. */
    .fc-h-reveal .fc-fn { max-height: none; opacity: 1; padding-top: 12px; border-top-color: var(--border); }
}

@media (min-width: 900px) {
    .fc-grid { gap: 18px; }
    .fc-c2 { grid-template-columns: repeat(2, 1fr); }
    .fc-c3 { grid-template-columns: repeat(3, 1fr); }
    .fc-c4 { grid-template-columns: repeat(4, 1fr); }
    .fc-im { height: 172px; }
    .fc-card h3 { font-size: 23px; }

    /* Spans. grid-auto-flow:dense backfills the holes a tall card leaves behind. */
    .fc-s2-1 { grid-column: span 2; }
    .fc-s1-2 { grid-row: span 2; }
    .fc-s2-2 { grid-column: span 2; grid-row: span 2; }
    /* A card given extra height should USE it, not leave a short photo and white space. */
    .fc-s1-2 .fc-im, .fc-s2-2 .fc-im { height: 300px; }
    .fc-s2-1 .fc-im { height: 228px; }
    /* Never let a span exceed the track count, or the card overflows the container. */
    .fc-c2 .fc-s2-1, .fc-c2 .fc-s2-2 { grid-column: span 2; }
}

/* ── Event ticket (.olami-ticket) — faithful two-layer tear-off ticket ─────────
   Lifted from the OLAMI plugin (events.css). Two state layers (.ot-state-initial
   / .ot-state-success) sit in the same grid cell and are swapped via clip-path;
   the stub flies off on .is-ripped. Themed by the --tk-* design tokens. */
.olami-ticket { position: relative; height: 220px; border-radius: 12px; box-shadow: var(--shadow); background: var(--surface); transition: transform .2s cubic-bezier(.25,.46,.45,.94), box-shadow .2s; }
.olami-ticket:hover { transform: translateY(-4px); box-shadow: 0 20px 35px rgba(0,0,0,.15); }
.olami-ticket-inner { display: flex; width: 100%; height: 100%; border-radius: 12px; overflow: hidden; transform: translateZ(0); }
/* The rip lets the stub fly off the card, so the inner box has to stop clipping —
   but `overflow: hidden` is also what rounds the corners, so the card squares off
   the moment it tears. Keep the radius on the panel itself, and never unclip at all
   when the stub isn't going anywhere (a pending ticket keeps its stub). */
.olami-ticket.is-ripped .olami-ticket-inner { overflow: visible; }
.olami-ticket.is-ripped.is-pending .olami-ticket-inner, .olami-ticket.is-ripped.is-rejected .olami-ticket-inner { overflow: hidden; }
.olami-ticket.is-ripped .olami-ticket-info { border-radius: 12px 0 0 12px; }

.olami-ticket-info { flex: 1; position: relative; display: grid; grid-template-columns: 1fr; grid-template-rows: 1fr; padding: 16px 14px 14px 14px; border-right: 2px dashed rgba(255,255,255,.35); background: linear-gradient(135deg, var(--tk-body-1), var(--tk-body-2)); background-size: cover; background-position: center; z-index: 2;
    -webkit-mask-image: radial-gradient(circle at right center, transparent 10px, #000 10.5px); mask-image: radial-gradient(circle at right center, transparent 10px, #000 10.5px); }
.ot-custom-overlay { position: absolute; inset: 0; grid-area: 1/1; background: linear-gradient(135deg, rgba(0,0,0,1) 0%, rgba(0,0,0,.5) 100%); opacity: .12; z-index: 1; pointer-events: none; }
.olami-ticket-info.has-bg-img .ot-custom-overlay { opacity: var(--tk-overlay); }

/* The two stacked state layers */
.ot-state-initial, .ot-state-success { grid-area: 1/1; position: relative; z-index: 2; display: flex; flex-direction: column; min-height: 0; color: var(--tk-text); transition: clip-path .8s cubic-bezier(.77,0,.175,1); }
.ot-state-initial { clip-path: inset(0 0 0 0); }
.ot-state-success { clip-path: inset(0 0 0 100%); align-items: center; justify-content: center; text-align: center; }
.olami-ticket.is-ripped .ot-state-initial { clip-path: inset(0 100% 0 0); }
.olami-ticket.is-ripped .ot-state-success { clip-path: inset(0 0 0 0); z-index: 6; }

.ot-content-centered { display: flex; flex-direction: column; justify-content: center; flex: 1 1 auto; min-height: 0; overflow: hidden; }
.ot-date-line { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .3px; opacity: .9; margin-bottom: 3px; }
.ot-title-main { font-size: 26px; font-weight: 900; line-height: 1; text-transform: uppercase; letter-spacing: -.5px; }
.ot-location-line { font-size: 13px; font-weight: 500; opacity: .9; margin-top: 6px; }
.ot-desc-line { font-size: 13px; margin-top: 8px; opacity: .85; line-height: 1.4; flex: 1 1 auto; min-height: 0; overflow-y: auto; scrollbar-width: none; }
.ot-desc-line::-webkit-scrollbar { display: none; }

/* Options (radio pills, single-row scroll + nudge guard) */
.ot-options-section { margin-top: auto; padding-top: 10px; flex: 0 0 auto; }
.ot-q-text { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .3px; opacity: .8; margin-bottom: 6px; }
.ot-pills-row { display: flex; flex-wrap: nowrap; gap: 6px; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none;
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 18px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 18px), transparent); }
.ot-pills-row::-webkit-scrollbar { display: none; }
.ot-pill { display: inline-flex; align-items: center; cursor: pointer; flex: 0 0 auto; scroll-snap-align: start; position: relative; }
.ot-pill input { position: absolute; opacity: 0; pointer-events: none; width: 0; height: 0; }
.ot-pill span { display: inline-block; padding: 7px 14px; font-size: 13px; font-weight: 600; background: rgba(0,0,0,.28); border-radius: 25px; color: var(--tk-text); white-space: nowrap; transition: all .15s ease; }
.ot-pill:hover span { background: rgba(0,0,0,.38); }
.ot-pill input:checked + span { background: rgba(255,255,255,.95); color: #14161c; box-shadow: 0 2px 8px rgba(0,0,0,.2); }
.ot-options-section.ot-nudge .ot-pills-row { animation: otPillNudge .5s ease; }
.ot-options-section.ot-nudge .ot-pill span { background: rgba(255,255,255,.35); box-shadow: 0 0 0 2px rgba(255,255,255,.5); }
@keyframes otPillNudge { 0%,100% { transform: translateX(0); } 20% { transform: translateX(-6px); } 40% { transform: translateX(5px); } 60% { transform: translateX(-3px); } 80% { transform: translateX(2px); } }

.ot-success-title { font-size: 24px; font-weight: 900; text-transform: uppercase; letter-spacing: -.5px; }
.ot-success-msg { font-size: 13px; opacity: .85; margin-top: 6px; max-width: 90%; }

/* The tear-off stub */
.olami-ticket-stub { width: 55px; flex: 0 0 55px; display: flex; align-items: center; justify-content: center; color: #fff; background: var(--tk-stub);
    -webkit-mask-image: radial-gradient(circle at left center, transparent 10px, #000 10.5px); mask-image: radial-gradient(circle at left center, transparent 10px, #000 10.5px); }
.olami-ticket-stub[data-stub] { cursor: pointer; }
.olami-stub-text { writing-mode: vertical-rl; text-orientation: mixed; font-weight: 800; letter-spacing: 2px; text-transform: uppercase; font-size: 13px; }
.olami-ticket.is-ripped:not(.is-pending) .olami-ticket-stub { transition: transform .8s cubic-bezier(.55,.055,.675,.19), opacity .8s ease-in; transform: translate(80px, -400px) rotate(25deg); opacity: 0; pointer-events: none; }
.olami-ticket.is-rejected { filter: saturate(.7); }
.olami-ticket.is-rejected .ot-title-main, .olami-ticket.is-rejected .ot-success-title { color: #ff6b6b; }

/* Unavailable option pills — a full host is greyed + not selectable; waitlist is muted. */
.ot-pill.is-full { cursor: not-allowed; }
.ot-pill.is-full span { opacity: .45; background: rgba(0,0,0,.28); }
.ot-pill.is-full:hover span { background: rgba(0,0,0,.28); }
.ot-pill.is-waitlist span { font-style: italic; opacity: .8; }

/* Stub invites a tear: an upward bob on hover, on top of the whole-card lift. */
.olami-ticket-stub[data-stub] { transition: filter .2s ease; }
.olami-ticket-stub[data-stub]:hover { filter: brightness(1.12); }
.olami-ticket-stub[data-stub]:hover .olami-stub-text { animation: ot-stub-bob .9s ease-in-out infinite; }
@keyframes ot-stub-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-5px); } }

/* ── Trip boarding pass (.obp-card) — faithful vertical "boarding pass" ─────── */
.obp-card { position: relative; min-height: 500px; background: var(--surface); color: var(--text); border-radius: 16px; box-shadow: 0 15px 35px rgba(0,0,0,.25); border: 1px solid rgba(0,0,0,.05); display: flex; flex-direction: column; overflow: hidden; transition: transform .2s, box-shadow .2s; }
.obp-card:hover { transform: translateY(-8px); box-shadow: 0 20px 40px rgba(0,0,0,.3); }
.obp-top { flex: 0 0 280px; position: relative; padding: 25px; display: flex; flex-direction: column; background: linear-gradient(135deg, var(--bp-bg-1), var(--bp-bg-2)); background-size: cover; background-position: center; }
.obp-top::after { content: ''; position: absolute; inset: 0; background: rgba(0,0,0,.70); z-index: 0; }
.obp-badge { position: absolute; top: 25px; right: 25px; z-index: 2; background: var(--bp-accent); color: #1c1407; padding: 4px 8px; border-radius: 4px; font-size: 9px; font-weight: 800; letter-spacing: 1px; box-shadow: 0 2px 10px rgba(0,0,0,.2); }
.obp-title { margin-top: auto; position: relative; z-index: 2; color: var(--bp-text); font-size: 28px; font-weight: 900; line-height: .95; letter-spacing: -1px; text-transform: uppercase; text-shadow: 0 2px 15px rgba(0,0,0,.5); }
.obp-input-stack { position: relative; z-index: 2; display: flex; flex-direction: column; gap: 8px; margin-top: 22px; }
.obp-grid-2 { display: grid; grid-template-columns: 1.5fr 1fr; gap: 10px; align-items: end; }
/* Captioned field (passport expiry date needs a visible label — a type=date input
   can't carry placeholder text, so the bare mm/dd/yyyy read as an unlabeled date). */
.obp-field { display: flex; flex-direction: column; gap: 3px; }
.obp-field-cap { text-transform: uppercase; font-size: 9px; font-weight: 700; letter-spacing: 1px; color: rgba(255,255,255,.7); padding-left: 2px; }
.obp-clean-input { width: 100%; box-sizing: border-box; background: rgba(0,0,0,.5); color: #fff; border: 1px solid rgba(255,255,255,.5); border-radius: 6px; padding: 10px; font-weight: 600; font-size: 14px; outline: none; transition: all .2s; }
.obp-clean-input::placeholder { color: rgba(255,255,255,.7); text-transform: uppercase; font-size: 10px; font-weight: 700; letter-spacing: 1px; }
.obp-clean-input:focus { background: rgba(0,0,0,.8); border-color: #fff; }
/* Required passport fields: highlight + shake the stack when a trip register is attempted empty. */
.obp-clean-input.pp-missing { border-color: #ff5a7a; box-shadow: 0 0 0 2px rgba(255,90,122,.55); }
.obp-input-stack.ot-nudge { animation: otPillNudge .5s ease; }
.obp-content { flex-grow: 1; padding: 14px; display: flex; flex-direction: column; justify-content: space-between; position: relative; background: var(--surface); }
.obp-content::before { content: ''; position: absolute; top: -1px; left: 10px; right: 10px; border-top: 2px dashed rgba(0,0,0,.12); z-index: 10; }
.obp-meta-row { display: flex; justify-content: space-between; margin-bottom: 5px; }
.obp-label { font-size: 9px; font-weight: 700; color: var(--text-soft); letter-spacing: .5px; text-transform: uppercase; margin-bottom: 3px; display: block; }
.obp-val { font-size: 14px; font-weight: 800; color: var(--text); }
.obp-desc { font-size: 13px; line-height: 1.5; color: var(--text); margin: 6px 0 8px; max-height: 92px; overflow-y: auto; flex: 0 1 auto; }
.obp-options-section { margin: 8px 0 4px; }
.obp-pills-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.obp-pill { display: inline-flex; align-items: center; cursor: pointer; }
.obp-pill input { display: none; }
.obp-pill span { display: inline-block; padding: 8px 16px; border: 1.5px solid var(--border); border-radius: 20px; font-size: 13px; font-weight: 600; color: var(--text); background: var(--surface); transition: all .15s; }
.obp-pill input:checked + span { border-color: var(--primary); background: var(--primary); color: #fff; }
.obp-pill:hover span { border-color: var(--primary); }
.obp-options-section.ot-nudge .obp-pills-row { animation: otPillNudge .5s ease; }
.obp-options-section.ot-nudge .obp-pill span { border-color: var(--primary); box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary) 45%, transparent); }
.obp-btn { width: 100%; padding: 15px; border-radius: 10px; border: none; font-weight: 800; text-transform: uppercase; font-size: 13px; cursor: pointer; letter-spacing: 1px; text-align: center; margin-top: auto; }
.obp-btn.btn-action { background: var(--bp-stub); color: #fff; box-shadow: 0 8px 20px rgba(0,0,0,.15); transition: transform .1s; }
.obp-btn.btn-action:active { transform: scale(.98); }
.obp-btn.btn-booked { background: #16a34a; color: #fff; cursor: default; }
.obp-btn.btn-pending { background: var(--tk-stub-pending); color: #fff; cursor: default; }
.obp-btn[disabled] { opacity: .9; cursor: default; }
/* Reward-trip gate — the card is public, registration isn't. Reads as an invitation. */
.obp-gate { font-size: 12.5px; line-height: 1.45; color: var(--text-soft); background: color-mix(in srgb, var(--primary) 8%, transparent); border: 1px solid color-mix(in srgb, var(--primary) 22%, transparent); border-radius: 10px; padding: 9px 11px; margin-bottom: 12px; }
.obp-gate strong { color: var(--text); }
.obp-gate-hint { opacity: .8; }
.obp-card.is-gated .obp-btn[disabled] { background: var(--surface-2, #eceff3); color: var(--text-soft); }

/* "Where we've been" — ONE horizontal rail of past trips, not a wall. A grid of two dozen
   tiles swamps everything below it; a rail reads as a gallery you flick through. Same
   behaviour on mobile and desktop, so there's one thing to reason about. */
/* Cards OVERLAP by default (negative margin), so the strip reads as a fanned deck rather than
   a row of separate boxes. The rail is padded by half its width so the first and last card can
   still reach the centre — without that the effect dies at both ends. */
/* A horizontal scroller inside a flex parent (every page-builder container is display:flex)
   must be allowed to SHRINK. Flex items default to min-width:auto, so without this the rail's
   content width wins and the whole PAGE gets a horizontal scrollbar. */
.pb-grid, .feed, .trip-rail, .row-scroll { min-width: 0; max-width: 100%; }

/* Snap is `proximity`, not `mandatory` — mandatory fights the finger on a rail this dense and
   is what made it feel sticky. No scroll-behavior here either: smooth scrolling on a scroller
   the user is dragging adds lag on top of their own momentum. */
.trip-rail { display: flex; gap: 0; overflow-x: auto; scroll-snap-type: x proximity;
    padding: 20px 8px 28px; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.trip-rail::-webkit-scrollbar { display: none; }
.trip-rail > * { flex: 0 0 auto; scroll-snap-align: center; width: 208px; margin-right: -52px; }
.trip-rail > *:last-child { margin-right: 0; }
@media (min-width: 900px) { .trip-rail > * { width: 244px; margin-right: -60px; } }

/* `rail` = the same sideways scroll WITHOUT the deck: no overlap, every card at full
   colour. For when the deck's fade reads as "these ones are broken" rather than depth. */
.trip-rail.is-flat { gap: 16px; }
.trip-rail.is-flat > * { margin-right: 0; width: 240px; }
.trip-rail.is-flat .trip-tile { filter: none; opacity: 1; transform: none; }
@media (min-width: 900px) { .trip-rail.is-flat > * { width: 268px; margin-right: 0; } }

/* `grid` = no horizontal scroll at all; wraps onto more rows. */
.trip-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 18px; padding: 14px 0 26px; }
.trip-grid .trip-tile { filter: none; opacity: 1; transform: none; }

/* Past = faded, but as a BAND not a spotlight: the middle card and a couple either side stay in
   full colour, and the fade ramps up only beyond them — one lit card in a grey row read as an
   accident. Every value (--gs grey, --br brightness, --op opacity, --tx nudge, --sc scale,
   --z layering) is written per-card by the rail script from its distance to the centre. */
.trip-tile { display: block; position: relative; z-index: var(--z, 1); border-radius: 16px; overflow: hidden;
    text-decoration: none; box-shadow: 0 6px 18px rgba(0,0,0,.22);
    filter: grayscale(var(--gs, .92)) brightness(var(--br, .86)); opacity: var(--op, .7);
    transform: translateX(var(--tx, 0px)) scale(var(--sc, .9));
    transition: filter .35s ease, opacity .35s ease, transform .35s ease, box-shadow .35s ease; }
.trip-tile.is-focus { box-shadow: 0 20px 44px rgba(0,0,0,.34); }
.trip-tile:hover, .trip-tile:focus-visible { filter: none; opacity: 1; z-index: 200; box-shadow: 0 20px 44px rgba(0,0,0,.34); }
@media (prefers-reduced-motion: reduce) { .trip-tile { transition: none; } }
.trip-tile-img { position: relative; aspect-ratio: 4 / 3; background-size: cover; background-position: center; background-color: var(--primary-2, #2a2a35); display: flex; align-items: flex-end; }
.trip-tile.no-img .trip-tile-img { background: linear-gradient(135deg, var(--primary), var(--primary-2, #0c0c12)); }
.trip-tile-ph { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -60%); font-size: 40px; opacity: .35; }
.trip-tile-shade { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(0,0,0,.05) 40%, rgba(0,0,0,.82) 100%); }
.trip-tile-cap { position: relative; padding: 14px 15px; color: #fff; width: 100%; }
.trip-tile-when { font-size: 11px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; opacity: .9; }
.trip-tile-name { font-size: 17px; font-weight: 900; line-height: 1.2; margin: 3px 0 4px; color: #fff; }
.trip-tile-meta { font-size: 12px; opacity: .88; }
.section-sub { margin: -8px 0 4px; color: var(--text-soft); font-size: 14.5px; }

.obp-success { display: none; text-align: center; padding: 10px 0; }
.obp-success h4 { font-size: 18px; font-weight: 900; margin-bottom: 2px; }
.obp-success span { font-size: 13px; color: var(--text-soft); }
.obp-card.is-ripped .obp-options-section, .obp-card.is-ripped .obp-input-stack { display: none; }
.obp-card.is-ripped .obp-success { display: block; }
/* A finished trip keeps its pass as a keepsake (like a completed program card) — clearly done,
   never mistakable for a live ticket. Show the success block even if they never signed up, so a
   past trip can't sit at "REQUEST PENDING" forever. */
/* A past trip in the same rail as upcoming ones: present, but visibly in the past.
   With one upcoming trip the strip read as an empty line with a single card; letting
   the finished ones fill in behind it shows a campus that actually goes places.
   Desaturated + dimmed rather than hidden, with a DONE ribbon so it can't be mistaken
   for something bookable. It lifts to full colour on hover — it's still a memory worth
   looking at. */
.obp-card.is-finished { filter: saturate(.25) brightness(.97); opacity: .78; transition: filter .3s, opacity .3s, transform .2s; }
.obp-card.is-finished:hover { filter: none; opacity: 1; }
.obp-card.is-finished .obp-top::after { background: rgba(0,0,0,.82); }
.obp-card.is-finished .obp-top { position: relative; }
/* The ribbon sits on the image, angled across the top-left corner. */
.obp-card.is-finished .obp-top::before { content: 'DONE'; position: absolute; z-index: 3; top: 16px; left: -34px;
    width: 132px; text-align: center; transform: rotate(-38deg); background: #16a34a; color: #fff;
    font-size: 10px; font-weight: 900; letter-spacing: 2px; padding: 4px 0; box-shadow: 0 2px 10px rgba(0,0,0,.28); }
@media (prefers-reduced-motion: reduce) { .obp-card.is-finished { transition: none; } }
.obp-card.is-finished .obp-options-section, .obp-card.is-finished .obp-input-stack { display: none; }
.obp-card.is-finished .obp-success { display: block; }
.obp-card.is-finished .obp-badge { background: #16a34a; color: #fff; }
.obp-card.is-finished .obp-success h4 { color: #15803d; }

/* ── Program card (.olami-prog-card-v2) — faithful "program pass" credential ── */
.olami-prog-card-v2 { position: relative; min-height: 210px; border-radius: 20px; overflow: hidden; box-shadow: 0 10px 30px rgba(0,0,0,.15); cursor: pointer; transition: transform .3s ease, box-shadow .3s ease; display: block; }
.olami-prog-card-v2:hover { transform: translateY(-5px) scale(1.02); box-shadow: 0 20px 40px rgba(0,0,0,.25); }
.pc-bg { position: absolute; inset: 0; z-index: 1; }
.pc-texture { position: absolute; inset: 0; z-index: 2; opacity: var(--pc-texture);
    background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); }
.pc-shine { position: absolute; inset: 0; z-index: 3; pointer-events: none; background: linear-gradient(45deg, transparent 40%, rgba(255,255,255,.05) 50%, transparent 60%); }
.pc-content { position: relative; z-index: 10; padding: 25px; min-height: 210px; display: flex; flex-direction: column; justify-content: space-between; }
.pc-header { display: flex; justify-content: space-between; align-items: flex-start; }
.pc-badge { font-size: 10px; font-weight: 700; letter-spacing: 1.5px; opacity: .7; text-transform: uppercase; margin-bottom: 6px; }
.pc-title { font-size: 22px; font-weight: 800; margin: 0; line-height: 1.2; letter-spacing: -.5px; }
.pc-icon-badge { width: 36px; height: 36px; border-radius: 50%; background: linear-gradient(135deg, #FFD700, #FDB931); border: 1px solid rgba(255,255,255,.4); display: flex; align-items: center; justify-content: center; box-shadow: 0 4px 10px rgba(0,0,0,.2); font-size: 18px; }
.pc-footer { margin-top: auto; }
.pc-meta-row { display: flex; justify-content: space-between; align-items: flex-end; margin-bottom: 12px; }
.pc-label { display: block; font-size: 10px; text-transform: uppercase; letter-spacing: 1px; opacity: .7; margin-bottom: 2px; }
.pc-date-val { font-size: 14px; font-weight: 700; }
.pc-progress-wrap { text-align: right; }
.pc-progress-label { display: block; font-size: 9px; text-transform: uppercase; letter-spacing: 1.5px; opacity: .6; margin-bottom: 2px; font-weight: 600; }
.pc-progress-num { font-size: 28px; font-weight: 800; line-height: 1; }
.pc-total { font-size: 14px; opacity: .7; font-weight: 600; margin-left: 2px; }
.pc-progress-track { height: 6px; background: rgba(255,255,255,.15); border-radius: 3px; overflow: hidden; }
.pc-progress-fill { height: 100%; border-radius: 3px; transition: width 1s cubic-bezier(.4,0,.2,1); }

/* ── Completed program — the card stays on the Hub as a bright-green credential ── */
.olami-prog-card-v2.is-complete { --pc-accent: #ffffff; box-shadow: 0 14px 36px rgba(21,128,61,.45); }
.olami-prog-card-v2.is-complete:hover { box-shadow: 0 22px 46px rgba(21,128,61,.55); }
.olami-prog-card-v2.is-complete .pc-progress-track { background: rgba(255,255,255,.28); }
.olami-prog-card-v2.is-complete .pc-icon-badge { background: linear-gradient(135deg, #bbf7d0, #22c55e); }
/* "COMPLETED" corner ribbon (clipped by the card's overflow:hidden). */
.pc-ribbon { position: absolute; top: 18px; right: -38px; z-index: 12; transform: rotate(45deg);
    background: #052e16; color: #bbf7d0; font-size: 10px; font-weight: 800; letter-spacing: 2px;
    text-transform: uppercase; padding: 5px 44px; box-shadow: 0 4px 12px rgba(0,0,0,.3); }
/* Confetti — pieces fall behind the content (z4) so the text stays crisp. */
.pc-confetti { position: absolute; inset: 0; z-index: 4; pointer-events: none; overflow: hidden; }
.pc-confetti i { position: absolute; top: -12%; width: 7px; height: 12px; border-radius: 1px; opacity: 0;
    animation-name: pc-confetti-fall; animation-timing-function: linear; animation-iteration-count: infinite; }
@keyframes pc-confetti-fall {
    0%   { transform: translateY(-12%) rotate(0deg); opacity: 0; }
    12%  { opacity: 1; }
    100% { transform: translateY(230px) rotate(560deg); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) { .pc-confetti { display: none; } }

/* ── Program SIGN-UP card (.olami-master-card) — faithful promo/sales card ──── */
.olami-master-card { position: relative; width: 100%; background: var(--promo-bg); border: 1px solid rgba(255,255,255,.1); border-top: 1px solid rgba(255,255,255,.2); border-bottom: 1px solid rgba(255,255,255,.1); border-radius: 16px; padding: 22px 20px; text-align: center; box-shadow: 0 12px 30px rgba(0,0,0,.42); color: var(--promo-text); overflow: hidden; transition: transform .3s ease, box-shadow .3s ease; box-sizing: border-box; }
.olami-master-card:hover { transform: translateY(-5px); box-shadow: 0 20px 44px rgba(0,0,0,.55); }
.olami-master-card > * { position: relative; z-index: 2; }
.olami-card-glow { position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); width: 105%; height: 105%; z-index: 0; border-radius: 30px; filter: blur(50px); opacity: var(--promo-shine); background: linear-gradient(45deg, var(--promo-secondary), var(--promo-accent), var(--promo-secondary)); animation: om-breathe 6s infinite alternate; }
@keyframes om-breathe { 0% { opacity: calc(var(--promo-shine) * .8); transform: translate(-50%,-50%) scale(.98); } 100% { opacity: calc(var(--promo-shine) * 1.2); transform: translate(-50%,-50%) scale(1.02); } }
/* The sheen. This effect already existed — at rgba(255,255,255,.06) on a 50%-wide
   band, which is roughly three times too faint to register on a near-black card, so
   it shipped invisible for its whole life. Wider band, a bright core and a warm edge
   borrowed from the accent, so it reads as light crossing a surface.

   It also runs on its OWN, slowly and staggered, not only on :hover — a third of
   this site's visitors are on a phone, where a hover-only effect does not exist. */
.olami-master-card::before {
    content: ''; position: absolute; top: -20%; left: -140%; width: 75%; height: 140%;
    z-index: 1; pointer-events: none; transform: skewX(-22deg);
    background: linear-gradient(100deg, transparent 0%, rgba(255,255,255,.05) 34%,
        rgba(255,255,255,.20) 48%, rgba(212,175,55,.16) 56%, rgba(255,255,255,.05) 68%, transparent 100%);
    animation: om-sheen 7s cubic-bezier(.25,.6,.35,1) infinite;
}
/* Rest off-screen for the back half of the cycle, so it passes once and waits. */
@keyframes om-sheen { 0% { left: -140%; } 38%, 100% { left: 170%; } }
.olami-master-card:hover::before,
.olami-master-card:focus-within::before { animation: om-sheen-fast .85s cubic-bezier(.25,.6,.35,1); }
@keyframes om-sheen-fast { from { left: -140%; } to { left: 170%; } }
/* A row reads as one surface catching the light, not three metronomes. */
.feed > .olami-master-card:nth-child(2n)::before { animation-delay: .5s; }
.feed > .olami-master-card:nth-child(3n)::before { animation-delay: 1s; }
@media (prefers-reduced-motion: reduce) {
    .olami-master-card::before { animation: none; }
}
.om-tagline { color: var(--promo-accent); font-size: 10.5px; text-transform: uppercase; letter-spacing: 2px; font-weight: 700; margin-bottom: 8px; display: inline-block; background: rgba(255,255,255,.05); padding: 4px 10px; border-radius: 50px; border: 1px solid var(--promo-accent); }
.om-title { font-size: clamp(20px, 3vw, 28px); color: var(--promo-title); margin: 0 0 7px; font-weight: 800; line-height: 1.1; text-transform: uppercase; }
.om-subtitle { font-size: 14px; color: var(--promo-text); opacity: .8; font-weight: 300; margin-bottom: 8px; }
.om-description { color: var(--promo-text); opacity: .85; font-size: 12.5px; line-height: 1.45; margin: 0 auto 10px; max-width: 92%; max-height: 3.4em; overflow-y: auto; scrollbar-width: thin; }
/* One line, always. The items used to carry a fixed 44px of horizontal padding, so
   three of them outgrew the card and wrapped — leaving the third stranded on its own
   row. Equal flex columns share whatever width the card has instead, and the value
   wraps inside its own column rather than pushing the layout around. */
.om-info-grid { display: flex; flex-wrap: nowrap; justify-content: center; align-items: flex-start; gap: 0; margin-bottom: 12px; border-top: 1px solid rgba(255,255,255,.1); border-bottom: 1px solid rgba(255,255,255,.1); padding: 8px 0; }
.om-info-item { flex: 1 1 0; min-width: 0; padding: 0 10px; position: relative; text-align: center; }
.om-info-item:not(:last-child)::after { content: ''; position: absolute; right: 0; top: 6px; height: 24px; width: 1px; background: rgba(255,255,255,.2); }
.om-label { display: block; font-size: 11px; text-transform: uppercase; color: var(--promo-text); opacity: .6; letter-spacing: 1px; margin-bottom: 5px; }
.om-value { display: block; font-size: 17px; line-height: 1.25; color: var(--promo-text); font-weight: 600; overflow-wrap: anywhere; }
/* Three columns on a narrow card need the smaller type; one or two can breathe. */
.om-info-grid[data-cols="3"] .om-value { font-size: 15px; }
.om-info-grid[data-cols="3"] .om-label { font-size: 10px; letter-spacing: .6px; }
.om-value.highlight { color: var(--promo-accent); }
.om-cta-area { background: rgba(255,255,255,.03); border-radius: 10px; padding: 15px; border: 1px dashed rgba(255,255,255,.1); }
.om-button { display: inline-block; background: var(--promo-accent); color: #000; padding: 10px 28px; font-weight: 700; text-transform: uppercase; border-radius: 5px; transition: .3s; font-size: 13.5px; cursor: pointer; border: none; }
.om-button:hover { filter: brightness(1.2); box-shadow: 0 0 30px var(--promo-accent); }
.feed > .olami-master-card { width: min(80vw, 390px); }

/* ── Cards / forms / modal ───────────────────────────────────────────────── */
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); padding: 26px; }
.field { margin-bottom: 16px; }
.field label { display: block; font-size: 13px; font-weight: 700; margin-bottom: 6px; }
.field input { width: 100%; padding: 13px 15px; border: 1px solid var(--border); border-radius: 10px; font-size: 15px; background: var(--surface); color: var(--text); }
.field input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 20%, transparent); }
.divider { display: flex; align-items: center; gap: 12px; color: var(--text-soft); font-size: 12px; margin: 18px 0; }
.divider::before, .divider::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.richtext { color: var(--text); }

/* ── Page-builder containers (flex/columns) + headings ───────────────────── */
.page-flex { width: 100%; box-sizing: border-box; }
.page-flex-full { width: 100%; }
.page-flex > .pf-col { flex: 1 1 0; min-width: 0; }
.page-flex[style*="flex-direction:column"] > .pf-col { flex: 0 0 auto; }
.page-heading { margin: 0; font-weight: 800; line-height: 1.2; color: var(--text); }
h1.page-heading { font-size: clamp(28px, 4vw, 42px); }
h2.page-heading { font-size: clamp(22px, 3vw, 32px); }
h3.page-heading { font-size: clamp(18px, 2.4vw, 24px); }
h4.page-heading { font-size: 18px; }
@media (max-width: 767px) {
    /* Auto-optimize for phones: a row container stacks to a single column, and its
       columns drop their desktop width-% so they fill the screen (no more squooshing).
       Opt out per-container with "Stack on mobile" off, or override per breakpoint. */
    .page-flex.pf-wrap { flex-direction: column !important; align-items: stretch !important; }
    .page-flex.pf-wrap > .pf-col { flex: 1 1 auto !important; max-width: 100% !important; width: 100% !important; }
    .page-flex.pf-wrap > .pf-resize { display: none !important; }
}

/* Page-builder "Advanced" — responsive visibility + entrance animations.
   Visibility breakpoints match the editor's device widths (so the device toggle
   previews them correctly inside the iframe). */
@media (min-width: 1025px) { .pb-hd { display: none !important; } }
@media (min-width: 768px) and (max-width: 1024px) { .pb-ht { display: none !important; } }
@media (max-width: 767px) { .pb-hm { display: none !important; } }

/* Animations: JS adds .pb-anim-ready so content is visible if JS never runs. */
.pb-anim-ready { opacity: 0; transition: opacity .6s ease, transform .65s cubic-bezier(.16,.84,.44,1); will-change: opacity, transform; }
.pb-anim-ready.is-in { opacity: 1; transform: none; }
.pb-anim-ready.pb-fade-up { transform: translateY(30px); }
.pb-anim-ready.pb-fade-in { transform: none; }
.pb-anim-ready.pb-zoom { transform: scale(.9); }
.pb-anim-ready.pb-slide-left { transform: translateX(-36px); }
.pb-anim-ready.pb-slide-right { transform: translateX(36px); }
@media (prefers-reduced-motion: reduce) { .pb-anim-ready { opacity: 1 !important; transform: none !important; transition: none; } }

.modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,.55); display: grid; place-items: center; z-index: 100; padding: 20px; }
.modal { background: var(--surface); color: var(--text); border-radius: 18px; max-width: 380px; width: 100%; padding: 30px; box-shadow: var(--shadow-lg); text-align: center; }
.modal h3 { font-size: 21px; margin-bottom: 6px; }
.modal p { color: var(--text-soft); font-size: 14px; margin-bottom: 18px; }

/* ── Mentorship band ─────────────────────────────────────────────────────── */
.mentor h2 { font-size: 26px; font-weight: 900; }
.mentor p { opacity: .85; margin: 8px 0 18px; max-width: 460px; }

/* ── Footer ──────────────────────────────────────────────────────────────── */
.footer { background: var(--footer-bg, #0c0c12); color: #fff; padding: 40px 0 28px; margin-top: 30px; }
.footer .cols { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 24px; }
.footer h4 { font-size: 15px; margin-bottom: 10px; }
.footer a { display: block; opacity: .7; font-size: 14px; padding: 3px 0; }
.footer .copy { opacity: .5; font-size: 12px; margin-top: 26px; border-top: 1px solid rgba(255,255,255,.12); padding-top: 16px; }

/* ── "Who's going" social-proof pill (OLAMI app GoingWithStack) ───────────── */
.going-pill { position: absolute; z-index: 4; display: inline-flex; align-items: center; gap: 4px;
    background: rgba(255,255,255,.94); color: #14161c; font-size: 11px; font-weight: 800; letter-spacing: .2px;
    padding: 5px 10px; border-radius: 999px; box-shadow: 0 1px 6px rgba(0,0,0,.2); white-space: nowrap; }
.ot-going { top: 12px; right: 14px; }
.obp-going { top: 14px; right: 14px; }
.pc-going { top: 16px; right: 16px; }
.hosted-pill { position: absolute; z-index: 4; display: inline-flex; align-items: center; gap: 4px;
    background: rgba(15,23,42,.85); color: #fff; font-size: 10.5px; font-weight: 800; letter-spacing: .2px;
    padding: 5px 10px; border-radius: 999px; box-shadow: 0 1px 6px rgba(0,0,0,.25); white-space: nowrap; }
.ot-hosted { top: 12px; left: 14px; }
.obp-hosted { top: 14px; left: 14px; }

/* ── Community page — OLAMI-app CommunityScreen (pulse + trending + feed) ──── */
.comm-wrap { padding-top: 8px; padding-bottom: 24px; display: flex; flex-direction: column; gap: 26px; }
.comm-pulse { position: relative; overflow: hidden; border-radius: 24px; padding: 26px 24px 24px;
    background: linear-gradient(135deg, var(--primary), var(--primary-2, var(--primary))); color: #fff;
    box-shadow: 0 14px 40px color-mix(in srgb, var(--primary) 38%, transparent); }
.comm-pulse-glow { position: absolute; top: -60px; right: -50px; width: 200px; height: 200px;
    background: rgba(255,255,255,.16); filter: blur(34px); border-radius: 50%; pointer-events: none; }
.comm-pulse-eyebrow { position: relative; font-size: 12px; font-weight: 800; letter-spacing: 1px; opacity: .9; }
.comm-pulse-title { position: relative; margin: 6px 0 18px; font-size: 26px; font-weight: 900; line-height: 1.15; }
.comm-pulse-sub { margin-top: 8px; font-size: 14.5px; opacity: .85; max-width: 46ch; }
.comm-pulse-stats { position: relative; display: flex; gap: 12px; }
.comm-pulse-stat { flex: 1; background: rgba(255,255,255,.14); border: 1px solid rgba(255,255,255,.18);
    border-radius: 16px; padding: 14px 10px; text-align: center; backdrop-filter: blur(4px); }
.cps-num { display: block; font-size: 28px; font-weight: 900; line-height: 1; }
.cps-label { display: block; margin-top: 5px; font-size: 11px; font-weight: 600; opacity: .92; }

.comm-section { display: flex; flex-direction: column; gap: 14px; }
.comm-trending { display: flex; gap: 14px; overflow-x: auto; padding: 2px 2px 6px; scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.comm-trending::-webkit-scrollbar { display: none; }
.comm-trend-card { position: relative; flex: 0 0 200px; height: 150px; border-radius: 18px; overflow: hidden;
    text-decoration: none; scroll-snap-align: start; display: flex; flex-direction: column; justify-content: flex-end;
    background: linear-gradient(135deg, var(--primary), var(--primary-2, var(--primary))); background-size: cover; background-position: center;
    box-shadow: 0 6px 18px rgba(0,0,0,.16); transition: transform .15s; }
.comm-trend-card:active { transform: scale(.97); }
.comm-trend-going { position: absolute; top: 12px; right: 12px; display: inline-flex; align-items: center; gap: 4px;
    background: rgba(255,255,255,.94); color: #14161c; font-size: 11px; font-weight: 800; padding: 4px 9px; border-radius: 999px; }
.comm-trend-body { padding: 14px; color: #fff; }
.comm-trend-date { font-size: 11px; font-weight: 800; letter-spacing: .4px; opacity: .92; }
.comm-trend-title { margin-top: 4px; font-size: 15px; font-weight: 800; line-height: 1.2;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

.comm-feed { display: flex; flex-direction: column; gap: 10px; }
.comm-feed-row { display: flex; align-items: center; gap: 13px; padding: 12px 14px; border-radius: 16px;
    background: var(--surface); border: 1px solid var(--border, rgba(0,0,0,.07)); text-decoration: none; color: inherit;
    transition: transform .12s, box-shadow .12s; }
.comm-feed-row:active { transform: scale(.99); }
.comm-feed-avatar { flex: 0 0 44px; width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center;
    overflow: hidden; font-weight: 900; font-size: 17px; color: #fff;
    background: linear-gradient(135deg, var(--primary), var(--primary-2, var(--primary))); }
.comm-feed-avatar img { width: 100%; height: 100%; object-fit: cover; }
.comm-feed-text { flex: 1; min-width: 0; }
.comm-feed-line { font-size: 14px; line-height: 1.35; color: var(--text); }
.comm-feed-line strong { font-weight: 800; }
.comm-feed-when { margin-top: 3px; font-size: 12px; font-weight: 600; color: var(--text-soft, #6b6b78); }
.comm-feed-thumb { flex: 0 0 48px; width: 48px; height: 48px; border-radius: 12px; background-size: cover; background-position: center; }
.comm-empty { padding: 36px 20px; text-align: center; border-radius: 16px; background: var(--surface);
    border: 1px dashed var(--border, rgba(0,0,0,.12)); color: var(--text-soft, #6b6b78); font-weight: 600; }

/* ── Mobile bottom tab bar — OLAMI-app style (standard, edge-to-edge) ─────── */
.tabbar { display: none; }
.tabbar-v2 { position: fixed; z-index: 60; left: 0; right: 0; bottom: 0;
    align-items: flex-start; justify-content: space-around;
    background: var(--tabbar-bg, #15151c); border-top: 1px solid rgba(255,255,255,.1);
    padding: 8px 4px calc(8px + env(safe-area-inset-bottom)); }
.tabbar-v2 .tb-item { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 4px;
    text-decoration: none; color: rgba(255,255,255,.5); font-size: 10px; font-weight: 600; letter-spacing: .1px; transition: color .15s; }
.tabbar-v2 .tb-item svg { width: 23px; height: 23px; }
.tabbar-v2 .tb-item.active { color: var(--primary); font-weight: 700; }
.tabbar-v2 .tb-center { flex: 0 0 54px; width: 54px; height: 54px; margin-top: -22px; border-radius: 50%;
    background: linear-gradient(135deg, var(--primary), var(--primary-2, var(--primary))); display: grid; place-items: center;
    box-shadow: 0 6px 16px rgba(0,0,0,.4); border: 4px solid var(--tabbar-bg, #15151c); text-decoration: none; transition: transform .12s; }
.tabbar-v2 .tb-center:active { transform: scale(.93); }
.tabbar-v2 .tb-center span { color: #fff; font-weight: 900; font-size: 19px; letter-spacing: -.5px; }
.tabbar-v2 .tb-center img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }

/* ── App download bar ─────────────────────────────────────────────────────────
   Sits above the nav, brand-coloured so it reads as ours rather than as an advert.
   Rendered hidden and revealed by script, so someone already inside the installed
   app never sees a prompt to install it, and a dismissal sticks. */
.app-bar {
    display: flex; align-items: center; gap: 10px;
    padding: 9px 16px; background: var(--primary); color: #fff;
    font-size: 13.5px; font-weight: 600; position: relative; z-index: 60;
}
.app-bar[hidden] { display: none; }
.app-bar-icon { font-size: 16px; line-height: 1; }
.app-bar-txt { flex: 1 1 auto; min-width: 0; }
.app-bar-txt b { font-weight: 800; }
.app-bar-cta {
    flex: none; background: #fff; color: var(--primary);
    padding: 5px 14px; border-radius: 999px; font-size: 12.5px; font-weight: 800;
    text-decoration: none; white-space: nowrap; transition: transform .15s ease;
}
.app-bar-cta:hover { transform: translateY(-1px); }
.app-bar-x {
    flex: none; background: none; border: 0; color: #fff; opacity: .75;
    font-size: 20px; line-height: 1; padding: 0 2px; cursor: pointer;
}
.app-bar-x:hover { opacity: 1; }
/* Phones: the campus name alone carries it, so the sentence does not wrap to two
   lines above the nav. */
@media (max-width: 520px) {
    .app-bar { padding: 8px 12px; gap: 8px; font-size: 12.5px; }
    .app-bar-cta { padding: 5px 12px; font-size: 12px; }
}

/* ── Nav swap — phones + tablets get the app bottom bar; desktop keeps the top
   nav. Triggers ≤1024px so iPads (portrait + landscape) are included. ───────── */
@media (max-width: 1024px) {
    .nav { display: none; }
    body[data-mode="portal"] { padding-bottom: 78px; }
    body[data-mode="portal"] .tabbar { display: flex; }
    body[data-mode="portal"] .topbar .actions .btn-text { display: none; }
    /* Top-nav hamburger → a working mobile menu on brochure sites (portal keeps the tabbar). */
    .nav-burger { display: inline-flex; }
    body[data-mode="portal"] .nav-burger { display: none; }
    .topbar .nav { position: absolute; top: 100%; left: 0; right: 0; flex-direction: column; gap: 2px; margin: 0;
        padding: 8px; background: var(--topbar-bg, var(--surface)); border-bottom: 1px solid var(--topbar-border, var(--border));
        box-shadow: 0 16px 40px rgba(0,0,0,.18); max-height: 80vh; overflow: auto; }
    .topbar .nav a { padding: 13px 14px; font-size: 15px; }
    .nav-cb:checked ~ .nav { display: flex !important; }
}

/* ── Responsive layout — stack on phones ─────────────────────────────────── */
@media (max-width: 760px) {
    .stats { grid-template-columns: repeat(2, 1fr); gap: 18px; }
    .band-split, .footer .cols { grid-template-columns: 1fr; }
    main > .wrap[style*="grid-template-columns"] { grid-template-columns: 1fr !important; }
}

/* ── Auth pages (login / register / profile / reset) ─────────────────────────
   Ported from the OLAMI plugin's custom auth screens, themed with the org tokens
   so each campus's login matches its brand. */
.auth-wrap { max-width: 460px; margin: 40px auto; padding: 0 18px; }
.auth-wrap.wide { max-width: 660px; }
.auth-card { background: var(--surface); border-radius: 20px; box-shadow: var(--shadow); padding: 40px; position: relative; overflow: hidden; border: 1px solid var(--border); }
.auth-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, var(--primary), color-mix(in srgb, var(--primary) 55%, transparent)); }
.auth-head { text-align: center; margin-bottom: 28px; }
.auth-head h1 { font-size: 26px; font-weight: 800; color: var(--text); margin: 0 0 6px; }
.auth-head p { font-size: 14px; color: var(--text-soft); margin: 0; }
.auth-avatar { width: 84px; height: 84px; border-radius: 50%; margin: 0 auto 14px; background: linear-gradient(135deg, color-mix(in srgb, var(--primary) 16%, var(--surface)), var(--surface)); display: grid; place-items: center; font-size: 34px; border: 3px solid var(--surface); box-shadow: 0 4px 15px rgba(0,0,0,.10); overflow: hidden; }
.auth-avatar img { width: 100%; height: 100%; object-fit: cover; }

.auth-google { display: flex; align-items: center; justify-content: center; gap: 12px; width: 100%; padding: 13px 18px; background: var(--surface); border: 2px solid var(--border); border-radius: 12px; font-size: 15px; font-weight: 600; color: var(--text); cursor: pointer; transition: all .2s ease; text-decoration: none; }
.auth-google:hover { border-color: #4285f4; box-shadow: 0 4px 12px rgba(66,133,244,.15); transform: translateY(-1px); }
.auth-google svg { width: 20px; height: 20px; flex-shrink: 0; }

.auth-divider { display: flex; align-items: center; margin: 24px 0; color: var(--text-soft); font-size: 13px; }
.auth-divider::before, .auth-divider::after { content: ''; flex: 1; height: 1px; background: var(--border); }
.auth-divider span { padding: 0 16px; }

.auth-grid { display: flex; flex-wrap: wrap; gap: 16px; }
.auth-field { margin-bottom: 16px; }
.auth-grid .auth-field { flex: 1 1 calc(50% - 8px); min-width: 190px; margin-bottom: 0; }
.auth-field.full { flex-basis: 100%; }
.auth-field label { display: block; font-size: 13px; font-weight: 700; color: var(--text); margin-bottom: 7px; }
.auth-field label .req { color: #dc2626; margin-left: 2px; }
.auth-field input, .auth-field select { width: 100%; padding: 13px 15px; border: 2px solid var(--border); border-radius: 12px; font-size: 15px; background: var(--surface); color: var(--text); box-sizing: border-box; transition: all .2s; }
.auth-field input:focus, .auth-field select:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 18%, transparent); }
.auth-phone { display: flex; gap: 10px; }
.auth-phone select { width: 130px; flex-shrink: 0; }
.auth-phone input { flex: 1; }
.auth-check { display: flex; align-items: center; gap: 12px; padding: 13px 15px; background: color-mix(in srgb, var(--primary) 5%, var(--surface)); border-radius: 12px; cursor: pointer; }
.auth-check input { width: 19px; height: 19px; accent-color: var(--primary); }
.auth-check span { font-weight: 500; font-size: 14px; color: var(--text); }

.auth-options { display: flex; justify-content: space-between; align-items: center; margin: 4px 0 20px; font-size: 13px; }
.auth-options label { display: flex; align-items: center; gap: 8px; color: var(--text-soft); cursor: pointer; }
.auth-options input { width: 16px; height: 16px; accent-color: var(--primary); }
.auth-options a, .auth-foot a { color: var(--primary); font-weight: 600; text-decoration: none; }
.auth-options a:hover, .auth-foot a:hover { text-decoration: underline; }
.auth-submit { width: 100%; padding: 15px; border: none; border-radius: 12px; background: var(--primary); color: var(--on-primary); font-size: 16px; font-weight: 800; cursor: pointer; transition: all .2s; }
.auth-submit:hover { filter: brightness(1.07); transform: translateY(-1px); box-shadow: 0 6px 18px color-mix(in srgb, var(--primary) 30%, transparent); }
.auth-foot { text-align: center; margin-top: 22px; padding-top: 20px; border-top: 1px solid var(--border); font-size: 14px; color: var(--text-soft); }
.auth-alt { margin-top: 14px; text-align: center; }
.auth-alt button { background: none; border: none; color: var(--primary); font-weight: 600; font-size: 13px; cursor: pointer; text-decoration: underline; padding: 0; }

.auth-msg { padding: 12px 15px; border-radius: 10px; font-size: 13.5px; margin-bottom: 18px; display: flex; align-items: center; gap: 10px; }
.auth-msg.ok { background: color-mix(in srgb, #16a34a 12%, var(--surface)); border: 1px solid color-mix(in srgb, #16a34a 35%, transparent); color: #15803d; }
.auth-msg.err { background: color-mix(in srgb, #dc2626 10%, var(--surface)); border: 1px solid color-mix(in srgb, #dc2626 30%, transparent); color: #b91c1c; }

@media (max-width: 540px) {
    .auth-card { padding: 28px 22px; }
    .auth-grid .auth-field { flex-basis: 100%; }
    .auth-phone { flex-direction: column; }
    .auth-phone select { width: 100%; }
}

/* ── Student Hub (personal dashboard) ───────────────────────────────────────
   Modelled on the OLAMI plugin's dashboard: an engagement hero, then the
   student's tickets / programs / boarding passes in horizontal feeds. */
.hub-wrap { padding: 26px 20px 60px; }

.hub-complete { display: flex; align-items: center; justify-content: space-between; gap: 12px; background: color-mix(in srgb, var(--primary) 10%, var(--surface)); border: 1px solid color-mix(in srgb, var(--primary) 30%, transparent); color: var(--text); border-radius: 14px; padding: 13px 18px; margin-bottom: 18px; font-weight: 600; font-size: 14px; text-decoration: none; }
.hub-complete-cta { color: var(--primary); font-weight: 800; white-space: nowrap; }

.hub-hero { position: relative; overflow: hidden; border-radius: 22px; padding: 26px 28px; margin-bottom: 18px; color: #fff; background: linear-gradient(135deg, #14162b 0%, #1c2747 55%, #0f3460 100%); border-bottom: 4px solid var(--primary); box-shadow: 0 14px 44px rgba(0,0,0,.28); }
.hub-hero-glow { position: absolute; top: -60%; right: -20%; width: 70%; height: 200%; background: radial-gradient(circle, color-mix(in srgb, var(--primary) 45%, transparent) 0%, transparent 60%); opacity: .5; pointer-events: none; }
.hub-hero-top, .hub-hero-stat, .hub-mini-stats { position: relative; z-index: 1; }
.hub-hero-greet { display: flex; align-items: center; gap: 14px; }
.hub-avatar { width: 52px; height: 52px; border-radius: 50%; flex-shrink: 0; display: grid; place-items: center; font-weight: 800; font-size: 20px; color: #fff; background: linear-gradient(135deg, var(--primary), color-mix(in srgb, var(--primary) 50%, #000)); overflow: hidden; border: 2px solid rgba(255,255,255,.25); }
.hub-avatar img { width: 100%; height: 100%; object-fit: cover; }
.hub-hello { font-size: 20px; font-weight: 800; line-height: 1.1; }
.hub-milestone { display: inline-block; margin-top: 5px; font-size: 11px; font-weight: 700; letter-spacing: .5px; padding: 3px 10px; border-radius: 20px; background: linear-gradient(135deg, var(--primary), color-mix(in srgb, var(--primary) 55%, #000)); }
.hub-hero-stat { margin-top: 18px; display: flex; align-items: baseline; gap: 10px; }
.hub-big-num { font-size: 50px; font-weight: 900; line-height: 1; text-shadow: 0 2px 24px color-mix(in srgb, var(--primary) 50%, transparent); }
.hub-big-label { font-size: 14px; opacity: .8; font-weight: 600; }
.hub-mini-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 18px; }
.hub-mini { background: rgba(255,255,255,.08); border: 1px solid rgba(255,255,255,.12); border-radius: 12px; padding: 10px 6px; text-align: center; }
.hub-mini-num { display: block; font-size: 19px; font-weight: 800; }
.hub-mini-label { display: block; font-size: 10.5px; opacity: .75; text-transform: uppercase; letter-spacing: .4px; margin-top: 2px; }

.hub-next { display: block; text-decoration: none; color: #fff; border-radius: 16px; padding: 16px 20px; margin-bottom: 22px; background: linear-gradient(135deg, #1a1a2e 0%, #16213e 60%, #0f3460 100%); position: relative; overflow: hidden; }
.hub-next-label { font-size: 11px; font-weight: 700; letter-spacing: 1.5px; opacity: .7; }
.hub-next-title { font-size: 19px; font-weight: 800; margin: 4px 0 6px; }
.hub-next-meta { font-size: 13px; opacity: .85; }
.hub-next-when { display: inline-block; margin-top: 10px; font-size: 12px; font-weight: 700; background: rgba(255,255,255,.14); padding: 5px 12px; border-radius: 20px; }

.hub-section { margin-bottom: 26px; }
.hub-section .section-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.hub-section .section-head h2 { font-size: 19px; font-weight: 800; }

.hub-past { display: flex; flex-direction: column; gap: 2px; background: var(--surface); border: 1px solid var(--border); border-radius: 14px; overflow: hidden; }
.hub-past-item { display: flex; align-items: center; gap: 12px; padding: 12px 16px; text-decoration: none; color: var(--text); border-bottom: 1px solid var(--border); transition: background .15s; }
.hub-past-item:last-child { border-bottom: none; }
.hub-past-item:hover { background: color-mix(in srgb, var(--primary) 5%, var(--surface)); }
.hub-past-icon { font-size: 15px; width: 20px; text-align: center; flex-shrink: 0; }
.hub-past-title { font-weight: 600; font-size: 14px; flex: 1; }
.hub-past-date { font-size: 12px; color: var(--text-soft); white-space: nowrap; }

.hub-empty { padding: 48px 24px; }
.hub-foot { text-align: center; margin-top: 30px; }
.hub-foot a { color: var(--text-soft); font-size: 13px; font-weight: 600; text-decoration: none; }
.hub-foot a:hover { color: var(--primary); }

@media (max-width: 540px) {
    .hub-mini-stats { grid-template-columns: repeat(2, 1fr); }
    .hub-big-num { font-size: 42px; }
}

/* ============================================================
   Page-builder widgets (icon-box, tabs, accordion, testimonial,
   countdown, social, map) — theme-driven.
   ============================================================ */
.w-iconbox { padding: 8px 0; }
.w-iconbox-ic { font-size: 40px; line-height: 1; margin-bottom: 10px; }
.w-iconbox-t { font-size: 19px; font-weight: 800; margin: 0 0 6px; color: var(--text, #15151b); }
.w-iconbox-x { margin: 0; color: var(--text-soft, #6b7280); line-height: 1.6; }
.w-iconbox-link { display: inline-block; margin-top: 10px; font-weight: 700; color: var(--primary, #b41f51); text-decoration: none; }
.w-iconbox-link:hover { text-decoration: underline; }

.w-tabs { border: 1px solid var(--border, #e5e7eb); border-radius: 14px; overflow: hidden; background: var(--surface, #fff); }
.w-tab-nav { display: flex; flex-wrap: wrap; gap: 2px; background: var(--surface-2, #f6f6f8); padding: 6px; }
.w-tab-btn { border: 0; background: transparent; cursor: pointer; font-weight: 700; font-size: 14px; padding: 9px 16px; border-radius: 9px; color: var(--text-soft, #6b7280); }
.w-tab-btn.is-active { background: var(--surface, #fff); color: var(--primary, #b41f51); box-shadow: 0 1px 4px rgba(0,0,0,.1); }
.w-tab-pane { display: none; padding: 20px; line-height: 1.7; color: var(--text, #15151b); }
.w-tab-pane.is-active { display: block; }

.w-acc { display: flex; flex-direction: column; gap: 10px; }
.w-acc-item { border: 1px solid var(--border, #e5e7eb); border-radius: 12px; overflow: hidden; background: var(--surface, #fff); }
.w-acc-head { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 12px; border: 0; background: transparent; cursor: pointer; font-weight: 700; font-size: 15px; padding: 15px 18px; text-align: left; color: var(--text, #15151b); }
.w-acc-ar { transition: transform .25s; color: var(--primary, #b41f51); }
.w-acc-item.is-open .w-acc-ar { transform: rotate(180deg); }
.w-acc-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .28s ease; }
.w-acc-item.is-open .w-acc-body { grid-template-rows: 1fr; }
.w-acc-inner { overflow: hidden; min-height: 0; padding: 0 18px; line-height: 1.7; color: var(--text-soft, #4b5563); }
.w-acc-item.is-open .w-acc-inner { padding: 0 18px 16px; }

.w-testi { margin: 0; background: var(--surface, #fff); border: 1px solid var(--border, #e5e7eb); border-radius: 16px; padding: 26px; max-width: 640px; }
.w-testi-stars { color: #f5b301; letter-spacing: 2px; margin-bottom: 10px; font-size: 16px; }
.w-testi-q { margin: 0 0 16px; font-size: 19px; line-height: 1.6; font-weight: 600; color: var(--text, #15151b); }
.w-testi-by { display: flex; align-items: center; gap: 12px; }
.w-testi-img { width: 46px; height: 46px; border-radius: 50%; background-size: cover; background-position: center; flex: none; }
.w-testi-meta strong { display: block; color: var(--text, #15151b); }
.w-testi-meta small { color: var(--text-soft, #6b7280); }
/* The Wix shape: portrait on top, everything centred, attribution pinned to the bottom so a
   row of cards lines up however long each quote is. */
.w-testi.is-stacked { display: flex; flex-direction: column; align-items: center; text-align: center; }
.w-testi.is-stacked .w-testi-img { width: 92px; height: 92px; margin-bottom: 20px; }
.w-testi.is-stacked .w-testi-q { font-weight: 500; }
.w-testi.is-stacked .w-testi-by { flex-direction: column; gap: 2px; margin-top: auto; padding-top: 10px; }

.w-countdown { padding: 10px 0; }
.w-cd-grid { display: inline-flex; gap: 12px; }
.w-cd-cell { min-width: 70px; background: var(--surface, #fff); border: 1px solid var(--border, #e5e7eb); border-radius: 12px; padding: 12px 10px; display: flex; flex-direction: column; align-items: center; }
.w-cd-n { font-size: 30px; font-weight: 800; color: var(--primary, #b41f51); line-height: 1; }
.w-cd-l { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--text-soft, #9ca3af); margin-top: 6px; }
.w-cd-empty, .w-map-empty { color: var(--text-soft, #9ca3af); font-style: italic; padding: 16px 0; }

.w-social { padding: 8px 0; }
.w-social-link { display: inline-flex; align-items: center; justify-content: center; width: 1.9em; height: 1.9em; margin: 0 4px; border-radius: 50%; background: var(--surface-2, #f1f1f4); text-decoration: none; transition: transform .15s, background .15s; }
.w-social-link:hover { transform: translateY(-2px); background: var(--primary, #b41f51); }

.w-map { box-shadow: 0 6px 24px rgba(0,0,0,.1); }
@media (max-width: 600px) { .w-cd-cell { min-width: 58px; } .w-cd-n { font-size: 24px; } }

/* Contact section (form + info + map) */
.w-contact { max-width: 1080px; margin: 0 auto; padding: 0 20px; width: 100%; }
.w-contact-head { text-align: center; margin-bottom: 26px; }
.w-contact-head h2 { font-size: clamp(26px, 4vw, 38px); font-weight: 900; letter-spacing: -.5px; margin: 0 0 8px; color: var(--text, #15151b); }
.w-contact-head p { margin: 0 auto; max-width: 620px; color: var(--text-soft, #6b7280); font-size: 16px; line-height: 1.6; }
.w-contact-grid { display: grid; grid-template-columns: 1.1fr .9fr; gap: 22px; align-items: start; }
.w-contact-grid--info { grid-template-columns: 1fr; max-width: 760px; margin: 0 auto; }
.w-contact-card { background: var(--surface, #fff); border: 1px solid var(--border, #e5e7eb); border-radius: 18px; padding: 24px; box-shadow: 0 6px 24px rgba(0,0,0,.06); }
.w-contact-card h3 { margin: 0 0 16px; font-size: 19px; font-weight: 800; color: var(--text, #15151b); }
.w-contact-form { display: flex; flex-direction: column; gap: 13px; }
.w-cf-row { display: grid; grid-template-columns: 1fr 1fr; gap: 13px; }
.w-contact-form label { display: flex; flex-direction: column; gap: 6px; font-size: 13px; font-weight: 700; color: var(--text-soft, #6b7280); }
.w-contact-form input, .w-contact-form textarea { width: 100%; padding: 11px 13px; border: 1px solid var(--border, #e5e7eb); border-radius: 11px; background: var(--bg, #f7f7fa); color: var(--text, #15151b); font-size: 15px; font-family: inherit; font-weight: 500; }
.w-contact-form input:focus, .w-contact-form textarea:focus { outline: none; border-color: var(--primary, #b41f51); box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary, #b41f51) 18%, transparent); }
.w-contact-form textarea { resize: vertical; min-height: 96px; }
.w-contact-form .btn { margin-top: 4px; align-self: flex-start; }
.w-contact-ok { background: color-mix(in srgb, #16a34a 12%, transparent); color: #15803d; border: 1px solid color-mix(in srgb, #16a34a 35%, transparent); padding: 11px 14px; border-radius: 11px; font-weight: 700; font-size: 14px; margin-bottom: 14px; }
.w-contact-err { background: color-mix(in srgb, #dc2626 10%, transparent); color: #b91c1c; border: 1px solid color-mix(in srgb, #dc2626 32%, transparent); padding: 11px 14px; border-radius: 11px; font-weight: 700; font-size: 14px; margin-bottom: 14px; }
.w-contact-info { display: flex; flex-direction: column; gap: 12px; }
.w-contact-grid--info .w-contact-info { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.w-contact-item { display: flex; align-items: flex-start; gap: 13px; padding: 15px 17px; background: var(--surface, #fff); border: 1px solid var(--border, #e5e7eb); border-radius: 14px; color: var(--text, #15151b); text-decoration: none; font-size: 15px; line-height: 1.5; transition: transform .15s, box-shadow .15s; }
a.w-contact-item:hover { transform: translateY(-2px); box-shadow: 0 8px 22px rgba(0,0,0,.08); border-color: var(--primary, #b41f51); }
.w-contact-item b { font-size: 13px; color: var(--text-soft, #6b7280); font-weight: 700; }
.w-ci-ic { font-size: 22px; line-height: 1.2; flex: none; }
.w-contact-map { height: 230px; border-radius: 14px; overflow: hidden; border: 1px solid var(--border, #e5e7eb); }
.w-contact-map iframe { width: 100%; height: 100%; border: 0; }
@media (max-width: 820px) {
    .w-contact-grid { grid-template-columns: 1fr; }
    .w-cf-row { grid-template-columns: 1fr; }
    .w-contact-form .btn { align-self: stretch; text-align: center; }
}

/* Footer social row */
.foot-social { display: flex; gap: 8px; margin-top: 14px; }
.foot-social a { display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; border-radius: 50%; background: rgba(255,255,255,.08); color: #fff; text-decoration: none; font-size: 15px; transition: background .15s, transform .15s; }
.foot-social a:hover { background: var(--primary, #b41f51); transform: translateY(-2px); }

/* ── Chrome blocks (visual header/footer editor): logo / menu / auth ── */
.topbar--custom { position: sticky; top: 0; z-index: 50; }
.w-logo { display: inline-flex; align-items: center; text-decoration: none; color: inherit; }
.w-menu { display: flex; align-items: center; gap: 4px; position: relative; }
.w-menu-links { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.w-menu-links a { padding: 8px 14px; border-radius: 8px; font-size: 15px; font-weight: 600; color: inherit; text-decoration: none; opacity: .85; white-space: nowrap; }
.w-menu-links a:hover, .w-menu-links a.active { opacity: 1; background: rgba(125,125,125,.14); }
.w-menu-burger { display: none; cursor: pointer; font-size: 22px; line-height: 1; padding: 5px 10px; border-radius: 8px; color: inherit; user-select: none; }
.w-authbtns { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
@media (max-width: 820px) {
    .w-menu { position: static; }
    .w-menu-burger { display: inline-flex; }
    .w-menu-links { display: none; position: absolute; top: 100%; left: 0; right: 0; flex-direction: column; gap: 2px; padding: 8px; background: var(--surface, #fff); border-top: 1px solid var(--border); box-shadow: 0 16px 40px rgba(0,0,0,.18); z-index: 60; max-height: 78vh; overflow: auto; }
    .w-menu-cb:checked ~ .w-menu-links { display: flex; }
}

/* ── Builder widgets (icon-list, counter, progress, rating, image-box, flip, price, alert, carousel) ── */
.w-iconlist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.w-iconlist li { display: flex; align-items: flex-start; gap: 10px; font-size: 15px; color: var(--text); line-height: 1.5; }
.w-il-ic { flex: none; }
.w-counter-num { font-size: 44px; font-weight: 900; color: var(--primary); line-height: 1; }
.w-counter-lbl { font-size: 14px; color: var(--text-soft, #6b7280); margin-top: 6px; }
.w-progress { display: flex; flex-direction: column; gap: 6px; }
.w-progress-top { display: flex; justify-content: space-between; font-size: 13px; font-weight: 700; color: var(--text); }
.w-progress-track { height: 10px; border-radius: 6px; background: var(--surface-2, #eef1f4); overflow: hidden; }
.w-progress-fill { display: block; height: 100%; border-radius: 6px; background: var(--primary); transition: width .6s ease; }
.w-rating-stars { font-size: 22px; letter-spacing: 2px; color: #d1d5db; }
.w-rating-stars .on { color: #f5b301; }
.w-rating-cap { margin-left: 8px; font-size: 13px; color: var(--text-soft, #6b7280); }
.w-imgbox-img { width: 100%; border-radius: 12px; margin-bottom: 14px; }
.w-imgbox-title { font-size: 19px; font-weight: 800; color: var(--text); }
.w-imgbox-text { font-size: 14px; color: var(--text-soft, #6b7280); margin: 8px 0 0; line-height: 1.6; }
.w-imgbox-link { text-decoration: none; color: inherit; display: block; }
.w-flip { perspective: 1200px; }
.w-flip-inner { position: relative; min-height: 240px; transition: transform .6s; transform-style: preserve-3d; }
.w-flip:hover .w-flip-inner { transform: rotateY(180deg); }
.w-flip-face { position: absolute; inset: 0; -webkit-backface-visibility: hidden; backface-visibility: hidden; border-radius: 16px; padding: 28px; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 8px; }
.w-flip-front { background: var(--surface-2, #f3f4f6); color: var(--text); }
.w-flip-back { background: var(--primary); color: #fff; transform: rotateY(180deg); }
.w-flip-ic { font-size: 36px; }
.w-flip-title { font-size: 20px; font-weight: 800; }
.w-flip-btn { margin-top: 10px; background: #fff; color: var(--primary); padding: 9px 18px; border-radius: 8px; font-weight: 700; text-decoration: none; }
.w-price { background: var(--surface, #fff); border: 1px solid var(--border, #e5e7eb); border-radius: 18px; padding: 30px 24px; text-align: center; box-shadow: 0 6px 24px rgba(0,0,0,.05); }
.w-price.is-featured { border-color: var(--primary); box-shadow: 0 14px 40px rgba(0,0,0,.12); }
.w-price-plan { font-size: 14px; font-weight: 800; text-transform: uppercase; letter-spacing: .5px; color: var(--text-soft, #6b7280); }
.w-price-amt { font-size: 46px; font-weight: 900; color: var(--text); margin: 10px 0 4px; }
.w-price-cur { font-size: 24px; vertical-align: super; }
.w-price-per { font-size: 15px; font-weight: 600; color: var(--text-soft, #6b7280); }
.w-price-feats { list-style: none; margin: 18px 0; padding: 0; display: flex; flex-direction: column; gap: 9px; font-size: 14px; color: var(--text); }
.w-price-btn { display: inline-block; background: var(--primary); color: #fff; padding: 12px 26px; border-radius: 10px; font-weight: 800; text-decoration: none; }
.w-alert { border-radius: 12px; padding: 14px 18px; border: 1px solid; }
.w-alert-title { font-weight: 800; margin-bottom: 3px; }
.w-alert-info { background: #eff6ff; border-color: #bfdbfe; color: #1e40af; }
.w-alert-success { background: #ecfdf5; border-color: #a7f3d0; color: #065f46; }
.w-alert-warning { background: #fffbeb; border-color: #fde68a; color: #92400e; }
.w-alert-danger { background: #fef2f2; border-color: #fecaca; color: #991b1b; }
.w-carousel { display: flex; gap: 14px; }
/* ── Horizontal scroller: the image carousel and a container's "scrolling row" ──
   Ohav, 2026-08-31: "without the bottom scroll dragger, rather arrows on left and right,
   and hovering over them moves the testimonials along". The bar is hidden in CSS, the
   arrows glide on hover and step on click (a phone has no hover, and still swipes).
   Behaviour: resources/js/site-widgets.js, delegated. */
.pb-scroller { position: relative; }
.pb-scroll-track { overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none; -ms-overflow-style: none;
    /* NO scroll-snap. Measured in Chrome 2026-08-31: with `x mandatory` OR `x proximity`,
       a hover glide of +7px per frame is re-snapped to the same rest point every frame and
       the track never moves — 210px of travel became 0. Snapping and a pixel glide cannot
       both exist; the glide is the feature Ohav asked for. */ }
.pb-scroll-track::-webkit-scrollbar { width: 0; height: 0; display: none; }
/* A slide with no explicit width still has to be a slide, not a squeezed column. */
.pb-scroll-track > .pf-col { flex: 0 0 min(86%, 420px); }
.pb-scroll-track > .pf-col { display: flex; }
.pb-scroll-track > .pf-col > * { flex: 1 1 auto; }
.pb-scroll-btn { position: absolute; top: 50%; left: 2px; transform: translateY(-50%); z-index: 3;
    width: 42px; height: 42px; padding: 0; border-radius: 50%; cursor: pointer;
    border: 1px solid var(--line, rgba(0,0,0,.09)); background: var(--card, #fff); color: var(--text, #111827);
    font-size: 24px; line-height: 1; display: flex; align-items: center; justify-content: center;
    box-shadow: 0 6px 18px rgba(0,0,0,.14); transition: opacity .18s ease, transform .18s ease; }
.pb-scroll-btn.is-next { left: auto; right: 2px; }
.pb-scroll-btn:hover { transform: translateY(-50%) scale(1.07); }
/* Nothing left that way — the arrow goes, it does not sit there doing nothing. */
.pb-scroller.at-start .pb-scroll-btn.is-prev,
.pb-scroller.at-end .pb-scroll-btn.is-next,
.pb-scroller.no-scroll .pb-scroll-btn { opacity: 0; pointer-events: none; }
@media (max-width: 767px) { .pb-scroll-btn { width: 36px; height: 36px; font-size: 20px; } }

.w-carousel-slide { flex: 0 0 80%; max-width: 520px; scroll-snap-align: center; }
.w-carousel-slide img { width: 100%; border-radius: 14px; display: block; }

/* ══ Long-list layout ══════════════════════════════════════════════════════════
   Sections stay wrapped rows while they're short and become browsable rails once
   there are more cards than anyone reads in a wall (App\Support\Site\Feed). The
   catalogue groups by time instead, leading with full cards and demoting the rest
   to compact rows — see site/partials/event-row.blade.php. */

/* End-cap: a rail with no visible end reads as "that's everything". */
.feed-endcap {
    flex: 0 0 auto; width: 168px; align-self: stretch; min-height: 220px;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
    border: 2px dashed var(--border); border-radius: var(--radius);
    text-decoration: none; color: inherit; background: transparent;
    transition: border-color .18s, transform .18s, background .18s;
}
.feed-endcap:hover { border-color: var(--primary); transform: translateY(-4px); background: color-mix(in srgb, var(--primary) 6%, transparent); }
.feed-endcap .fe-arrow { font-size: 22px; color: var(--primary); line-height: 1; margin-bottom: 6px; }
.feed-endcap .fe-count { font-size: 30px; font-weight: 800; letter-spacing: -1px; line-height: 1; }
.feed-endcap .fe-label { font-size: 12px; text-transform: uppercase; letter-spacing: .08em; opacity: .65; }
.feed-endcap .fe-cta { margin-top: 10px; font-size: 12.5px; font-weight: 700; color: var(--primary); }

/* Group heading on the catalogue. */
.feed-group-label { font-size: 15px !important; text-transform: uppercase; letter-spacing: .1em; opacity: .75; }

/* Compact rows — same hierarchy as the ticket, a tenth of the height. */
.event-rows { display: flex; flex-direction: column; gap: 8px; padding-bottom: 26px; }
.event-row {
    display: flex; align-items: center; gap: 14px; padding: 11px 14px;
    border: 1px solid var(--border); border-radius: var(--radius);
    text-decoration: none; color: inherit; background: var(--surface);
    transition: border-color .15s, transform .15s;
}
.event-row:hover { border-color: var(--primary); transform: translateX(2px); }
.event-row .er-date { flex: 0 0 46px; display: flex; flex-direction: column; align-items: center; line-height: 1.05; }
.event-row .er-mon { font-size: 10.5px; font-weight: 800; letter-spacing: .08em; color: var(--primary); }
.event-row .er-day { font-size: 20px; font-weight: 800; letter-spacing: -.5px; }
.event-row .er-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.event-row .er-title { font-weight: 700; font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.event-row .er-meta { display: flex; gap: 10px; flex-wrap: wrap; font-size: 12.5px; opacity: .68; }
.event-row .er-state {
    flex: 0 0 auto; font-size: 11px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
    padding: 5px 10px; border-radius: 999px; background: rgba(128,128,128,.14);
}
.event-row.is-going .er-state { background: rgba(34,197,94,.18); color: #16a34a; }
.event-row.is-pending .er-state { background: rgba(250,204,21,.2); color: #a16207; }
.event-row.is-soon .er-state { background: rgba(59,130,246,.16); color: #2563eb; }
.event-row.is-closed .er-state { opacity: .6; }
.event-row.is-open .er-state { background: color-mix(in srgb, var(--primary) 16%, transparent); color: var(--primary); }

@media (max-width: 640px) {
    .event-row .er-meta { font-size: 12px; }
    .event-row .er-meta span:nth-child(n+3) { display: none; }
    .feed-endcap { width: 132px; min-height: 180px; }
}

/* ══ Book a meeting ═══════════════════════════════════════════════════════════
   Where a "MEET FIRST" ticket sends you. Times grouped by day, because people
   scan for a day that works before they scan for an hour. */
.bm-wrap { padding-bottom: 60px; }
.bm-lead { font-size: 16px; margin: 0 0 18px; }
.bm-card { border: 1px solid var(--border); border-radius: var(--radius); padding: 26px; background: var(--surface); box-shadow: var(--shadow); max-width: 520px; }
.bm-done-title { font-size: 20px; font-weight: 800; }
.bm-done-when { font-size: 17px; font-weight: 700; color: var(--primary); margin: 6px 0 10px; }
.bm-back { display: inline-block; margin-top: 14px; font-size: 14px; text-decoration: none; color: var(--primary); font-weight: 600; }

.bm-gender { display: flex; gap: 10px; flex-wrap: wrap; }
.bm-gender button {
    flex: 1 1 160px; padding: 14px 18px; font: inherit; font-weight: 700; cursor: pointer;
    border-radius: var(--radius); border: 1.5px solid var(--border);
    background: transparent; color: inherit; transition: border-color .15s, transform .15s;
}
.bm-gender button:hover { border-color: var(--primary); transform: translateY(-2px); }

.bm-days { display: flex; flex-direction: column; gap: 18px; max-width: 620px; }
.bm-day-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 8px; }
.bm-day-head .d { font-weight: 800; font-size: 15px; }
.bm-day-head .s { font-size: 13px; opacity: .6; }
.bm-slots { display: flex; flex-wrap: wrap; gap: 8px; }
.bm-slot {
    padding: 10px 16px; font: inherit; font-weight: 700; font-size: 14px; cursor: pointer;
    border-radius: 999px; border: 1.5px solid var(--border);
    background: transparent; color: inherit; transition: border-color .15s, background .15s, transform .12s;
}
.bm-slot:hover:not(:disabled) { border-color: var(--primary); background: color-mix(in srgb, var(--primary) 10%, transparent); transform: translateY(-2px); }
.bm-slot:disabled { opacity: .45; cursor: default; }
.bm-slot.is-busy { opacity: 1; border-color: var(--primary); }

.bm-msg { margin-top: 18px; padding: 14px 16px; border-radius: var(--radius); font-weight: 600; max-width: 620px; }
.bm-msg.is-ok { background: rgba(34,197,94,.14); color: #16a34a; }
.bm-msg.is-err { background: rgba(239,68,68,.12); color: #dc2626; }

/* A block given a Min height in the editor must actually BE that tall — the height
   lands on the wrapper, while the block's own root (a hero <section> carries its own
   min-height and an absolutely-positioned background) sized itself to its content. The
   result was a taller box with the image stranded at its original height and empty
   space beneath. Stretch the child to the wrapper so backgrounds fill the space. */
.pb-block.has-minh { display: flex; flex-direction: column; }
.pb-block.has-minh > * { flex: 1 1 auto; min-height: 0; }

/* Booking page, responsive. The day list is the thing you scan, so it gets room to
   breathe on desktop and becomes a single column of tappable pills on a phone —
   44px minimum, because these are the only controls on the page that matter. */
@media (max-width: 640px) {
    .bm-card { padding: 20px; }
    .bm-slot { flex: 1 1 calc(33.333% - 6px); padding: 13px 10px; min-height: 44px; }
    .bm-gender button { flex: 1 1 100%; min-height: 48px; }
    .bm-days { gap: 22px; }
}
@media (prefers-reduced-motion: reduce) {
    .bm-slot, .bm-gender button, .event-row, .feed-endcap { transition: none; }
    .bm-slot:hover, .bm-gender button:hover, .feed-endcap:hover { transform: none; }
}

/* ── Featured (.sf-*) — the pinned event / trip / program, under the hero ──────
   Stage on the left, the rest of the pinned items as a real list on the right. The
   whole thing sits inside the normal content margins and is LIFTED so it overlaps the
   banner above it: that overlap is what stops a hero plus a featured row reading as
   two stacked bands, which was the objection that killed the full-width version.

   The turn-taking is CSS only. One keyframe window per position, one set per item
   count, so it needs no script, degrades to a static card at a count of one, and can
   never drift out of step with the list beside it. `visibility` rides along with
   `opacity` on purpose: a slide that is merely transparent is still focusable and
   still read aloud, so a keyboard user would tab through several invisible copies. */
.sf-sec { position: relative; z-index: 6; }
.sf-sec.is-overlap { margin-top: -46px; }
.sf-row { display: grid; grid-template-columns: 1fr; gap: 16px; }
.sf-stage { position: relative; border-radius: 20px; overflow: hidden; background: var(--surface-2);
    box-shadow: 0 18px 44px rgba(0, 0, 0, .24); min-height: 300px; }
.sf-slide { position: absolute; inset: 0; opacity: 0; visibility: hidden; }
.sf-im { position: absolute; inset: 0; background-size: cover; background-position: center;
    background-color: var(--primary-2, var(--primary)); animation: sf-burns 30s ease-in-out infinite; }
.sf-im.sf-noimg { background-image: linear-gradient(135deg, var(--primary), var(--primary-2, var(--primary))); }
@keyframes sf-burns { 0% { transform: scale(1.03); } 50% { transform: scale(1.1) translateY(-1%); } 100% { transform: scale(1.03); } }
/* Dark where the text is, not only at the very bottom edge: these photos are whatever
   the staff uploaded, and half of them are bright. */
.sf-sc { position: absolute; inset: 0;
    background: linear-gradient(180deg, rgba(0,0,0,.44) 0%, rgba(0,0,0,.10) 30%, rgba(0,0,0,.62) 62%, rgba(0,0,0,.93) 100%); }
.sf-bd { position: absolute; left: 24px; right: 24px; bottom: 22px; z-index: 4; color: #fff; }
.sf-k { display: block; font-size: 11px; font-weight: 900; letter-spacing: 1.8px; text-transform: uppercase;
    color: #FFD75A; margin: 0 0 6px; }
.sf-bd h3 { margin: 0 0 8px; font-size: 28px; font-weight: 900; letter-spacing: -.04em; line-height: 1.08; color: #fff; }
.sf-bd p { margin: 0 0 14px; font-size: 13.8px; line-height: 1.5; color: rgba(255,255,255,.9); max-width: 50ch; }
.sf-cta { display: inline-block; background: var(--primary); color: #fff; border-radius: 999px;
    padding: 10px 22px; font-size: 13.5px; font-weight: 800; text-decoration: none; }
.sf-cta:hover { filter: brightness(1.08); }
/* One colour per type, borrowed from the card each type already uses: event = brand
   crimson, trip = the boarding pass blue, program = the program card gold. Nothing new. */
.sf-chip { position: absolute; top: 14px; left: 14px; z-index: 5; font-size: 10px; font-weight: 900;
    letter-spacing: 1.4px; text-transform: uppercase; border-radius: 999px; padding: 5px 11px; color: #fff;
    background: rgba(0,0,0,.5); border: 1px solid rgba(255,255,255,.3); backdrop-filter: blur(8px); }
.sf-chip.is-event { background: var(--primary); border-color: transparent; }
.sf-chip.is-trip { background: #16395f; border-color: #38bdf8; color: #cbeafe; }
.sf-chip.is-prog { background: #1a1a1a; border-color: #FFD700; color: #FFD700; }
.sf-going { position: absolute; top: 14px; right: 14px; z-index: 5; font-size: 11.5px; font-weight: 800; color: #fff;
    background: rgba(0,0,0,.55); border: 1px solid rgba(255,255,255,.26); border-radius: 999px; padding: 4px 10px;
    backdrop-filter: blur(8px); }

/* The list. It sits on the page background, so it uses the site's own surface tokens
   and follows dark mode with everything else. */
.sf-side { display: flex; flex-direction: column; }
.sf-qh { font-size: 10px; font-weight: 900; letter-spacing: 1.6px; text-transform: uppercase;
    color: var(--text-soft); margin-bottom: 8px; }
.sf-queue { display: flex; flex-direction: column; gap: 9px; flex: 1; }
.sf-q { display: flex; gap: 11px; align-items: center; padding: 9px 11px; border-radius: 14px;
    border: 1px solid var(--border); background: var(--surface); text-decoration: none; color: inherit; }
.sf-qim { flex: none; width: 58px; height: 46px; border-radius: 10px; background-size: cover;
    background-position: center; background-color: var(--primary); }
.sf-qim.sf-noimg { background-image: linear-gradient(135deg, var(--primary), var(--primary-2, var(--primary))); }
.sf-qt { min-width: 0; }
.sf-qk { display: block; font-size: 9px; font-weight: 900; letter-spacing: 1.1px; text-transform: uppercase;
    color: var(--primary); margin-bottom: 2px; }
.sf-q b { display: block; font-size: 13.5px; font-weight: 800; letter-spacing: -.02em; line-height: 1.22; color: var(--text); }
.sf-q i { display: block; font-style: normal; margin-top: 2px; font-size: 11px; color: var(--text-soft); }

/* ── the turn-taking. One set per item count; six seconds a turn either way ──── */
.sf-n1 .sf-s1 { opacity: 1; visibility: visible; }

@keyframes sf-2a { 0% { opacity: 1; visibility: visible } 47% { opacity: 1; visibility: visible } 50% { opacity: 0; visibility: hidden } 97% { opacity: 0; visibility: hidden } 100% { opacity: 1; visibility: visible } }
@keyframes sf-2b { 0% { opacity: 0; visibility: hidden } 47% { opacity: 0; visibility: hidden } 50% { opacity: 1; visibility: visible } 97% { opacity: 1; visibility: visible } 100% { opacity: 0; visibility: hidden } }
.sf-n2 .sf-s1 { animation: sf-2a 12s linear infinite; }
.sf-n2 .sf-s2 { animation: sf-2b 12s linear infinite; }

@keyframes sf-3a { 0% { opacity: 1; visibility: visible } 31% { opacity: 1; visibility: visible } 34% { opacity: 0; visibility: hidden } 97% { opacity: 0; visibility: hidden } 100% { opacity: 1; visibility: visible } }
@keyframes sf-3b { 0% { opacity: 0; visibility: hidden } 31% { opacity: 0; visibility: hidden } 34% { opacity: 1; visibility: visible } 64.6% { opacity: 1; visibility: visible } 67.6% { opacity: 0; visibility: hidden } 100% { opacity: 0; visibility: hidden } }
@keyframes sf-3c { 0% { opacity: 0; visibility: hidden } 64.6% { opacity: 0; visibility: hidden } 67.6% { opacity: 1; visibility: visible } 97% { opacity: 1; visibility: visible } 100% { opacity: 0; visibility: hidden } }
.sf-n3 .sf-s1 { animation: sf-3a 18s linear infinite; }
.sf-n3 .sf-s2 { animation: sf-3b 18s linear infinite; }
.sf-n3 .sf-s3 { animation: sf-3c 18s linear infinite; }

@keyframes sf-4a { 0% { opacity: 1; visibility: visible } 23% { opacity: 1; visibility: visible } 25% { opacity: 0; visibility: hidden } 98% { opacity: 0; visibility: hidden } 100% { opacity: 1; visibility: visible } }
@keyframes sf-4b { 0% { opacity: 0; visibility: hidden } 23% { opacity: 0; visibility: hidden } 25% { opacity: 1; visibility: visible } 48% { opacity: 1; visibility: visible } 50% { opacity: 0; visibility: hidden } 100% { opacity: 0; visibility: hidden } }
@keyframes sf-4c { 0% { opacity: 0; visibility: hidden } 48% { opacity: 0; visibility: hidden } 50% { opacity: 1; visibility: visible } 73% { opacity: 1; visibility: visible } 75% { opacity: 0; visibility: hidden } 100% { opacity: 0; visibility: hidden } }
@keyframes sf-4d { 0% { opacity: 0; visibility: hidden } 73% { opacity: 0; visibility: hidden } 75% { opacity: 1; visibility: visible } 98% { opacity: 1; visibility: visible } 100% { opacity: 0; visibility: hidden } }
.sf-n4 .sf-s1 { animation: sf-4a 24s linear infinite; }
.sf-n4 .sf-s2 { animation: sf-4b 24s linear infinite; }
.sf-n4 .sf-s3 { animation: sf-4c 24s linear infinite; }
.sf-n4 .sf-s4 { animation: sf-4d 24s linear infinite; }

/* The list row lights up in step with the stage. Border and shadow only, so the row
   never moves and the list cannot jitter while you are reading it. */
@keyframes sf-lit2a { 0%, 49.8% { border-color: var(--primary); box-shadow: 0 8px 20px rgba(0,0,0,.12) } 50%, 100% { border-color: var(--border); box-shadow: none } }
@keyframes sf-lit2b { 0%, 49.8% { border-color: var(--border); box-shadow: none } 50%, 100% { border-color: var(--primary); box-shadow: 0 8px 20px rgba(0,0,0,.12) } }
.sf-n2 ~ .sf-side .sf-q1 { animation: sf-lit2a 12s linear infinite; }
.sf-n2 ~ .sf-side .sf-q2 { animation: sf-lit2b 12s linear infinite; }

@keyframes sf-lit3a { 0%, 33.2% { border-color: var(--primary); box-shadow: 0 8px 20px rgba(0,0,0,.12) } 33.4%, 100% { border-color: var(--border); box-shadow: none } }
@keyframes sf-lit3b { 0%, 33.2% { border-color: var(--border); box-shadow: none } 33.4%, 66.5% { border-color: var(--primary); box-shadow: 0 8px 20px rgba(0,0,0,.12) } 66.7%, 100% { border-color: var(--border); box-shadow: none } }
@keyframes sf-lit3c { 0%, 66.5% { border-color: var(--border); box-shadow: none } 66.7%, 100% { border-color: var(--primary); box-shadow: 0 8px 20px rgba(0,0,0,.12) } }
.sf-n3 ~ .sf-side .sf-q1 { animation: sf-lit3a 18s linear infinite; }
.sf-n3 ~ .sf-side .sf-q2 { animation: sf-lit3b 18s linear infinite; }
.sf-n3 ~ .sf-side .sf-q3 { animation: sf-lit3c 18s linear infinite; }

@keyframes sf-lit4a { 0%, 24.8% { border-color: var(--primary); box-shadow: 0 8px 20px rgba(0,0,0,.12) } 25%, 100% { border-color: var(--border); box-shadow: none } }
@keyframes sf-lit4b { 0%, 24.8% { border-color: var(--border); box-shadow: none } 25%, 49.8% { border-color: var(--primary); box-shadow: 0 8px 20px rgba(0,0,0,.12) } 50%, 100% { border-color: var(--border); box-shadow: none } }
@keyframes sf-lit4c { 0%, 49.8% { border-color: var(--border); box-shadow: none } 50%, 74.8% { border-color: var(--primary); box-shadow: 0 8px 20px rgba(0,0,0,.12) } 75%, 100% { border-color: var(--border); box-shadow: none } }
@keyframes sf-lit4d { 0%, 74.8% { border-color: var(--border); box-shadow: none } 75%, 100% { border-color: var(--primary); box-shadow: 0 8px 20px rgba(0,0,0,.12) } }
.sf-n4 ~ .sf-side .sf-q1 { animation: sf-lit4a 24s linear infinite; }
.sf-n4 ~ .sf-side .sf-q2 { animation: sf-lit4b 24s linear infinite; }
.sf-n4 ~ .sf-side .sf-q3 { animation: sf-lit4c 24s linear infinite; }
.sf-n4 ~ .sf-side .sf-q4 { animation: sf-lit4d 24s linear infinite; }

@media (min-width: 901px) {
    .sf-row { grid-template-columns: 1fr 300px; height: 300px; }
    .sf-row.is-solo { grid-template-columns: 1fr; }
    .sf-stage { min-height: 0; }
    .sf-side { height: 100%; }
    /* The lift puts this label on the banner photo every time, so it is white by
       construction. Below 901px the section stacks under the banner and the token
       colour above is correct again. */
    .sf-qh { color: rgba(255, 255, 255, .88); text-shadow: 0 1px 6px rgba(0, 0, 0, .55); }
    .sf-q { flex: 1; }
}
@media (max-width: 900px) {
    .sf-sec.is-overlap { margin-top: -34px; }
    .sf-stage { min-height: 250px; }
    .sf-bd h3 { font-size: 23px; }
}
@media (prefers-reduced-motion: reduce) {
    .sf-im, .sf-slide, .sf-q { animation: none !important; }
    /* Never leave someone who asked for less motion staring at a stack of invisible
       slides: with the turn-taking off, the first pinned item is simply the one shown. */
    .sf-slide { opacity: 0; visibility: hidden; }
    .sf-s1 { opacity: 1 !important; visibility: visible !important; }
}

/* ── Sign-up cards + campus picker (site groups, 2026-08-30) ────────────────
   One question per card. Without the script every card is simply visible. */
.auth-card.wiz { display: flex; flex-direction: column; }
.wiz-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 18px; }
.wiz-step { font-size: 12px; font-weight: 800; letter-spacing: 1px; text-transform: uppercase; color: var(--primary); }
.dots { display: flex; gap: 6px; }
.dot { width: 9px; height: 9px; border-radius: 50%; background: var(--surface-2); }
.dot.on { background: var(--primary); }
.wiz-card { border: 0; padding: 0; margin: 0 0 6px; min-width: 0; }
.wiz-card h1 { font-size: 24px; font-weight: 800; color: var(--text); margin: 0 0 6px; line-height: 1.2; }
.wiz-sub { margin: 0 0 18px; color: var(--text-soft); font-size: 14px; }
.wiz-hint { font-size: 12.5px; color: var(--text-soft); margin-top: 10px; line-height: 1.5; }
.wiz-actions { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-top: 18px; }
.wiz-actions > span { flex: 1; }
.wiz-submit { width: auto; margin: 0; }
.campus-grid { display: grid; gap: 12px; }
.campus { display: flex; align-items: center; gap: 14px; border: 2px solid var(--border); border-radius: 14px; padding: 10px; cursor: pointer; background: var(--surface); color: var(--text); text-decoration: none; position: relative; }
.campus > span { flex: 1 1 auto; min-width: 0; }   /* a campus without a logo keeps its name on one line */
.campus img, .campus i { flex: none; }
/* The stepper hides cards and buttons with the hidden attribute; .btn sets display, which would win. */
.wiz [hidden] { display: none !important; }
.campus input { position: absolute; opacity: 0; width: 0; height: 0; }
.campus img { width: 96px; height: 68px; object-fit: contain; border-radius: 9px; background: var(--surface-2); padding: 8px; }
.campus b { display: block; font-size: 15px; }
.campus small { color: var(--text-soft); font-size: 12px; }
.campus i { width: 24px; height: 24px; border-radius: 50%; border: 2px solid var(--border); display: grid; place-items: center; font-style: normal; font-size: 13px; color: #fff; }
.campus:has(input:checked), .campus:hover { border-color: var(--primary); box-shadow: 0 0 0 4px color-mix(in srgb, var(--primary) 14%, transparent); }
.campus:has(input:checked) i { background: var(--primary); border-color: var(--primary); }
.campus:has(input:checked) i::before { content: "\2713"; }

