Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 961ad3351c | |||
| c75830185c |
BIN
public/about/whitehat.avif
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 31 KiB |
BIN
public/hero-dark.avif
Normal file
|
After Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 7.7 MiB |
BIN
public/hero-light.avif
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 14 MiB |
BIN
public/icon/pinkheart.avif
Normal file
|
After Width: | Height: | Size: 8.8 KiB |
BIN
public/projects/IMG_0170.avif
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
public/projects/epc-finale-broadcast.avif
Normal file
|
After Width: | Height: | Size: 76 KiB |
9
public/projects/tape.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="93.2438" height="130.333" viewBox="0 0 93.2438 130.333" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path id="Vector 9" opacity="0.8" d="M0.134946 107.562L62.0301 0.499498C62.4189 -0.173014 63.3926 -0.164787 63.7699 0.514198L66.8764 6.10337C67.0233 6.36771 67.2819 6.55136 67.5799 6.60293L73.4547 7.61956L79.6478 8.69127C79.7492 8.70881 79.8472 8.74187 79.9384 8.7893L92.7048 15.4239C93.2048 15.6838 93.3915 16.3053 93.1173 16.7977L30.1904 129.819C29.9013 130.339 29.2259 130.493 28.7403 130.15L16.029 121.185C15.8996 121.093 15.7937 120.973 15.72 120.832L10.9287 111.708C10.7928 111.449 10.5505 111.263 10.2655 111.198L0.778585 109.037C0.121886 108.888 -0.202153 108.145 0.134946 107.562Z" fill="url(#paint0_linear_0_6)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_0_6" x1="46.537" y1="-1.02762" x2="46.537" y2="130.791" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F1C8FF"/>
|
||||
<stop offset="1" stop-color="#FF92AD"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1 KiB |
BIN
public/side.avif
Normal file
|
After Width: | Height: | Size: 431 KiB |
BIN
public/side.png
|
Before Width: | Height: | Size: 8 MiB |
|
|
@ -1,145 +1,143 @@
|
|||
---
|
||||
import ExperienceRow from "@/components/ExperienceRow.astro";
|
||||
import { events } from "@/lib/events";
|
||||
|
||||
const sortedEvents = [...events].sort((a, b) => b.date.localeCompare(a.date));
|
||||
const years = [...new Set(sortedEvents.map((event) => event.date.slice(0, 4)))];
|
||||
// biome-ignore lint/correctness/noUnusedVariables: Used in the Astro template below.
|
||||
const eventsByYear = years.map((year) => ({
|
||||
year,
|
||||
events: sortedEvents.filter((event) => event.date.startsWith(year)),
|
||||
}));
|
||||
|
||||
// biome-ignore lint/correctness/noUnusedVariables: Used in the Astro template below.
|
||||
const getShortDate = (date: string) => {
|
||||
const [, month, day] = date.split("-");
|
||||
return `${month}.${day}`;
|
||||
};
|
||||
|
||||
const currentYear = new Date().getFullYear();
|
||||
// biome-ignore lint/correctness/noUnusedVariables: Used in the Astro template below.
|
||||
const daysUntilYearEnd = Math.ceil(
|
||||
(new Date(currentYear + 1, 0, 1).getTime() - Date.now()) /
|
||||
(1000 * 60 * 60 * 24),
|
||||
);
|
||||
---
|
||||
|
||||
<section
|
||||
id="about"
|
||||
data-node-id="4:104"
|
||||
class="min-h-full snap-start snap-always bg-background text-foreground lg:h-full lg:overflow-hidden"
|
||||
class="min-h-full snap-start snap-always bg-background text-foreground"
|
||||
aria-labelledby="about-title"
|
||||
>
|
||||
<div class="grid min-h-full grid-cols-1 lg:h-full lg:grid-cols-2">
|
||||
<div class="grid min-h-full grid-cols-1 lg:grid-cols-2">
|
||||
<div
|
||||
class="relative z-10 px-6 py-12 sm:px-10 lg:px-[clamp(52px,5.208vw,100px)] lg:py-[clamp(58px,9.26vh,100px)]"
|
||||
>
|
||||
<div
|
||||
class="max-w-[654px] text-[24px] leading-[1.2] tracking-[-0.02em] lg:leading-none"
|
||||
id="experience"
|
||||
class="max-w-[654px] break-keep text-[24px] leading-[1.2] tracking-[-0.02em] lg:leading-none"
|
||||
>
|
||||
<p id="about-title">저는 이런 것들을 해왔어요.</p>
|
||||
<p id="about-title">
|
||||
저는 <b>{years.length}년간 {events.length}개</b>의
|
||||
개성있는 조각들을 모아왔어요.
|
||||
</p>
|
||||
|
||||
<section class="mt-[0.75em]" aria-labelledby="security-title">
|
||||
<h2
|
||||
id="security-title"
|
||||
class="text-[inherit] font-bold leading-[inherit]"
|
||||
<section class="mt-[0.75em]" aria-label="Experience">
|
||||
{
|
||||
eventsByYear.map(({ year, events: yearEvents }) => (
|
||||
<section
|
||||
class="py-[0.55em]"
|
||||
aria-labelledby={`experience-${year}`}
|
||||
>
|
||||
Information security
|
||||
</h2>
|
||||
<div class="mt-[0.5em] flex flex-col gap-[0.34em]">
|
||||
<ExperienceRow year="2026" connector="wave">
|
||||
<img
|
||||
class="h-[1em] w-[1em] shrink-0"
|
||||
src="/about/layer7-mark.svg"
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span>선린인터넷고등학교 정보보안 동아리</span>
|
||||
<img
|
||||
class="h-[1em] w-[1em] shrink-0 [filter:var(--mono-filter)]"
|
||||
src="/about/layer7-wordmark.svg"
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span>Layer7</span>
|
||||
</ExperienceRow>
|
||||
|
||||
<ExperienceRow year="2026" connector="wave">
|
||||
<img
|
||||
class="h-[1em] w-[1em] shrink-0"
|
||||
src="/about/sunrin.svg"
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span>선린인터넷고등학교 정보보호과</span>
|
||||
</ExperienceRow>
|
||||
|
||||
<ExperienceRow year="2025" connector="line">
|
||||
<img
|
||||
class="h-[1em] w-[1em] shrink-0 object-contain"
|
||||
src="/about/whitehat.png"
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span>화이트햇스쿨 3기 이수</span>
|
||||
</ExperienceRow>
|
||||
<div class="flex items-center gap-3">
|
||||
<h3
|
||||
id={`experience-${year}`}
|
||||
class="text-[0.62em] font-bold leading-none"
|
||||
>
|
||||
{year}
|
||||
</h3>
|
||||
<span class="text-[0.43em] font-medium tracking-[0.04em] text-foreground/45">
|
||||
{yearEvents.length}{" "}
|
||||
{yearEvents.length === 1
|
||||
? "EVENT"
|
||||
: "EVENTS"}
|
||||
</span>
|
||||
<div class="h-px flex-1 bg-foreground/10" />
|
||||
</div>
|
||||
|
||||
<ol class="mt-[0.35em]">
|
||||
{yearEvents.map((event) => (
|
||||
<li class="grid min-w-0 grid-cols-[3.5em_minmax(0,1fr)] gap-x-[0.6em] border-b border-foreground/[0.07] py-[0.48em] last:border-b-0">
|
||||
<time
|
||||
class="pt-[0.08em] text-[0.55em] font-medium tabular-nums tracking-[0.02em] text-foreground/50"
|
||||
datetime={event.date}
|
||||
>
|
||||
{getShortDate(event.date)}
|
||||
</time>
|
||||
<div class="min-w-0">
|
||||
<div class="mb-[0.12em] flex items-center gap-[0.45em]">
|
||||
<span class="text-[0.43em] font-semibold tracking-[0.04em] text-foreground/50">
|
||||
{event.category}
|
||||
</span>
|
||||
{event.link && (
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="h-[0.52em] w-[0.52em] text-foreground/40"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M7 17 17 7" />
|
||||
<path d="M7 7h10v10" />
|
||||
</svg>
|
||||
)}
|
||||
</div>
|
||||
{event.link ? (
|
||||
<a
|
||||
href={event.link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="text-[0.62em] leading-[1.35] underline decoration-foreground/20 underline-offset-2 transition-colors hover:decoration-foreground focus-visible:rounded-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-foreground"
|
||||
>
|
||||
{event.description}
|
||||
</a>
|
||||
) : (
|
||||
<p class="text-[0.62em] leading-[1.35]">
|
||||
{event.description}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
{year === currentYear.toString() && (
|
||||
<div class="my-8 flex items-center gap-4">
|
||||
<div class="flex-1 h-px bg-foreground/10" />
|
||||
<span class="text-xs text-muted-foreground whitespace-nowrap">
|
||||
✨ | D-{daysUntilYearEnd}동안
|
||||
만들어나갈 멋진 것들을
|
||||
기대해주세요.
|
||||
</span>
|
||||
<div class="flex-1 h-px bg-foreground/10" />
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
<section class="mt-[0.75em]" aria-labelledby="software-title">
|
||||
<h2
|
||||
id="software-title"
|
||||
class="text-[inherit] font-bold leading-[inherit]"
|
||||
>
|
||||
Software engineering
|
||||
</h2>
|
||||
<div class="mt-[0.5em] flex flex-col gap-[0.34em]">
|
||||
<ExperienceRow year="2025" connector="line">
|
||||
<img
|
||||
class="h-[1em] w-[1em] shrink-0"
|
||||
src="/about/adofai.svg"
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span>ADOFAI.gg</span>
|
||||
<span class="text-foreground/70"
|
||||
>Full Stack, Mod Developer</span
|
||||
>
|
||||
</ExperienceRow>
|
||||
|
||||
<div
|
||||
class="grid min-w-0 grid-cols-[2.25em_0.55em_minmax(0,1fr)] items-start gap-[0.5em]"
|
||||
>
|
||||
<time class="whitespace-nowrap" datetime="2026"
|
||||
>2026</time
|
||||
>
|
||||
<img
|
||||
class="mt-[0.08em] h-[1em] w-[0.55em] [filter:var(--mono-filter)]"
|
||||
src="/about/contest-separator.svg"
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<div
|
||||
class="grid min-w-0 grid-cols-[1em_minmax(0,1fr)] items-start gap-[0.34em]"
|
||||
>
|
||||
<img
|
||||
class="mt-[0.22em] h-[0.55em] w-[1em] [filter:var(--mono-filter)]"
|
||||
src="/about/contest.svg"
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<div
|
||||
class="grid min-w-0 grid-cols-1 gap-[0.35em] lg:grid-cols-[minmax(11em,1.5fr)_minmax(8.6em,1fr)] lg:gap-[0.75em]"
|
||||
>
|
||||
<div
|
||||
class="flex flex-wrap content-start gap-x-[0.5em]"
|
||||
>
|
||||
<span>Effect Playing Contest</span>
|
||||
<span class="text-foreground/70"
|
||||
>2025 · Finale</span
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
class="flex flex-col text-foreground/70"
|
||||
>
|
||||
<span>Broadcast Engineer</span>
|
||||
<span>ARG Creator</span>
|
||||
<span>Full Stack Developer</span>
|
||||
<span>Mod Developer</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="relative h-[min(150vw,720px)] min-h-[600px] overflow-hidden lg:h-auto lg:min-h-0"
|
||||
class="relative order-first h-[min(150vw,720px)] min-h-[600px] overflow-hidden lg:sticky lg:top-0 lg:order-none lg:h-[calc(100svh-64px)] lg:min-h-0 lg:self-start"
|
||||
aria-label="활동 사진"
|
||||
>
|
||||
<img
|
||||
class="absolute inset-0 h-full w-full select-none object-contain"
|
||||
src="/side.png"
|
||||
class="absolute inset-0 h-full w-full select-none pointer-events-none object-contain"
|
||||
src="/side.avif"
|
||||
alt="활동 사진 콜라주"
|
||||
width="3840"
|
||||
height="4320"
|
||||
|
|
|
|||
222
src/components/EPCProjects.astro
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
---
|
||||
const videoUrl =
|
||||
"https://www.youtube.com/live/5HDW7u3xt6Y?si=SgPxg83YMdeqGo3t&t=8366";
|
||||
const roles = ["Broadcast Manager", "ARG Creator", "Developer"];
|
||||
---
|
||||
|
||||
<section
|
||||
id="projects"
|
||||
class="min-h-full snap-start bg-background text-foreground"
|
||||
aria-labelledby="projects-title"
|
||||
>
|
||||
<div class="grid min-h-full grid-cols-1 lg:grid-cols-2">
|
||||
<div
|
||||
class="px-6 py-12 sm:px-10 lg:px-[clamp(52px,5.208vw,100px)] lg:py-[clamp(58px,9.26vh,100px)]"
|
||||
>
|
||||
<div class="max-w-[654px] break-keep">
|
||||
<h2
|
||||
id="projects-title"
|
||||
class="mt-5 text-[clamp(32px,3.1vw,54px)] font-bold leading-[1.2] tracking-[-0.04em]"
|
||||
>
|
||||
무대 뒤에서,<br />경험을 만들면서...
|
||||
</h2>
|
||||
<p
|
||||
class="mt-6 max-w-[32rem] text-base leading-relaxed text-foreground/65"
|
||||
>
|
||||
불과 얼음의 춤(A Dance of Fire and Ice)의 이펙트 제작과
|
||||
플레이를 함께 다루는 대회, Effect Playing Contest. 2025와
|
||||
Finale 시즌에 참여하며 방송부터 ARG, 개발까지 함께했어요.
|
||||
</p>
|
||||
<ul
|
||||
class="mt-6 flex flex-wrap gap-x-4 gap-y-2 text-[13px] font-semibold"
|
||||
aria-label="담당 역할"
|
||||
>
|
||||
{
|
||||
roles.map((role) => (
|
||||
<li class="border-b-2 border-[#ff92ad]/60 pb-1">
|
||||
{role}
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
|
||||
<div class="mt-10 space-y-7">
|
||||
<article
|
||||
class="border-t border-foreground/15 pt-5"
|
||||
aria-labelledby="epc-finale-title"
|
||||
>
|
||||
<div
|
||||
class="mb-2 flex items-center gap-3 text-xs font-medium text-foreground/50"
|
||||
>
|
||||
<span>01</span><span>2026 · FINALE</span>
|
||||
</div>
|
||||
<h3
|
||||
id="epc-finale-title"
|
||||
class="text-[clamp(21px,1.7vw,28px)] font-bold tracking-[-0.025em]"
|
||||
>
|
||||
Effect Playing Contest : Finale
|
||||
</h3>
|
||||
<p
|
||||
class="mt-3 text-sm leading-[1.85] text-foreground/65"
|
||||
>
|
||||
달성이 주관하고 ADOFAI.gg가 공동 주최하는 EPC의
|
||||
마지막 시즌이에요.<br /> 방송 화면 개발과 운영을 맡고,
|
||||
대회의 퍼즐을 경험하는 ARG를 제작했었어요.
|
||||
</p>
|
||||
<a
|
||||
href="https://www.youtube.com/playlist?list=PLZeYZotn5_IM15cD3W2y5SAtI83xXE226"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="mt-4 inline-block text-sm font-semibold underline decoration-foreground/25 underline-offset-4 hover:decoration-current focus-visible:rounded-sm focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring"
|
||||
>Finale 영상 플레이리스트 <span aria-hidden="true"
|
||||
>↗</span
|
||||
></a
|
||||
>
|
||||
</article>
|
||||
|
||||
<article
|
||||
class="border-t border-foreground/15 pt-5"
|
||||
aria-labelledby="epc-2025-title"
|
||||
>
|
||||
<div
|
||||
class="mb-2 flex items-center gap-3 text-xs font-medium text-foreground/50"
|
||||
>
|
||||
<span>02</span><span>2025</span>
|
||||
</div>
|
||||
<h3
|
||||
id="epc-2025-title"
|
||||
class="text-[clamp(21px,1.7vw,28px)] font-bold tracking-[-0.025em]"
|
||||
>
|
||||
Effect Playing Contest 2025
|
||||
</h3>
|
||||
<p
|
||||
class="mt-3 text-sm leading-[1.85] text-foreground/65"
|
||||
>
|
||||
이펙트 제작자와 플레이어가 각자의 실력을 선보이는
|
||||
리듬 게임 대회입니다. 방송 화면의 대부분의 기능을
|
||||
개발하고, 방송 운영을 담당했습니다.
|
||||
</p>
|
||||
<a
|
||||
href="https://www.youtube.com/playlist?list=PLZeYZotn5_IOJDek6e35NKzUtJm09yxZD"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="mt-4 inline-block text-sm font-semibold underline decoration-foreground/25 underline-offset-4 hover:decoration-current focus-visible:rounded-sm focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring"
|
||||
>2025 영상 플레이리스트 <span aria-hidden="true"
|
||||
>↗</span
|
||||
></a
|
||||
>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="grid min-w-0 items-center overflow-hidden px-4 pt-8 pb-[52px] lg:sticky lg:top-0 lg:h-[calc(100svh-64px)] lg:min-h-[560px] lg:self-start lg:py-6 lg:pr-7 lg:pl-0"
|
||||
aria-label="EPC 방송과 ARG 작업 사진"
|
||||
>
|
||||
<div class="relative mx-auto aspect-[0.98] w-full max-w-[880px]">
|
||||
<figure
|
||||
class="absolute top-[9%] left-[6%] z-[2] m-0 w-[80%] -rotate-[5deg]"
|
||||
>
|
||||
<div
|
||||
class="aspect-video overflow-hidden rounded-xl bg-[#18141f] shadow-[0_12px_36px_#00000014]"
|
||||
id="epc-video"
|
||||
>
|
||||
<button
|
||||
class="group relative block h-full w-full cursor-pointer border-0 bg-transparent p-0 text-white focus-visible:outline-2 focus-visible:outline-offset-[-5px] focus-visible:outline-[#ff92ad]"
|
||||
type="button"
|
||||
aria-label="EPC Finale 결승 방송을 2시간 19분 26초부터 재생"
|
||||
>
|
||||
<img
|
||||
class="block h-full w-full object-cover"
|
||||
src="/projects/epc-finale-broadcast.avif"
|
||||
alt="EPC Finale의 두 선수 경기 화면과 실시간 판정을 보여주는 방송 화면"
|
||||
width="655"
|
||||
height="387"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
<span
|
||||
class="absolute top-1/2 left-1/2 grid aspect-square w-[clamp(40px,4vw,64px)] -translate-x-1/2 -translate-y-1/2 place-items-center rounded-full border border-[#ffffff80] bg-[#17121d99] pl-[3px] backdrop-blur-[8px] transition-colors duration-200 group-hover:bg-[#17121de6] motion-reduce:transition-none"
|
||||
aria-hidden="true">▶</span
|
||||
>
|
||||
<span
|
||||
class="absolute inset-x-0 bottom-0 flex justify-between gap-2 bg-gradient-to-b from-transparent to-[#000c] px-4 pt-[30px] pb-3 text-left text-[clamp(10px,1vw,14px)] font-semibold"
|
||||
>Finale 결승 방송 <span
|
||||
class="font-normal opacity-80"
|
||||
>02:19:26부터 재생</span
|
||||
></span
|
||||
>
|
||||
</button>
|
||||
</div>
|
||||
<img
|
||||
class="absolute top-[-13%] left-[-5%] z-[3] pointer-events-none h-auto w-[13%] aspect-[94/131] rotate-[10deg]"
|
||||
src="/projects/tape.svg"
|
||||
alt=""
|
||||
width="94"
|
||||
height="131"
|
||||
/>
|
||||
<img
|
||||
class="absolute top-[-13%] right-[-5%] z-[3] pointer-events-none h-auto w-[13%] aspect-[94/131] rotate-[100deg]"
|
||||
src="/projects/tape.svg"
|
||||
alt=""
|
||||
width="94"
|
||||
height="131"
|
||||
/>
|
||||
</figure>
|
||||
|
||||
<figure
|
||||
class="absolute top-[47%] left-[21%] z-[1] m-0 w-[70%] rotate-[5deg] pointer-events-none select-none"
|
||||
>
|
||||
<img
|
||||
class="block h-auto w-full pointer-events-none overflow-hidden rounded-2xl shadow-[0_12px_36px_#00000014] focus-visible:rounded-2xl focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ring"
|
||||
src="/projects/IMG_0170.avif"
|
||||
alt="점자로 보이는 단서가 적힌 찢어진 종이와 태블릿, 펜이 놓인 ARG 작업 사진"
|
||||
width="2880"
|
||||
height="2160"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
<img
|
||||
class="absolute bottom-0 left-[-6%] z-[3] pointer-events-none h-auto w-[13%] aspect-[94/131] rotate-90"
|
||||
src="/projects/tape.svg"
|
||||
alt=""
|
||||
width="94"
|
||||
height="131"
|
||||
/>
|
||||
<img
|
||||
class="absolute top-[-9%] right-[-5%] z-[3] pointer-events-none h-auto w-[13%] aspect-[94/131] rotate-[100deg]"
|
||||
src="/projects/tape.svg"
|
||||
alt=""
|
||||
width="94"
|
||||
height="131"
|
||||
/>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
const videoFrame = document.getElementById("epc-video");
|
||||
const playButton = videoFrame?.querySelector("button");
|
||||
playButton?.addEventListener(
|
||||
"click",
|
||||
() => {
|
||||
if (!videoFrame) return;
|
||||
const player = document.createElement("iframe");
|
||||
player.src =
|
||||
"https://www.youtube-nocookie.com/embed/5HDW7u3xt6Y?start=8366&autoplay=1&playsinline=1";
|
||||
player.title =
|
||||
"EPC Finale Playing Section Tournament Finals — 2:19:26부터 재생";
|
||||
player.allow =
|
||||
"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share";
|
||||
player.allowFullscreen = true;
|
||||
player.referrerPolicy = "strict-origin-when-cross-origin";
|
||||
player.className = "block h-full w-full border-0";
|
||||
videoFrame.replaceChildren(player);
|
||||
player.focus();
|
||||
},
|
||||
{ once: true },
|
||||
);
|
||||
</script>
|
||||
|
|
@ -24,10 +24,10 @@
|
|||
class="font-normal text-foreground/50"
|
||||
>로 만들어나가는</span
|
||||
><br class="hidden max-md:block md:hidden" /><span
|
||||
class="font-bold"> 암냥</span
|
||||
><span class="font-normal text-foreground/50"
|
||||
>입니다.</span
|
||||
class="font-bold"
|
||||
>
|
||||
남현석</span
|
||||
><span class="font-normal text-foreground/50">입니다.</span>
|
||||
</span>
|
||||
</h1>
|
||||
</div>
|
||||
|
|
@ -45,12 +45,12 @@
|
|||
<source
|
||||
id="hero-theme-source"
|
||||
media="(prefers-color-scheme: dark)"
|
||||
srcset="/hero-dark.png"
|
||||
srcset="/hero-dark.avif"
|
||||
type="image/png"
|
||||
/>
|
||||
<img
|
||||
class="block h-full w-full object-cover object-center transition-[scale,border-radius,box-shadow] duration-500 ease-[var(--ease-out-expo)] hover:z-10 hover:scale-105 hover:rounded-lg hover:shadow-[0_15px_45px_#0006] motion-reduce:transition-none"
|
||||
src="/hero-light.png"
|
||||
src="/hero-light.avif"
|
||||
alt="벚꽃이 핀 수로에서 보트를 타고 있는 암냥"
|
||||
width="3840"
|
||||
height="2160"
|
||||
|
|
@ -60,7 +60,8 @@
|
|||
<div
|
||||
aria-hidden="true"
|
||||
class="pointer-events-none absolute inset-x-0 bottom-0 z-20 h-[min(150px,35%)] bg-gradient-to-b from-transparent via-background/20 to-background backdrop-blur-[2px] [mask-image:linear-gradient(to_bottom,transparent,black_42%)]"
|
||||
></div>
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
|
@ -75,13 +76,13 @@
|
|||
|
||||
if (root.classList.contains("dark")) {
|
||||
heroThemeSource.media = "all";
|
||||
heroThemeSource.srcset = "/hero-dark.png";
|
||||
heroThemeSource.srcset = "/hero-dark.avif";
|
||||
} else if (root.classList.contains("light")) {
|
||||
heroThemeSource.media = "all";
|
||||
heroThemeSource.srcset = "/hero-light.png";
|
||||
heroThemeSource.srcset = "/hero-light.avif";
|
||||
} else {
|
||||
heroThemeSource.media = "(prefers-color-scheme: dark)";
|
||||
heroThemeSource.srcset = "/hero-dark.png";
|
||||
heroThemeSource.srcset = "/hero-dark.avif";
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,17 @@
|
|||
export const events = [
|
||||
interface Event {
|
||||
description: string;
|
||||
category: string;
|
||||
date: string;
|
||||
link?: string;
|
||||
}
|
||||
|
||||
export const events: Event[] = [
|
||||
{
|
||||
description: "제 2회 SSD CTF - 최다 풀이자 SSD상 수상",
|
||||
category: "Award",
|
||||
date: "2026-08-30",
|
||||
link: "https://forge.hspace.io/competitions/6a8b93c72586e8e70978b4df"
|
||||
},
|
||||
{
|
||||
description: "33회 해킹캠프 발표 - LLM에 로그인했더니 내 계정이 아니게 됐다???",
|
||||
category: "Presentation",
|
||||
|
|
@ -145,27 +158,5 @@ export const events = [
|
|||
date: "2022-05-23",
|
||||
description: "2022학년도 석정초SW영재학급 첫 수업",
|
||||
category: "Education",
|
||||
},
|
||||
{
|
||||
date: "2022-07-26",
|
||||
description: "제 14회 맑은하늘 맑은웃음 공모전에서 맑은웃음상 수여",
|
||||
category: "Award",
|
||||
},
|
||||
{
|
||||
date: "2021-11-14",
|
||||
description: "Become a ZEPETO Creator 이수",
|
||||
category: "Education",
|
||||
},
|
||||
{
|
||||
date: "2021-05-19",
|
||||
description:
|
||||
"소프트웨어와 전자신문이 주관한 소프트웨어재단 꿈찾기 캠프 이수",
|
||||
category: "Education",
|
||||
},
|
||||
{
|
||||
date: "2018-01-27",
|
||||
description:
|
||||
"제4회 맑은하늘 맑은웃음 어린이 문예공모전에서 위닉스상(2위) 수여",
|
||||
category: "Award",
|
||||
},
|
||||
}
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
---
|
||||
import About from "@/components/About.astro";
|
||||
import EPCProjects from "@/components/EPCProjects.astro";
|
||||
import Header from "@/components/Header.astro";
|
||||
import Hero from "@/components/Hero.astro";
|
||||
import "@/globals.css";
|
||||
|
|
@ -33,10 +34,11 @@ import "@/globals.css";
|
|||
<Header />
|
||||
|
||||
<main
|
||||
class="mt-[64px] h-[calc(100svh-64px)] snap-y snap-mandatory overflow-x-hidden overflow-y-auto scroll-smooth overscroll-y-contain bg-background transition-colors duration-300 [&::-webkit-scrollbar]:h-[11px] [&::-webkit-scrollbar]:w-[19px] [&::-webkit-scrollbar-thumb]:rounded-2xl [&::-webkit-scrollbar-thumb]:border-[5px] [&::-webkit-scrollbar-thumb]:border-background [&::-webkit-scrollbar-thumb]:bg-[var(--scrollbar)] [&::-webkit-scrollbar-thumb:hover]:bg-[var(--scrollbar-hover)] [&::-webkit-scrollbar-track]:bg-transparent"
|
||||
class="mt-[64px] h-[calc(100svh-64px)] snap-y snap-proximity overflow-x-hidden overflow-y-auto scroll-smooth overscroll-y-contain bg-background transition-colors duration-300 [&::-webkit-scrollbar]:h-[11px] [&::-webkit-scrollbar]:w-[19px] [&::-webkit-scrollbar-thumb]:rounded-2xl [&::-webkit-scrollbar-thumb]:border-[5px] [&::-webkit-scrollbar-thumb]:border-background [&::-webkit-scrollbar-thumb]:bg-[var(--scrollbar)] [&::-webkit-scrollbar-thumb:hover]:bg-[var(--scrollbar-hover)] [&::-webkit-scrollbar-track]:bg-transparent"
|
||||
>
|
||||
<Hero />
|
||||
<About />
|
||||
<EPCProjects />
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||