Commit Graph

233 Commits

Author SHA1 Message Date
popovskik b1a2a62f1b content: add real photos + captions to all Student Welcome Guide pages
Replace the "Image placeholder" boxes on all 30 guide subpages + the guide
landing hero with real, optimized photos and captions, EN/MK/SI (93 figures).

- 31 source photos (up to 18 MB) optimized to WebP (<=1400px, all <500 KB)
  as images/guide-<slug>.webp.
- Captions follow the Get-to-Know style: description + "Photo:/Фото:/Foto:"
  + linked source (or MSOS for own event photos). Photographer credits kept.
  MK/SI descriptions are translated (proofread welcome).
- CSS: move the banner crop from the figure onto the <img> so the caption
  shows below it (was clipped by the figure's fixed height + overflow).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 12:58:45 +02:00
popovskik 4721b3cc75 docs: master pre-launch to-do list (paused before go-live)
Consolidates outstanding items so nothing is lost during the pause: domain
decision, content placeholders, MK/SI proofread, GA4 setup, plus a record of
what's already hardened. Dev-only doc (docs/ excluded from deploy).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 10:56:58 +02:00
popovskik c092e65ae0 Merge pull request 'security: enforce Content-Security-Policy' (#13) from kristijan-dev into develop
Deploy to Production on Develop Push / deploy (push) Successful in 12s Details
2026-08-04 08:48:52 +00:00
popovskik 9877b4bbd6 security(.htaccess): enforce Content-Security-Policy (was report-only)
Switch CSP from Report-Only to enforcing, with an allowlist verified in a
browser against a server sending this exact header (0 violations across the
homepage, a YouTube project page, the assistant, MailerLite JSONP, GA/gtag,
and the Google Forms endpoint).

Adds the sources the old report-only policy was missing (and would have
broken if enforced blindly): Google Fonts (style/font), Font Awesome cdnjs
(style/font), MailerLite newsletter (script/connect), the Google Forms
endpoint in connect-src, plus object-src 'none'. Keeps 'unsafe-inline' for
the in-<head> consent bootstrap; the host allowlists + form-action/base-uri
are the real hardening on top of existing output escaping.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 10:48:23 +02:00
popovskik 15624454e8 Merge pull request 'security: force HTTPS + HSTS' (#12) from kristijan-dev into develop
Deploy to Production on Develop Push / deploy (push) Successful in 12s Details
2026-08-04 08:39:59 +00:00
popovskik 0c07b05b1f security(.htaccess): force HTTPS + add HSTS
- Redirect all plain-http requests to https (double condition guards against
  a redirect loop behind a TLS-terminating proxy).
- Add Strict-Transport-Security (6-month max-age, no preload/includeSubDomains
  so it stays easy to adjust) so browsers refuse http after the first visit.

Closes the "HTTPS everywhere" gap: previously http:// served in the clear.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 10:37:37 +02:00
popovskik 77dc3ae940 Merge pull request 'HOTFIX: restore live site (revert cross-domain redirect that 404'd)' (#11) from kristijan-dev into develop
Deploy to Production on Develop Push / deploy (push) Successful in 13s Details
2026-08-04 00:09:43 +00:00
popovskik f30c9c6155 hotfix(.htaccess): stop cross-domain redirect that 404'd the live site
The earlier "canonical domain" redirect forced msos.spletnimojster.si (where
the site is actually served) to msosorg.com, which does NOT yet host these
files — so every page 404'd. Replace it with a host-relative root -> /en/
redirect so the live domain serves the site again. A canonical-host redirect
can be re-added once msosorg.com is pointed at this same docroot.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 02:08:37 +02:00
popovskik a7dceb4f7b Merge pull request 'Pre-launch: security + health + a11y hardening & offline Ask MSOS assistant' (#10) from kristijan-dev into develop
Deploy to Production on Develop Push / deploy (push) Successful in 18s Details
Reviewed-on: #10
2026-08-04 00:02:42 +00:00
popovskik 55bc101410 feat(assistant): one-time disclaimer note + GA4 question-report guide
- Add a subtle disclaimer under the greeting (EN/MK/SI): "automated guide,
  can make mistakes — check the linked page for official steps." Shown once,
  not on every message, so it sets expectations without clutter. Persistent
  footer disclaimer stays.
- docs/GA4-ASSISTANT-REPORT.md: step-by-step for registering the custom
  dimensions and building the "top questions" + "unanswered questions"
  explorations in GA4 (dev-only doc, not deployed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 01:57:55 +02:00
popovskik 661943bb34 feat(assistant): v2 — query-language detection, analytics, chips, auto-index
Addresses real gaps found in testing (a Macedonian question on an English
page returned nothing):

- Detect the language of the QUESTION (Cyrillic -> MK; Slovene markers -> SI;
  else the page language) and load that language's index + curated answers.
  Fixes cross-language questions.
- Expand curated multilingual intents (now incl. enrolment/eVŠ, deadlines,
  health, "what is MSOS", etc.) with stem keywords for better paraphrase
  matching. MK/SI answers machine-drafted — proofread before launch.
- Suggested-question chips on open (localized) to guide users.
- Privacy-safe analytics: fire a GA4 'assistant_query' event ONLY after the
  visitor accepts cookies (q text, result type, question vs page language) so
  the team can see real FAQs and unanswered questions.
- Move the widget to bottom-left on pages with the floating "Become a member"
  CTA so they never overlap. Design polish (chips, typing dots, launcher pulse).
- CI: rebuild the search index on every deploy (setup-python + build script)
  so the assistant stays in sync with content automatically. Build script is
  now path-portable (no hardcoded path).

Verified in a headless browser: MK-on-EN now answers correctly, chips work,
analytics event fires only with consent, become-a-member offset applies,
zero console errors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 01:48:39 +02:00
popovskik f7f297bd65 feat: offline in-browser "Ask MSOS" assistant (no API, zero cost)
A privacy-friendly help widget that answers visitor questions from the
site's own content and links to the full page — runs 100% in the browser,
no API, no server, no per-token cost.

- tools/build_search_index.py: parses every EN/MK/SI page into ~720
  heading-level chunks per language -> assistant/index-<lang>.json
  (lazy-loaded only when the chat is opened; gzips to ~80 KB).
- assistant.js: dependency-free BM25 search + multilingual stopword
  filtering + a curated short-answer layer for common questions, plus an
  accessible chat widget (role=dialog, keyboard, aria). CSP-safe (self only).
- assistant.css: scoped .msa-* styles in the site's teal palette;
  responsive (full-screen panel on mobile).
- Injected on 208 pages (blog WIP excluded; picks it up when that lands).

Verified in a headless browser across EN/MK/SI: curated answers, search
fallback with correct ranking (rare terms win), correct deep links,
Cyrillic + Slovene diacritics, and zero console errors. Curated MK/SI
answers are machine-drafted — proofread before launch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 01:29:22 +02:00
popovskik cca6fd18aa fix: remove unwired "Play video" button from homepage (en/mk/si)
The homepage "Every Student Has a Story" section had a <button class=
"play-button"> with no handler and no video wired to it — clicking did
nothing. Remove the dead button; keep the team photo and section copy.
The story video can be wired back in later.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 01:00:44 +02:00
popovskik c4da5de491 a11y: make mobile menu toggle keyboard & screen-reader accessible
The mobile hamburger is a <div class="mobile-menu-icon"> with a click
handler, so it worked on tap but was invisible to keyboard and screen-reader
users. Expose it as a button in main.js: role="button", tabindex="0",
aria-label, aria-expanded toggling, and Enter/Space activation. Verified in
a headless browser (focusable, Enter opens, aria state flips).

Also adds docs/PRE-LAUNCH-CHECKLIST.md (dev-only, excluded from deploy):
inventory of remaining content placeholders for the public launch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 00:57:27 +02:00
popovskik 9ce7450aa1 health: fix broken pages, add image dimensions, a11y & SEO wins
Site-wide health pass (excludes in-progress blog work). Verified with a
local server + headless browser: Timeline, homepage and gallery pages load
with zero console errors and no layout distortion.

Render bugs
- Timeline page (en/mk/si): fix ../../../ paths that overshot the site root,
  so the main stylesheet and hero image load again.
- Meet Student Slovenia 2023 (en/mk/si): remove a <figure> referencing
  event3-photo-11.png, an image that was never uploaded (broken image).

Performance
- Add intrinsic width/height to 1039 raster <img> tags to prevent layout
  shift (CLS); 450 SVGs correctly skipped. Add a global
  `img { max-width:100%; height:auto }` safety net so aspect ratio is
  preserved and images never overflow.
- Preload the homepage hero (LCP) image on en/mk/si.
- Load Font Awesome non-blocking (media=print/onload swap) with a <noscript>
  fallback, on 225 pages.

Accessibility
- Add aria-label to 57 unlabeled newsletter email inputs.
- Add an sr-only <h1> to the three "My Route" pages (had no h1).
- Add an .sr-only utility class.

SEO
- Add meta descriptions to legal/msos-hub/support pages (en/mk/si).

Note: MK/SI meta descriptions are machine-drafted and should be proofread
by a native speaker before considering them final.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 00:31:27 +02:00
popovskik 168e4ce378 security: harden static site (headers, exposed-file cleanup, privacy)
Proactive security & health pass. No live/exploitable vulnerabilities were
found; these changes remove information-disclosure surfaces and add
standard hardening.

- Remove publicly-downloadable 1.1 MB full source dump (code_export.txt)
  and stray empty l.php; add code_export.txt to .gitignore.
- Exclude dev files/folders (*.sh, *.py, docs/, templates/, tools/,
  README.md) from the rsync deploy so they never reach the live server.
- .htaccess: add X-Frame-Options, Referrer-Policy, Permissions-Policy,
  and a report-only Content-Security-Policy; add defense-in-depth deny
  block for dev/VCS files (robots.txt & sitemap.xml left served).
- .htaccess: fix root redirect to canonical msosorg.com + /en/.
- Swap 4 project-page YouTube embeds to youtube-nocookie.com so no
  Google cookies are set before consent (GDPR).
- Add rel="noopener" to 30 team social links on the About Us pages.
- Harden esc() in my-route.js to also escape single quotes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 23:56:48 +02:00
popovskik c2b1b6eb5a Content cleanup: fix unclosed tags, remove em/en dashes, verify translations
- Fixed 3 SI event posts that were missing their </article> and </main> tags
- Replaced all punctuation em-dashes and spaced en-dashes (435 across 64 files)
  with commas; normalized a SI date range to a hyphen to match EN/MK
- Verified the new Gallery + in-post gallery content is fully translated in
  EN/MK/SI (headings, titles, links, nav labels) with no English leftovers

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 15:46:50 +02:00
popovskik ea1afcd6ae Merge pull request 'Hub redesign, Gallery, per-language logos, footer/menu fixes + mobile polish' (#9) from kristijan-dev into develop
Deploy to Production on Develop Push / deploy (push) Successful in 6s Details
Reviewed-on: #9
2026-08-03 13:38:56 +00:00
popovskik 9edd6daa52 Roll out "Photos from the event" gallery to all event posts (EN/MK/SI)
- Added the reusable lightbox gallery block to all 9 event posts in every
  language (27 pages): shows 5 thumbnails + "+N more", opens the full-screen
  viewer with the whole photo set
- Inserted inside <article> (before the author footer where present) so it
  never breaks the sidebar/article flex layout
- Handled 3 SI posts that were missing their </article> tag by anchoring on
  the newsletter section instead

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 15:24:37 +02:00
popovskik 1f5e031be9 In-post event gallery block + lightbox; mobile polish
- Reusable "Photos from the event" grid (shows 5 thumbnails + "+N more") that
  opens a full-screen lightbox (arrows / keyboard / swipe / Esc); added to the
  Meet Student Slovenia 2024 post as the pattern
- New css/components/_lightbox.css + setupLightbox() in main.js (injects one
  shared overlay, wires any .js-lightbox grid)
- Mobile polish: gallery albums go single-column on phones, two on tablets;
  event-gallery grid 3-up on mobile; lightbox sizing/controls tuned for small
  screens

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 15:16:28 +02:00
popovskik 24c77e6171 Gallery: distinct album cards, blue tint, hover lift, whole card links to story
- Each album is now a bordered card with a resting shadow and clear separation
- Blue brand tint over the cover photos; fades on hover so images brighten
- Whole card lifts with a stronger shadow on hover (album-level, not per image)
- Clicking anywhere on a card opens the event story page (removed the lightbox)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 14:49:28 +02:00
popovskik d048226daf Redesign gallery as Pinterest-style album collage cards
- Each album is now a compact collage card (1 large + 2 small photos) with a
  "+N" overlay on the last tile; multiple cards per row (responsive grid)
- Title + photo count + "Read the story" link under each card
- All album photos remain in the DOM (hidden) so the lightbox still browses
  the full set; clicking any tile opens the lightbox at that photo

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 14:43:04 +02:00
popovskik d085e3376a Add Gallery page (per-event albums + lightbox); remove video-thumbnail blur
- New multilingual Gallery page (en/mk/si) with 9 event albums and a
  keyboard-accessible lightbox (prev/next scoped per album)
- Reuses existing event photos; links each album to its event post
- New css/pages/_gallery.css + setupGallery() lightbox in main.js
- "Gallery" link added to the "What We Do" nav (desktop + mobile) site-wide
- Gallery URLs added to sitemap.xml with hreflang
- Landing "Every Student Has a Story": removed backdrop blur on the video
  thumbnail, kept the bluish gradient tint

Note: images/original/ (458 MB of raw source photos, gitignored + unused by
the site) moved out of the working tree to reclaim disk.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 14:28:53 +02:00
popovskik f5dfd8830e Hub redesign, per-language logos, partner carousel, footer + menu fixes
MSOS Hub page:
- "What you can do here": Porsche-style vertical image cards in a
  continuous auto-scrolling marquee with edge fades (real photos placeholders)
- "A glimpse of the space": full-bleed band of 4 connected photos
- "A space we built together": full-bleed image banner with blue gradient overlay
- "Made possible by": partner logo tiles (Cultural Association + Ministry);
  processed Ministry + Cultural Association logos from source art
- Copy/spacing polish; removed em-dashes; larger section spacing; deeper
  final-CTA gradient so it no longer blends into the footer

Branding / partners:
- Per-language MSOS logos (SVG) in header + footer across all pages
- Partner carousel: added Ministry (wide variant), Cultural Association,
  Embassy of North Macedonia, and Spletni Mojster (width-capped); de-duplicated
  logos within each marquee group so new logos appear sooner

Footer:
- Build credit line (Spletni Mojster + Kristijan), clean centered text
- Synced MK/SI footers to EN (added missing About us + Timeline links)

Landing page:
- FAQ short CTA already avatar design (FAQ page kept its Email/Viber block)
- Swapped blurry stock video thumbnail for the real team photo
- Removed the intentional hero-background blur

Navigation:
- Mobile menu: use 100dvh so the language selector is reachable with submenus open
- Desktop: dropdown parents no longer navigate to dead "/#" links

Language suggestion banner:
- Dismissible, browser-language based banner suggesting the matching locale;
  remembers choice in localStorage and waits for the cookie-consent choice
  to avoid overlapping the consent card

Removed stale *.html.bak backup files.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 14:06:53 +02:00
popovskik 8a32c10273 Merge pull request 'Policy accuracy (GA/consent), dual contact email, footer dedup' (#8) from kristijan-dev into develop
Deploy to Production on Develop Push / deploy (push) Successful in 6s Details
Reviewed-on: #8
2026-08-03 08:39:13 +00:00
popovskik 7c32f416f5 Fix mobile top spacing (double header offset) + CTA/newsletter gap
On mobile, body already has padding-top:60px to clear the fixed header, but
every page ALSO added its own clearance — doubling it and leaving a ~60px
white gap under the menu (content sat too low). Trimmed each page's mobile
top offset so it relies on the body padding (matching .article-page, which
was already correct): page-content, support/hub/legal pages, and the
news-hub / news-article / blog / member heroes. Content now sits ~32-42px
under the header.

Also add a 32px top gap to .newsletter-cta on mobile so it no longer
touches the CTA/content above it.

CSS only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 01:31:49 +02:00
popovskik 04f7653001 Support page: full legal account-holder name + fix partners spacing
- Account holder on the bank card now shows the full legal name (…za
  študentsko podporo in kulturno sodelovanje), matching the Official
  information page, in all three languages
- Fix cramped spacing: the .sup-thanks rule had cut the partners section's
  bottom padding to 24px, pushing the logos against the teal CTA; raised to
  72px for clear separation

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 01:10:26 +02:00
popovskik f057e761cf Fix Official information page: hero layout, short name, SKD activity
- Fix the hero: override the global flex-row .container so the eyebrow,
  title and lead stack and centre (they were laid out in a row)
- Short name -> "Društvo MŠOS za študentsko podporo in kulturno sodelovanje"
  (official kratki naziv, normal case) instead of "MSOS"
- Add the main activity row: SKD 94.999 (activities of other membership
  organisations n.e.c.), and relabel S.15000 as the institutional sector
  (SKIS). All three languages.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 01:05:23 +02:00
popovskik 974daa59f3 Add Official information page (EN/MK/SI) + fill real bank details
New legal/registration reference page at /{lang}/legal/ with the official
details: legal name, registered office, registration number (4128133000),
tax number (44932448), VAT status, SKIS activity, registration date, bank
(NLB d.d.), IBAN SI56 0284 3026 6115 703, SWIFT LJBASI2X, representative,
and contact. New css/pages/_legal.css. Linked as "Official information" in
the footer legal bar on all pages.

Also fills the Support page's bank-transfer card with the same real IBAN/
bank/SWIFT (placeholders removed). SEO block + hreflang + sitemap (210
pages) regenerated.

MK/SI labels AI-drafted -> native review. SWIFT LJBASI2X is inferred from
the IBAN bank code (02 = NLB) -> please double-check.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 00:56:19 +02:00
popovskik de3b65fb15 Add MSOS Hub venue page (EN/MK/SI) + add to Who We Are menu
A promo page for the MSOS Hub — a renovated community/event space in
Ljubljana for gatherings up to 50 people. Sections: hero with quick facts,
the funding/partner story (Ministry of Foreign Affairs and Trade of North
Macedonia, Municipality of Ljubljana, Macedonian Cultural Association
"Macedonia"), what you can do here, what's inside (amenities), an image
placeholder gallery (photos pending — captioned), "made possible by", and a
booking CTA (mailto info@msosorg.com). New css/pages/_hub.css.

'MSOS Hub' added to the Who We Are dropdown (desktop + mobile) on all pages.
SEO block + hreflang + sitemap (207 pages) regenerated.

MK/SI translations are AI-drafted -> native review. Real photos to replace
the captioned placeholders when available.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 00:39:58 +02:00
popovskik b9dee56628 Add Support MSOS page (EN/MK/SI) and wire the header button
New donation/partnership landing page telling the MSOS story of being
community-built: hero, "built by the community" narrative, four ways to
support (partner/sponsor, donate, offer skills/space, spread the word),
"where your support goes" impact, a bank-transfer card (placeholder IBAN/
bank/SWIFT for the org to fill in), a partners thank-you marquee, and a
contact CTA (mailto info@msosorg.com). New css/pages/_support.css.

The header "Support MSOS" button (previously a dead <button>) now links to
/{lang}/support/ on all pages. SEO block + hreflang + sitemap regenerated.

MK/SI translations are AI-drafted -> native review. Bank details are
placeholders pending real IBAN/SWIFT.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-02 23:54:00 +02:00
popovskik 587fd3d197 Footer dedup, dual contact email, privacy-policy accuracy
- Remove the duplicate Privacy/Cookie links from the footer Organisation
  column; keep them (plus Manage cookies) in the bottom legal bar
- Show both info@msosorg.com and info.msosorg@gmail.com in the privacy +
  cookie policy prose (en/mk/si)
- Fix the privacy policy's now-false "no tracking cookies" sentence to
  reflect consent-based Google Analytics (en/mk/si)

MK/SI policy text is AI-drafted -> native review.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-02 23:28:04 +02:00
popovskik 7fe36cdb8e Update cookie policy to reflect Google Analytics + consent banner
The policy previously claimed the site set no tracking/analytics cookies
and showed no consent banner - both untrue after adding GA4. Updated
en/mk/si: revised "how we use cookies", added an Analytics cookie type
and a Google Analytics third-party entry (_ga/_gid, Consent Mode), and
rewrote the consent section to describe the banner + "Manage cookies"
withdrawal. Bumped last-updated date. MK/SI text AI-drafted -> review.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-02 23:08:56 +02:00
popovskik bc8a98fef4 Merge pull request 'SEO foundation, analytics + consent, bank-account blog, MK/SI translations' (#7) from kristijan-dev into develop
Deploy to Production on Develop Push / deploy (push) Successful in 6s Details
Reviewed-on: #7
2026-08-02 21:00:32 +00:00
popovskik 8067d6a354 Add "Manage cookies" footer link (GDPR consent withdrawal)
Adds a per-language "Manage cookies" link to the footer legal bar on all
201 pages, wired to window.msosOpenConsent() so visitors can change or
withdraw their choice at any time (GDPR requirement). Verified: decline ->
re-open via link -> accept flips analytics consent to granted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-02 22:17:13 +02:00
popovskik f24fc704d6 Add GDPR cookie-consent banner (Consent Mode v2)
- consent.js: self-contained, non-blocking bottom banner in EN/MK/SI,
  remembers the choice in localStorage, links to the per-language cookie
  policy. Accept -> gtag consent 'update' granted; Decline stays denied.
- Head GA snippet restores a returning visitor's prior "granted" choice
  before the first hit; loads /consent.js on every page.
- Re-openable via window.msosOpenConsent() for a "manage cookies" link.

Verified in-browser: shows for new visitors, Accept grants + remembers,
reload keeps consent without re-prompting, Slovene text + /si/ policy link.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-02 18:30:35 +02:00
popovskik 9a6d2c335c Add Google Analytics 4 (G-WVYV807VSS) with Consent Mode v2
- gtag.js injected on all 201 pages via tools/seo_inject.py + on 404.html
- Consent Mode v2 defaults all storage to 'denied' (EEA-safe: tag loads,
  no tracking cookies until a consent banner grants analytics_storage)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-02 12:52:19 +02:00
popovskik 788084e094 Add article dates, brand OG image, launch SEO checklist
- Add datePublished/dateModified to Article JSON-LD on the 11 dated
  articles (curated once from EN, applied to all languages)
- Replace og-default.jpg with the official brand OG image (1200x630)
- Add docs/launch-seo-checklist.md (go-live steps: redirects, Search
  Console, analytics, rich-result validation, monitoring)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-02 12:38:20 +02:00
popovskik 6e8b8befe6 Add .htaccess: branded 404, compression, caching, MIME types
Appends static-site production defaults below the existing root->/en/
redirect: ErrorDocument 404 /404.html, gzip compression, browser caching
(short for CSS/JS since unhashed, longer for images/fonts), correct WebP/
SVG/manifest MIME types, -Indexes, and X-Content-Type-Options. All guarded
by <IfModule> so a missing module cannot 500; ignored by nginx.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-02 12:26:27 +02:00
popovskik 314667f692 SEO polish: OG image, favicons, 404, article schema, image optimization
- Add branded 1200x630 og-default.jpg; article pages use their hero as
  og:image, others use the default
- Wire the existing (previously unlinked) favicon set into every page
- Add branded 404.html with root-absolute paths + noindex
- Emit Article + localized BreadcrumbList JSON-LD on all article pages
- Convert 74 heavy served photos to WebP (28MB -> 8.5MB, -70%), rewrite
  references, add loading=lazy/decoding=async to below-fold images and
  fetchpriority=high to heroes (protect LCP)
- Stop tracking images/original/ (458MB of unused source masters; kept on
  disk, gitignored) and ignore .playwright-mcp/

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-02 12:15:53 +02:00
popovskik b393859467 Add technical SEO foundation, MK/SI about-us + timeline, content fixes
SEO (all 201 pages, en/mk/si):
- Inject canonical, hreflang (en/mk/sl + x-default), Open Graph, Twitter
  cards and Organization JSON-LD via idempotent SEO:START/END block
- Generate multilingual sitemap.xml (xhtml:link alternates) + robots.txt
- Curated meta descriptions for lead-less pages (home, become-a-member,
  faq, news hub, my-route); every page now has a description
- Absolute URLs target final domain msosorg.com, not the temp host
- Add reusable tools/seo_inject.py (+ README)

Content fixes:
- Translate about-us and timeline-and-milestones into MK + SI, wire up
  their pages, and repair the previously-dead "Who We Are" nav links
  across all mk/si pages
- Remove duplicate en/projects/makedonska-studentska-vecer-vo-ljubljana
  (unreferenced; already covered by macedonian-student-night-in-ljubljana)

Locale correctness:
- Normalise Slovene pages to <html lang="sl"> (correct ISO 639-1)
- Map sl->si in main.js so the language-switcher highlight and newsletter
  i18n keep working on Slovene pages (data-lang="si" still maps to /si/)

MK/SI translations and descriptions are AI-drafted; flag for native review.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-02 11:43:10 +02:00
popovskik 31487ad83e Add "How to open a Slovenian bank account" blog post (EN/MK/SI)
- New scrollspy article page in all three languages, with guide-style
  warning callout, sourced link list + last-checked line, and standard
  author + newsletter blocks
- Blog listing featured card now links to the article and shows the hero
  photo + read-time instead of the "coming soon" placeholder
- Add hero image and cropped MSOS emblem avatar; add .blog-read-time and
  .blog-feat-thumb--image styles

MK/SI translations are AI-produced and need a native-speaker proofread.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-02 10:37:45 +02:00
popovskik 75722d064b Merge pull request 'Homepage refresh, newsletter rollout, pagination + Events/Projects redesign' (#6) from kristijan-dev into develop
Deploy to Production on Develop Push / deploy (push) Successful in 1m28s Details
Reviewed-on: #6
2026-08-01 18:33:11 +00:00
popovskik e1d596751a Pagination fixes, blog page chooser, Events & Projects redesign
Pagination
- Fix the broken mobile layout on News & Projects: page numbers on top,
  Previous / Next side-by-side below (shared .pagination component)
- Add a page chooser to the Blog: rewrite blog-filter.js to combine the
  topic filter with client-side pagination (page size 6), add the pager
  markup (all 3 languages) and .blog-pagination styles; it auto-hides
  when a topic has one page

Events & Projects — match the Blog/News design
- Hero: uppercase letter-spaced eyebrow, sentence-case bold title, lead
  subtitle, soft gradient; drop the redundant hero subscribe form and the
  placeholder copy (signup still available in the bottom newsletter CTA);
  align MK/SI titles to "Events & projects"
- Filters: News-style pills (dark active), left-aligned, with the thin
  separator line below; .filter-inner wrapper aligns pills/separator with
  the grid
- Spacing: reduce the gap under the header, add space below the filter so
  the separator / Events sub-filter no longer collide with "All our
  projects" (these hero/spacing tweaks also tidy the shared About/Get-to-know/
  Timeline heroes)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-01 20:30:47 +02:00
popovskik 9e8cbc5876 Homepage refresh, activities redesign + newsletter rollout
Navigation
- Replace "Donate" with a "Support MSOS ❤️" CTA site-wide
- Remove dead nav links (Gallery, Press releases)
- Turn the one-item News dropdown into a direct link

Homepage
- Replace the non-functional "Become part" contact form with a
  "Find your people in Slovenia" join CTA (blue/white gradient band,
  orange button, photo collage), in all three languages
- Fix the placeholder Activities subtitle
- Redesign Activities into card-style tabs with icons; move per-tab
  content into HTML panels and switch by index so the tabs work in
  every language (MK/SI tabs were previously dead)

Newsletter (MailerLite)
- Add the subscribe block to the News hub, news articles, and every
  events/projects page and hub, in all three languages
- Resize/rebalance the block, shrink the privacy line, add top spacing
- Standardise on honest copy (drop the "2,000+ subscribers" claim)
- Load main.js on the News hub pages (they shipped without it, so the
  form and header dropdowns didn't work there)
- Fix a dead privacy-policy link on the makedonska-vecer page
- Document the signup convention in docs/newsletter-signup.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-01 19:51:59 +02:00
popovskik 72c5c1a3d6 Merge pull request 'Become a Member polish: bento benefits, merged/redesigned join form, floating CTA, header + nav fixes' (#5) from kristijan-dev into develop
Deploy to Production on Develop Push / deploy (push) Successful in 1m8s Details
Reviewed-on: #5
2026-08-01 11:24:39 +00:00
popovskik f492a8a547 Become a Member: bento benefits, merged/redesigned join form, floating CTA, fixes
Why become a member
- Rebuild the benefits grid as a 3x3 bento: 7 icon cards + 2 real event photos
  (with captions), fixes the orphan card, adds hover motion. Swap the blank
  fa-house-heart (Pro) for fa-house-user (Free) on "Feel at home".

Join form
- Merge the duplicate "There is a place for you here" section into the form's
  path step (student / supporter cards now carry the descriptions); drop the
  separate section. New heading "There is a place for you here"; centred layout.
- Redesign the choice cards: colour-coded (student orange / supporter teal)
  icon circles, descriptions, hover lift + "Choose this" reveal.
- Fix the stray "Support MSOS" submit button showing on the path step.

Conversion + polish
- Floating "Become a member" CTA that appears after the hero and hides near the
  form/final CTA, so the ask stays reachable without scrolling to the bottom.
- More space between section titles and their cards (numbers, reals, tests,
  showcase, benefits).
- Testimonials: Elena -> Katerina (Koper); un-swap Ana (Maribor) and Marko
  (Ljubljana); remove the "sample quotes" placeholder note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-01 13:14:36 +02:00
popovskik ab2056dda3 Merge pull request 'Become a Member page, minimum-income update + announcement, mobile & nav/header/hero fixes' (#4) from kristijan-dev into develop
Deploy to Production on Develop Push / deploy (push) Successful in 1m7s Details
Reviewed-on: #4
2026-08-01 10:33:30 +00:00
popovskik 51474b2da5 Polish Become a Member hero: full-bleed gradient, button sizing + interaction, remove tag pills
- Hero gradient now spans edge to edge (full-viewport ::before band behind the
  centred content) and is more colourful/on-brand (warm peach to soft teal).
- Both hero CTAs (Become a member / See what we do) share one size so they align.
- Add hover (lift + shadow + colour shift) and active (press) states to the
  reusable .btn classes, so all buttons site-wide get consistent feedback; plus
  a focus-visible outline for keyboard users.
- Remove the confusing Community/Events/Support/... tag pills (they duplicated
  the hero lead sentence). member.js updated + now emits main.js on the member
  pages so regeneration keeps the nav working.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-01 12:29:59 +02:00
popovskik d35324f988 Remove "Get Involved" nav dropdown + full-width header alignment
- Remove the "Get Involved" dropdown (Become a member / Support MSOS): dead
  href="#" links that duplicated the top-right buttons. Swept site-wide
  (desktop + mobile, en/si/mk) - 390 blocks across 195 pages, including the
  privacy-policy header the generators slice from, so regeneration stays clean.
  Nav is now Who We Are / What We Do / For Students / News + the two buttons.
- Header now spans the full page width: logo + text menus flush left, buttons +
  language switcher flush right (was constrained to a centred 1280px container,
  which left the logo floating inward on wide screens). CSS-only in _header.css,
  scoped so the mobile hamburger layout is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-01 12:06:59 +02:00