Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"format": "prettier --write src"
"format": "prettier --write ."
},
"keywords": [],
"author": "",
"license": "ISC",
"packageManager": "pnpm@10.10.0",
"dependencies": {
"@fontsource-variable/jetbrains-mono": "^5.2.8",
"@fontsource-variable/outfit": "^5.2.8",
"@tailwindcss/vite": "^4.1.18",
"animejs": "^4.2.2",
"astro": "^5.16.8",
Expand Down Expand Up @@ -45,4 +46,4 @@
}
]
}
}
}
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added public/logoBAD.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 15 additions & 29 deletions src/layouts/Layout.astro
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
import '../style/global.css'
import '@fontsource-variable/jetbrains-mono'
import '@fontsource-variable/outfit'
import { ClientRouter } from 'astro:transitions'

interface Props {
title: string
description?: string // Optional (?)
description?: string
}

const { title, description = 'PyconES 2026' } = Astro.props
Expand All @@ -17,7 +17,7 @@ const { title, description = 'PyconES 2026' } = Astro.props
<meta charset="UTF-8" />
<meta name="description" content={description} />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="/2026.es.pycon.org/favicon.svg" />
<link rel="icon" type="image/png" href="/logoBAD.png" />
<meta name="generator" content={Astro.generator} />

<title>{title}</title>
Expand All @@ -26,37 +26,23 @@ const { title, description = 'PyconES 2026' } = Astro.props
</head>

<body
class="bg-slate-900 text-white antialiased h-screen flex flex-col justify-center bg-linear-to-r from-gray to-blue-900 bg-radial"
class="bg-[#1C1514] text-white antialiased h-screen flex flex-col justify-center overflow-hidden selection:bg-pycon-orange selection:text-white"
>
<slot />
<div
class="absolute inset-0 z-0 opacity-[0.03] pointer-events-none mix-blend-overlay"
style="background-image: radial-gradient(#ffffff 1px, transparent 1px); background-size: 34px 34px;"
>
</div>

<div class="relative z-10 w-full h-full flex flex-col justify-center items-center">
<slot />
</div>
</body>
</html>

<style is:global>
/* Global CSS styles (Vanilla CSS) */

:root {
/* If you want to define native CSS variables */
--accent: 136, 58, 234;
}

html {
font-family: system-ui, sans-serif;
scroll-behavior: smooth; /* Smooth scroll when navigating by anchors (#) */
}

/* Scrollbar customization (optional, Midudev style) */
::-webkit-scrollbar {
width: 10px;
}
::-webkit-scrollbar-track {
background: #0f172a;
}
::-webkit-scrollbar-thumb {
background: #334155;
border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover {
background: #475569;
font-family: 'Outfit Variable', system-ui, sans-serif;
scroll-behavior: smooth;
}
</style>
190 changes: 75 additions & 115 deletions src/pages/index.astro
Original file line number Diff line number Diff line change
@@ -1,164 +1,124 @@
---
import Layout from '../layouts/Layout.astro'
import '@fontsource-variable/jetbrains-mono'
import '@fontsource-variable/outfit'
import { SPONSORS_EMAIL } from './constants'
---

<Layout title="PyConES 2026">
<main class="min-h-screen flex flex-col justify-center items-center text-center px-4">
<div class="relative z-10 max-w-3xl">
<main class="flex flex-col justify-center items-center text-center px-4 w-full h-full">
<div class="flex flex-col items-center gap-2">
<img src="/logoBAD.png" alt="PyConES 2026" class="w-32 h-auto" />

<h1
class="text-4xl md:text-7xl font-bold text-white font-mono tracking-tighter cursor-default"
aria-label="PyConES 2026"
class="font-sans font-bold tracking-tighter leading-none text-white flex flex-col items-center"
aria-label="PyCon Barcelona 2026"
>
<span aria-hidden="true" data-value="PyConES 2026" id="matrix-text"> PyConES 2026 </span>
<div class="text-8xl md:text-9xl flex items-baseline relative z-10 ml-[-0.05em]" aria-hidden="true">
<span>P</span>
<span class="relative mx-[1px]">
y
<span
class="absolute top-[62%] left-[10%] w-[50%] h-[10%] bg-[#1C1514] -rotate-45 pointer-events-none block"
></span>
</span>
<span>C</span>
<span class="relative mx-[2px]">
o
<span
class="absolute top-[35%] left-[42%] w-[12%] h-[50%] bg-white rotate-[30deg] rounded-sm pointer-events-none block"
></span>
</span>
<span>nES</span>
</div>

<div class="flex items-center justify-center gap-4 mt-2 w-full pl-2" aria-hidden="true">
<span class="text-3xl md:text-5xl font-medium tracking-[0.2em] uppercase text-white">
Barcelona
</span>
<div class="flex flex-col text-sm md:text-base font-bold leading-[0.85] text-white/90 text-left">
<span class="text-2xl -mb-2">20</span>
<span class="text-2xl">26</span>
</div>
</div>
</h1>

<h2
id="subtitle-container"
class="mt-4 text-xl md:text-2xl text-green-400 font-mono h-8 flex justify-center items-center gap-2"
aria-live="polite"
aria-busy="true"
<div
class="mt-8 flex items-center gap-3 text-lg md:text-xl font-medium tracking-widest uppercase text-white/90"
>
<span aria-hidden="true" class="select-none">&gt;</span>
<span id="subtitle">Initialising system...</span>
<span class="animate-pulse motion-reduce:animate-none" aria-hidden="true">_</span>
</h2>
<span class="w-1.5 h-1.5 rounded-full bg-[#F06449]"></span>
<span>Sede UB</span>
<span class="text-[#F06449] mx-1">•</span>
<span>6-8 Noviembre</span>
<span class="w-1.5 h-1.5 rounded-full bg-[#F06449]"></span>
</div>

<div
id="actions"
class="mt-12 flex flex-col md:flex-row gap-6 justify-center items-center opacity-0 transition-opacity duration-1000 ease-in"
class="mt-12 opacity-0 motion-safe:animate-fade-in motion-reduce:opacity-100 relative"
>
<button
id="sponsor-btn"
type="button"
data-email={SPONSORS_EMAIL}
aria-describedby="sponsor-hint"
class="group relative px-7 py-2 bg-green-500 text-black font-mono font-bold text-lg hover:bg-green-400 transition-all duration-300 shadow-[0_0_15px_rgba(34,197,94,0.5)] hover:shadow-[0_0_25px_rgba(34,197,94,0.8)] cursor-pointer focus:outline-none focus:ring-4 focus:ring-green-300/50 rounded-sm"
class="group px-7 py-3 bg-white text-[#1C1514] font-sans font-bold text-lg rounded-full
hover:bg-[#F06449] hover:text-white transition-all duration-300 shadow-lg cursor-pointer
flex items-center gap-2
focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-[#F06449]/50"
>
<span
class="absolute inset-0 w-full h-full bg-white opacity-0 group-hover:opacity-20 transition-opacity pointer-events-none"
></span>

<span id="sponsor-text">
<span aria-hidden="true">&lt; </span><span lang="en">BECOME A SPONSOR</span><span
aria-hidden="true"
>
/&gt;</span
>
</span>
<span id="sponsor-hint" class="sr-only">Copia el email de contacto para patrocinadores</span>
<span id="btn-text">BECOME A SPONSOR</span>
</button>

<div
id="copy-confirmation"
role="status"
tabindex="-1"
class="hidden px-7 py-2 text-green-400 font-mono font-bold text-lg rounded-sm"
>
<span aria-hidden="true"> &lt;!-- </span><span lang="en">EMAIL COPIED!</span><span
aria-hidden="true"
>
--&gt;</span
>
</div>
<div id="copy-status" role="status" class="sr-only" aria-live="polite"></div>
</div>
</div>

<div
aria-hidden="true"
class="absolute inset-0 bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:24px_24px] pointer-events-none"
>
</div>
</main>
</Layout>

<script>
const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+'

let interval: number | null = null

const runMatrixEffect = (element: HTMLElement) => {
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches
if (prefersReducedMotion) return

let iteration = 0
clearInterval(interval as number)
const originalText = element.dataset.value || ''

interval = window.setInterval(() => {
element.innerText = originalText
.split('')
.map((_, index) => {
if (index < iteration) {
return originalText[index]
}
return letters[Math.floor(Math.random() * letters.length)]
})
.join('')

if (iteration >= originalText.length) {
clearInterval(interval as number)
}

iteration += 1 / 3
}, 30)
}

const init = () => {
const matrixText = document.getElementById('matrix-text')
const h1 = document.querySelector('h1')
const subtitle = document.querySelector('#subtitle')
const actions = document.querySelector('#actions')

if (matrixText && h1) {
runMatrixEffect(matrixText)
h1.onmouseover = () => runMatrixEffect(matrixText)
<style>
@media (prefers-reduced-motion: no-preference) {
.animate-fade-in {
animation: fadeIn 1s ease-out forwards;
animation-delay: 0.5s;
}
}

if (subtitle) {
setTimeout(() => {
subtitle.textContent = 'Sede UB Barcelona | 6-8 Nov 2026'
const container = document.getElementById('subtitle-container')
if (container) {
container.setAttribute('aria-busy', 'false')
}
if (actions) {
actions.classList.remove('opacity-0')
}
}, 1500)
@keyframes fadeIn {
to {
opacity: 1;
}
}
</style>

// COPY MAIL LOGIC
<script>
const init = () => {
const sponsorBtn = document.getElementById('sponsor-btn')
const copyConfirmation = document.getElementById('copy-confirmation')
const email = sponsorBtn?.dataset.email as string
const btnText = document.getElementById('btn-text')
const statusRegion = document.getElementById('copy-status')

const email = sponsorBtn?.dataset.email || 'sponsors@es.python.org'

if (sponsorBtn && copyConfirmation && email) {
if (sponsorBtn && btnText && statusRegion) {
sponsorBtn.onclick = async () => {
try {
await navigator.clipboard.writeText(email)

// Hide button, show confirmation
sponsorBtn.classList.add('hidden')
copyConfirmation.classList.remove('hidden')
copyConfirmation.focus()
const originalText = btnText.innerText

btnText.innerText = '¡Email Copiado!'
sponsorBtn.classList.add('bg-[#F06449]', 'text-white')
statusRegion.innerText = 'Email copiado al portapapeles'

setTimeout(() => {
// Hide confirmation, show button and restore focus
copyConfirmation.classList.add('hidden')
sponsorBtn.classList.remove('hidden')
sponsorBtn.focus()
btnText.innerText = originalText
sponsorBtn.classList.remove('bg-[#F06449]', 'text-white')
statusRegion.innerText = ''
}, 2000)
} catch (err) {
console.error('Failed to copy', err)
window.location.href = `mailto:${email}`
}
}
}
}

//not needed now
document.addEventListener('astro:page-load', init)
init()
</script>
5 changes: 5 additions & 0 deletions tailwind.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ export default {
extend: {
fontFamily: {
mono: ['"JetBrains Mono Variable"', 'monospace'],
sans: ['"Outfit Variable"', 'sans-serif'],
},
colors: {
'pycon-dark': '#0F172A', // Slate 900
'pycon-warm-dark': '#1C1514', // Un negro con tinte rojizo/marrón
'pycon-orange': '#F06449', },
},
},
plugins: [],
Expand Down