Add: 파트너 스트리머 모집 페이지 추가
- 파트너 스트리머 모집 페이지 (partner.html) 추가 - 선발 로드맵 섹션 구현 (2026.01.10 ~ 2026.12.31) - 지원 조건 및 혜택 안내 - 지원서 양식 템플릿 및 복사 기능 - 이메일 클릭 시 클립보드 복사 기능 - 반응형 디자인 적용 (모바일 최적화) Update: 팝업 시스템 개선 - index.html 팝업 이미지 및 링크 업데이트 - 쿠키 기반 "오늘 하루 보지 않기" 기능 Update: 네비게이션 메뉴 - 헤더에 Partner 링크 추가 Update: 서버 설정 - Caddy 리버스 프록시 설정 추가 (HTTPS 지원) - Python 서버 HTTP 모드 강제 설정 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
c1d35fcc2e
commit
5d2ff03d79
18
Caddyfile
Normal file
18
Caddyfile
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# HTTP to HTTPS redirect
|
||||||
|
:80 {
|
||||||
|
redir https://{host}{uri} permanent
|
||||||
|
}
|
||||||
|
|
||||||
|
# HTTPS with self-signed cert (bypassing Let's Encrypt issues)
|
||||||
|
:443 {
|
||||||
|
tls internal {
|
||||||
|
on_demand
|
||||||
|
}
|
||||||
|
reverse_proxy localhost:8001
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
log {
|
||||||
|
output file C:\Dev\Web\mingle-website\caddy\access.log
|
||||||
|
format json
|
||||||
|
}
|
||||||
|
}
|
||||||
202
caddy/LICENSE
Normal file
202
caddy/LICENSE
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
200
caddy/README.md
Normal file
200
caddy/README.md
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
<p align="center">
|
||||||
|
<a href="https://caddyserver.com">
|
||||||
|
<picture>
|
||||||
|
<source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/1128849/210187358-e2c39003-9a5e-4dd5-a783-6deb6483ee72.svg">
|
||||||
|
<source media="(prefers-color-scheme: light)" srcset="https://user-images.githubusercontent.com/1128849/210187356-dfb7f1c5-ac2e-43aa-bb23-fc014280ae1f.svg">
|
||||||
|
<img src="https://user-images.githubusercontent.com/1128849/210187356-dfb7f1c5-ac2e-43aa-bb23-fc014280ae1f.svg" alt="Caddy" width="550">
|
||||||
|
</picture>
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
<h3 align="center">a <a href="https://zerossl.com"><img src="https://user-images.githubusercontent.com/55066419/208327323-2770dc16-ec09-43a0-9035-c5b872c2ad7f.svg" height="28" style="vertical-align: -7.7px" valign="middle"></a> project</h3>
|
||||||
|
</p>
|
||||||
|
<hr>
|
||||||
|
<h3 align="center">Every site on HTTPS</h3>
|
||||||
|
<p align="center">Caddy is an extensible server platform that uses TLS by default.</p>
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://github.com/caddyserver/caddy/actions/workflows/ci.yml"><img src="https://github.com/caddyserver/caddy/actions/workflows/ci.yml/badge.svg"></a>
|
||||||
|
<a href="https://pkg.go.dev/github.com/caddyserver/caddy/v2"><img src="https://img.shields.io/badge/godoc-reference-%23007d9c.svg"></a>
|
||||||
|
<br>
|
||||||
|
<a href="https://twitter.com/caddyserver" title="@caddyserver on Twitter"><img src="https://img.shields.io/badge/twitter-@caddyserver-55acee.svg" alt="@caddyserver on Twitter"></a>
|
||||||
|
<a href="https://caddy.community" title="Caddy Forum"><img src="https://img.shields.io/badge/community-forum-ff69b4.svg" alt="Caddy Forum"></a>
|
||||||
|
<br>
|
||||||
|
<a href="https://sourcegraph.com/github.com/caddyserver/caddy?badge" title="Caddy on Sourcegraph"><img src="https://sourcegraph.com/github.com/caddyserver/caddy/-/badge.svg" alt="Caddy on Sourcegraph"></a>
|
||||||
|
<a href="https://cloudsmith.io/~caddy/repos/"><img src="https://img.shields.io/badge/OSS%20hosting%20by-cloudsmith-blue?logo=cloudsmith" alt="Cloudsmith"></a>
|
||||||
|
</p>
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://github.com/caddyserver/caddy/releases">Releases</a> ·
|
||||||
|
<a href="https://caddyserver.com/docs/">Documentation</a> ·
|
||||||
|
<a href="https://caddy.community">Get Help</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Menu
|
||||||
|
|
||||||
|
- [Features](#features)
|
||||||
|
- [Install](#install)
|
||||||
|
- [Build from source](#build-from-source)
|
||||||
|
- [For development](#for-development)
|
||||||
|
- [With version information and/or plugins](#with-version-information-andor-plugins)
|
||||||
|
- [Quick start](#quick-start)
|
||||||
|
- [Overview](#overview)
|
||||||
|
- [Full documentation](#full-documentation)
|
||||||
|
- [Getting help](#getting-help)
|
||||||
|
- [About](#about)
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<b>Powered by</b>
|
||||||
|
<br>
|
||||||
|
<a href="https://github.com/caddyserver/certmagic">
|
||||||
|
<picture>
|
||||||
|
<source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/55066419/206946718-740b6371-3df3-4d72-a822-47e4c48af999.png">
|
||||||
|
<source media="(prefers-color-scheme: light)" srcset="https://user-images.githubusercontent.com/1128849/49704830-49d37200-fbd5-11e8-8385-767e0cd033c3.png">
|
||||||
|
<img src="https://user-images.githubusercontent.com/1128849/49704830-49d37200-fbd5-11e8-8385-767e0cd033c3.png" alt="CertMagic" width="250">
|
||||||
|
</picture>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
## [Features](https://caddyserver.com/features)
|
||||||
|
|
||||||
|
- **Easy configuration** with the [Caddyfile](https://caddyserver.com/docs/caddyfile)
|
||||||
|
- **Powerful configuration** with its [native JSON config](https://caddyserver.com/docs/json/)
|
||||||
|
- **Dynamic configuration** with the [JSON API](https://caddyserver.com/docs/api)
|
||||||
|
- [**Config adapters**](https://caddyserver.com/docs/config-adapters) if you don't like JSON
|
||||||
|
- **Automatic HTTPS** by default
|
||||||
|
- [ZeroSSL](https://zerossl.com) and [Let's Encrypt](https://letsencrypt.org) for public names
|
||||||
|
- Fully-managed local CA for internal names & IPs
|
||||||
|
- Can coordinate with other Caddy instances in a cluster
|
||||||
|
- Multi-issuer fallback
|
||||||
|
- **Stays up when other servers go down** due to TLS/OCSP/certificate-related issues
|
||||||
|
- **Production-ready** after serving trillions of requests and managing millions of TLS certificates
|
||||||
|
- **Scales to hundreds of thousands of sites** as proven in production
|
||||||
|
- **HTTP/1.1, HTTP/2, and HTTP/3** all supported by default
|
||||||
|
- **Highly extensible** [modular architecture](https://caddyserver.com/docs/architecture) lets Caddy do anything without bloat
|
||||||
|
- **Runs anywhere** with **no external dependencies** (not even libc)
|
||||||
|
- Written in Go, a language with higher **memory safety guarantees** than other servers
|
||||||
|
- Actually **fun to use**
|
||||||
|
- So much more to [discover](https://caddyserver.com/features)
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
The simplest, cross-platform way to get started is to download Caddy from [GitHub Releases](https://github.com/caddyserver/caddy/releases) and place the executable file in your PATH.
|
||||||
|
|
||||||
|
See [our online documentation](https://caddyserver.com/docs/install) for other install instructions.
|
||||||
|
|
||||||
|
## Build from source
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
|
||||||
|
- [Go 1.21 or newer](https://golang.org/dl/)
|
||||||
|
|
||||||
|
### For development
|
||||||
|
|
||||||
|
_**Note:** These steps [will not embed proper version information](https://github.com/golang/go/issues/29228). For that, please follow the instructions in the next section._
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ git clone "https://github.com/caddyserver/caddy.git"
|
||||||
|
$ cd caddy/cmd/caddy/
|
||||||
|
$ go build
|
||||||
|
```
|
||||||
|
|
||||||
|
When you run Caddy, it may try to bind to low ports unless otherwise specified in your config. If your OS requires elevated privileges for this, you will need to give your new binary permission to do so. On Linux, this can be done easily with: `sudo setcap cap_net_bind_service=+ep ./caddy`
|
||||||
|
|
||||||
|
If you prefer to use `go run` which only creates temporary binaries, you can still do this with the included `setcap.sh` like so:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ go run -exec ./setcap.sh main.go
|
||||||
|
```
|
||||||
|
|
||||||
|
If you don't want to type your password for `setcap`, use `sudo visudo` to edit your sudoers file and allow your user account to run that command without a password, for example:
|
||||||
|
|
||||||
|
```
|
||||||
|
username ALL=(ALL:ALL) NOPASSWD: /usr/sbin/setcap
|
||||||
|
```
|
||||||
|
|
||||||
|
replacing `username` with your actual username. Please be careful and only do this if you know what you are doing! We are only qualified to document how to use Caddy, not Go tooling or your computer, and we are providing these instructions for convenience only; please learn how to use your own computer at your own risk and make any needful adjustments.
|
||||||
|
|
||||||
|
### With version information and/or plugins
|
||||||
|
|
||||||
|
Using [our builder tool, `xcaddy`](https://github.com/caddyserver/xcaddy)...
|
||||||
|
|
||||||
|
```
|
||||||
|
$ xcaddy build
|
||||||
|
```
|
||||||
|
|
||||||
|
...the following steps are automated:
|
||||||
|
|
||||||
|
1. Create a new folder: `mkdir caddy`
|
||||||
|
2. Change into it: `cd caddy`
|
||||||
|
3. Copy [Caddy's main.go](https://github.com/caddyserver/caddy/blob/master/cmd/caddy/main.go) into the empty folder. Add imports for any custom plugins you want to add.
|
||||||
|
4. Initialize a Go module: `go mod init caddy`
|
||||||
|
5. (Optional) Pin Caddy version: `go get github.com/caddyserver/caddy/v2@version` replacing `version` with a git tag, commit, or branch name.
|
||||||
|
6. (Optional) Add plugins by adding their import: `_ "import/path/here"`
|
||||||
|
7. Compile: `go build`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
The [Caddy website](https://caddyserver.com/docs/) has documentation that includes tutorials, quick-start guides, reference, and more.
|
||||||
|
|
||||||
|
**We recommend that all users -- regardless of experience level -- do our [Getting Started](https://caddyserver.com/docs/getting-started) guide to become familiar with using Caddy.**
|
||||||
|
|
||||||
|
If you've only got a minute, [the website has several quick-start tutorials](https://caddyserver.com/docs/quick-starts) to choose from! However, after finishing a quick-start tutorial, please read more documentation to understand how the software works. 🙂
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Caddy is most often used as an HTTPS server, but it is suitable for any long-running Go program. First and foremost, it is a platform to run Go applications. Caddy "apps" are just Go programs that are implemented as Caddy modules. Two apps -- `tls` and `http` -- ship standard with Caddy.
|
||||||
|
|
||||||
|
Caddy apps instantly benefit from [automated documentation](https://caddyserver.com/docs/json/), graceful on-line [config changes via API](https://caddyserver.com/docs/api), and unification with other Caddy apps.
|
||||||
|
|
||||||
|
Although [JSON](https://caddyserver.com/docs/json/) is Caddy's native config language, Caddy can accept input from [config adapters](https://caddyserver.com/docs/config-adapters) which can essentially convert any config format of your choice into JSON: Caddyfile, JSON 5, YAML, TOML, NGINX config, and more.
|
||||||
|
|
||||||
|
The primary way to configure Caddy is through [its API](https://caddyserver.com/docs/api), but if you prefer config files, the [command-line interface](https://caddyserver.com/docs/command-line) supports those too.
|
||||||
|
|
||||||
|
Caddy exposes an unprecedented level of control compared to any web server in existence. In Caddy, you are usually setting the actual values of the initialized types in memory that power everything from your HTTP handlers and TLS handshakes to your storage medium. Caddy is also ridiculously extensible, with a powerful plugin system that makes vast improvements over other web servers.
|
||||||
|
|
||||||
|
To wield the power of this design, you need to know how the config document is structured. Please see [our documentation site](https://caddyserver.com/docs/) for details about [Caddy's config structure](https://caddyserver.com/docs/json/).
|
||||||
|
|
||||||
|
Nearly all of Caddy's configuration is contained in a single config document, rather than being scattered across CLI flags and env variables and a configuration file as with other web servers. This makes managing your server config more straightforward and reduces hidden variables/factors.
|
||||||
|
|
||||||
|
|
||||||
|
## Full documentation
|
||||||
|
|
||||||
|
Our website has complete documentation:
|
||||||
|
|
||||||
|
**https://caddyserver.com/docs/**
|
||||||
|
|
||||||
|
The docs are also open source. You can contribute to them here: https://github.com/caddyserver/website
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Getting help
|
||||||
|
|
||||||
|
- We advise companies using Caddy to secure a support contract through [Ardan Labs](https://www.ardanlabs.com/my/contact-us?dd=caddy) before help is needed.
|
||||||
|
|
||||||
|
- A [sponsorship](https://github.com/sponsors/mholt) goes a long way! We can offer private help to sponsors. If Caddy is benefitting your company, please consider a sponsorship. This not only helps fund full-time work to ensure the longevity of the project, it provides your company the resources, support, and discounts you need; along with being a great look for your company to your customers and potential customers!
|
||||||
|
|
||||||
|
- Individuals can exchange help for free on our community forum at https://caddy.community. Remember that people give help out of their spare time and good will. The best way to get help is to give it first!
|
||||||
|
|
||||||
|
Please use our [issue tracker](https://github.com/caddyserver/caddy/issues) only for bug reports and feature requests, i.e. actionable development items (support questions will usually be referred to the forums).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## About
|
||||||
|
|
||||||
|
Matthew Holt began developing Caddy in 2014 while studying computer science at Brigham Young University. (The name "Caddy" was chosen because this software helps with the tedious, mundane tasks of serving the Web, and is also a single place for multiple things to be organized together.) It soon became the first web server to use HTTPS automatically and by default, and now has hundreds of contributors and has served trillions of HTTPS requests.
|
||||||
|
|
||||||
|
**The name "Caddy" is trademarked.** The name of the software is "Caddy", not "Caddy Server" or "CaddyServer". Please call it "Caddy" or, if you wish to clarify, "the Caddy web server". Caddy is a registered trademark of Stack Holdings GmbH.
|
||||||
|
|
||||||
|
- _Project on Twitter: [@caddyserver](https://twitter.com/caddyserver)_
|
||||||
|
- _Author on Twitter: [@mholt6](https://twitter.com/mholt6)_
|
||||||
|
|
||||||
|
Caddy is a project of [ZeroSSL](https://zerossl.com), a Stack Holdings company.
|
||||||
|
|
||||||
|
Debian package repository hosting is graciously provided by [Cloudsmith](https://cloudsmith.com). Cloudsmith is the only fully hosted, cloud-native, universal package management solution, that enables your organization to create, store and share packages in any format, to any place, with total confidence.
|
||||||
21
caddy/access.log
Normal file
21
caddy/access.log
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{"level":"info","ts":1767974718.0383568,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"66.133.109.36","remote_port":"40279","client_ip":"66.133.109.36","proto":"HTTP/1.1","method":"GET","host":"www.mingleon.duckdns.org","uri":"/.well-known/acme-challenge/ngyiKxhwpD1mwM0fa8bW3CBbJHOOh04C9g-KmXJVS3s","headers":{"User-Agent":["Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"],"Accept":["*/*"],"Accept-Encoding":["gzip"],"Connection":["close"]}},"bytes_read":0,"user_id":"","duration":0,"size":87,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["text/plain"]}}
|
||||||
|
{"level":"info","ts":1767974719.9677167,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"54.203.1.121","remote_port":"48938","client_ip":"54.203.1.121","proto":"HTTP/1.1","method":"GET","host":"www.mingleon.duckdns.org","uri":"/.well-known/acme-challenge/ngyiKxhwpD1mwM0fa8bW3CBbJHOOh04C9g-KmXJVS3s","headers":{"User-Agent":["Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"],"Accept":["*/*"],"Accept-Encoding":["gzip"],"Connection":["close"]}},"bytes_read":0,"user_id":"","duration":0,"size":87,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["text/plain"]}}
|
||||||
|
{"level":"info","ts":1767974728.642247,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"47.128.77.196","remote_port":"55926","client_ip":"47.128.77.196","proto":"HTTP/1.1","method":"GET","host":"www.mingleon.duckdns.org","uri":"/.well-known/acme-challenge/ngyiKxhwpD1mwM0fa8bW3CBbJHOOh04C9g-KmXJVS3s","headers":{"User-Agent":["Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"],"Accept":["*/*"],"Accept-Encoding":["gzip"],"Connection":["close"]}},"bytes_read":0,"user_id":"","duration":0,"size":87,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["text/plain"]}}
|
||||||
|
{"level":"info","ts":1767974730.6060884,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"3.14.254.124","remote_port":"31374","client_ip":"3.14.254.124","proto":"HTTP/1.1","method":"GET","host":"www.mingleon.duckdns.org","uri":"/.well-known/acme-challenge/ngyiKxhwpD1mwM0fa8bW3CBbJHOOh04C9g-KmXJVS3s","headers":{"User-Agent":["Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"],"Accept":["*/*"],"Accept-Encoding":["gzip"],"Connection":["close"]}},"bytes_read":0,"user_id":"","duration":0,"size":87,"status":200,"resp_headers":{"Content-Type":["text/plain"],"Server":["Caddy"]}}
|
||||||
|
{"level":"info","ts":1767974733.4113173,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"13.50.236.75","remote_port":"51302","client_ip":"13.50.236.75","proto":"HTTP/1.1","method":"GET","host":"www.mingleon.duckdns.org","uri":"/.well-known/acme-challenge/ngyiKxhwpD1mwM0fa8bW3CBbJHOOh04C9g-KmXJVS3s","headers":{"Accept":["*/*"],"Accept-Encoding":["gzip"],"Connection":["close"],"User-Agent":["Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"]}},"bytes_read":0,"user_id":"","duration":0,"size":87,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["text/plain"]}}
|
||||||
|
{"level":"info","ts":1767976567.2994442,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"23.178.112.212","remote_port":"32969","client_ip":"23.178.112.212","proto":"HTTP/1.1","method":"GET","host":"www.mingleon.duckdns.org","uri":"/.well-known/acme-challenge/_Bh1-SpqEkMeevVc4FJpsnqcXl2P_zd81sJTrS2fIL0","headers":{"User-Agent":["Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"],"Accept":["*/*"],"Accept-Encoding":["gzip"],"Connection":["close"]}},"bytes_read":0,"user_id":"","duration":0,"size":87,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["text/plain"]}}
|
||||||
|
{"level":"info","ts":1767976568.2214603,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"52.14.92.2","remote_port":"31036","client_ip":"52.14.92.2","proto":"HTTP/1.1","method":"GET","host":"www.mingleon.duckdns.org","uri":"/.well-known/acme-challenge/_Bh1-SpqEkMeevVc4FJpsnqcXl2P_zd81sJTrS2fIL0","headers":{"User-Agent":["Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"],"Accept":["*/*"],"Accept-Encoding":["gzip"],"Connection":["close"]}},"bytes_read":0,"user_id":"","duration":0,"size":87,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["text/plain"]}}
|
||||||
|
{"level":"info","ts":1767976570.2455995,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"13.53.35.17","remote_port":"60524","client_ip":"13.53.35.17","proto":"HTTP/1.1","method":"GET","host":"www.mingleon.duckdns.org","uri":"/.well-known/acme-challenge/_Bh1-SpqEkMeevVc4FJpsnqcXl2P_zd81sJTrS2fIL0","headers":{"User-Agent":["Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"],"Accept":["*/*"],"Accept-Encoding":["gzip"],"Connection":["close"]}},"bytes_read":0,"user_id":"","duration":0,"size":87,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["text/plain"]}}
|
||||||
|
{"level":"info","ts":1767976572.9680867,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"54.218.186.63","remote_port":"48478","client_ip":"54.218.186.63","proto":"HTTP/1.1","method":"GET","host":"www.mingleon.duckdns.org","uri":"/.well-known/acme-challenge/_Bh1-SpqEkMeevVc4FJpsnqcXl2P_zd81sJTrS2fIL0","headers":{"Accept-Encoding":["gzip"],"Connection":["close"],"User-Agent":["Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"],"Accept":["*/*"]}},"bytes_read":0,"user_id":"","duration":0,"size":87,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["text/plain"]}}
|
||||||
|
{"level":"info","ts":1767976579.4746377,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"18.142.243.164","remote_port":"23420","client_ip":"18.142.243.164","proto":"HTTP/1.1","method":"GET","host":"www.mingleon.duckdns.org","uri":"/.well-known/acme-challenge/_Bh1-SpqEkMeevVc4FJpsnqcXl2P_zd81sJTrS2fIL0","headers":{"Accept":["*/*"],"Accept-Encoding":["gzip"],"Connection":["close"],"User-Agent":["Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"]}},"bytes_read":0,"user_id":"","duration":0,"size":87,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["text/plain"]}}
|
||||||
|
{"level":"error","ts":1767976746.460091,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"192.168.0.1","remote_port":"8236","client_ip":"192.168.0.1","proto":"HTTP/2.0","method":"GET","host":"www.mingleon.duckdns.org","uri":"/","headers":{"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Sec-Fetch-User":["?1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["ko,en-US;q=0.9,en;q=0.8,ja;q=0.7"],"Priority":["u=0, i"],"Cache-Control":["max-age=0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Whale/4.35.351.13 Safari/537.36"],"Sec-Fetch-Site":["none"],"Sec-Fetch-Dest":["document"],"Sec-Ch-Ua":["\"Chromium\";v=\"142\", \"Whale\";v=\"4\", \"Not.A/Brand\";v=\"99\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["navigate"],"Upgrade-Insecure-Requests":["1"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"www.mingleon.duckdns.org"}},"bytes_read":0,"user_id":"","duration":0.0031286,"size":0,"status":502,"resp_headers":{"Server":["Caddy"],"Alt-Svc":["h3=\":443\"; ma=2592000"]}}
|
||||||
|
{"level":"error","ts":1767976752.2995276,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"192.168.0.1","remote_port":"13648","client_ip":"192.168.0.1","proto":"HTTP/2.0","method":"GET","host":"58.29.195.73","uri":"/","headers":{"Sec-Fetch-Dest":["document"],"Sec-Fetch-User":["?1"],"Priority":["u=0, i"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["navigate"],"Sec-Ch-Ua-Mobile":["?0"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Whale/4.35.351.13 Safari/537.36"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Sec-Fetch-Site":["none"],"Cache-Control":["max-age=0"],"Sec-Ch-Ua":["\"Chromium\";v=\"142\", \"Whale\";v=\"4\", \"Not.A/Brand\";v=\"99\""],"Accept-Language":["ko,en-US;q=0.9,en;q=0.8,ja;q=0.7"],"Upgrade-Insecure-Requests":["1"],"Accept-Encoding":["gzip, deflate, br, zstd"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":""}},"bytes_read":0,"user_id":"","duration":0.0027841,"size":0,"status":502,"resp_headers":{"Server":["Caddy"],"Alt-Svc":["h3=\":443\"; ma=2592000"]}}
|
||||||
|
{"level":"error","ts":1767976759.5702891,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"192.168.0.1","remote_port":"13648","client_ip":"192.168.0.1","proto":"HTTP/2.0","method":"GET","host":"58.29.195.73","uri":"/","headers":{"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Mode":["navigate"],"Priority":["u=0, i"],"Cache-Control":["max-age=0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Sec-Ch-Ua":["\"Chromium\";v=\"142\", \"Whale\";v=\"4\", \"Not.A/Brand\";v=\"99\""],"Upgrade-Insecure-Requests":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Whale/4.35.351.13 Safari/537.36"],"Sec-Fetch-Dest":["document"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["ko,en-US;q=0.9,en;q=0.8,ja;q=0.7"],"Sec-Fetch-Site":["none"],"Sec-Fetch-User":["?1"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":""}},"bytes_read":0,"user_id":"","duration":0.00319,"size":0,"status":502,"resp_headers":{"Server":["Caddy"],"Alt-Svc":["h3=\":443\"; ma=2592000"]}}
|
||||||
|
{"level":"error","ts":1767976766.1323526,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"192.168.0.1","remote_port":"8236","client_ip":"192.168.0.1","proto":"HTTP/2.0","method":"GET","host":"www.mingleon.duckdns.org","uri":"/","headers":{"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Sec-Fetch-Site":["none"],"Sec-Fetch-Dest":["document"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-User":["?1"],"Priority":["u=0, i"],"Sec-Ch-Ua":["\"Chromium\";v=\"142\", \"Whale\";v=\"4\", \"Not.A/Brand\";v=\"99\""],"Sec-Ch-Ua-Platform":["\"Windows\""],"Upgrade-Insecure-Requests":["1"],"Sec-Fetch-Mode":["navigate"],"Cache-Control":["max-age=0"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Whale/4.35.351.13 Safari/537.36"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["ko,en-US;q=0.9,en;q=0.8,ja;q=0.7"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"www.mingleon.duckdns.org"}},"bytes_read":0,"user_id":"","duration":0.0026185,"size":0,"status":502,"resp_headers":{"Server":["Caddy"],"Alt-Svc":["h3=\":443\"; ma=2592000"]}}
|
||||||
|
{"level":"error","ts":1767976766.5005789,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"192.168.0.1","remote_port":"8236","client_ip":"192.168.0.1","proto":"HTTP/2.0","method":"GET","host":"www.mingleon.duckdns.org","uri":"/","headers":{"Priority":["u=0, i"],"Cache-Control":["max-age=0"],"Sec-Fetch-User":["?1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Whale/4.35.351.13 Safari/537.36"],"Sec-Fetch-Site":["none"],"Sec-Fetch-Dest":["document"],"Sec-Fetch-Mode":["navigate"],"Accept-Language":["ko,en-US;q=0.9,en;q=0.8,ja;q=0.7"],"Sec-Ch-Ua-Mobile":["?0"],"Upgrade-Insecure-Requests":["1"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Sec-Ch-Ua":["\"Chromium\";v=\"142\", \"Whale\";v=\"4\", \"Not.A/Brand\";v=\"99\""],"Sec-Ch-Ua-Platform":["\"Windows\""]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"www.mingleon.duckdns.org"}},"bytes_read":0,"user_id":"","duration":0.0010358,"size":0,"status":502,"resp_headers":{"Alt-Svc":["h3=\":443\"; ma=2592000"],"Server":["Caddy"]}}
|
||||||
|
{"level":"error","ts":1767976768.996292,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"192.168.0.1","remote_port":"8236","client_ip":"192.168.0.1","proto":"HTTP/2.0","method":"GET","host":"www.mingleon.duckdns.org","uri":"/","headers":{"Priority":["u=0, i"],"Cache-Control":["max-age=0"],"Sec-Ch-Ua":["\"Chromium\";v=\"142\", \"Whale\";v=\"4\", \"Not.A/Brand\";v=\"99\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["document"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Upgrade-Insecure-Requests":["1"],"Sec-Fetch-Site":["none"],"Sec-Fetch-User":["?1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Whale/4.35.351.13 Safari/537.36"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Sec-Fetch-Mode":["navigate"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept-Language":["ko,en-US;q=0.9,en;q=0.8,ja;q=0.7"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"www.mingleon.duckdns.org"}},"bytes_read":0,"user_id":"","duration":0.0010344,"size":0,"status":502,"resp_headers":{"Server":["Caddy"],"Alt-Svc":["h3=\":443\"; ma=2592000"]}}
|
||||||
|
{"level":"error","ts":1767976845.1716719,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"192.168.0.1","remote_port":"8236","client_ip":"192.168.0.1","proto":"HTTP/2.0","method":"GET","host":"www.mingleon.duckdns.org","uri":"/","headers":{"Upgrade-Insecure-Requests":["1"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Sec-Fetch-Mode":["navigate"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["ko,en-US;q=0.9,en;q=0.8,ja;q=0.7"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Whale/4.35.351.13 Safari/537.36"],"Sec-Fetch-Site":["none"],"Sec-Fetch-User":["?1"],"Sec-Fetch-Dest":["document"],"Sec-Ch-Ua":["\"Chromium\";v=\"142\", \"Whale\";v=\"4\", \"Not.A/Brand\";v=\"99\""],"Sec-Ch-Ua-Mobile":["?0"],"Priority":["u=0, i"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"www.mingleon.duckdns.org"}},"bytes_read":0,"user_id":"","duration":0.0037944,"size":0,"status":502,"resp_headers":{"Server":["Caddy"],"Alt-Svc":["h3=\":443\"; ma=2592000"]}}
|
||||||
|
{"level":"error","ts":1767976849.4067652,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"192.168.0.1","remote_port":"8236","client_ip":"192.168.0.1","proto":"HTTP/2.0","method":"GET","host":"www.mingleon.duckdns.org","uri":"/","headers":{"Sec-Ch-Ua-Mobile":["?0"],"Cache-Control":["max-age=0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Sec-Fetch-Mode":["navigate"],"Sec-Fetch-Dest":["document"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua":["\"Chromium\";v=\"142\", \"Whale\";v=\"4\", \"Not.A/Brand\";v=\"99\""],"Upgrade-Insecure-Requests":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Whale/4.35.351.13 Safari/537.36"],"Sec-Fetch-User":["?1"],"Accept-Language":["ko,en-US;q=0.9,en;q=0.8,ja;q=0.7"],"Priority":["u=0, i"],"Sec-Fetch-Site":["none"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"www.mingleon.duckdns.org"}},"bytes_read":0,"user_id":"","duration":0.0033039,"size":0,"status":502,"resp_headers":{"Server":["Caddy"],"Alt-Svc":["h3=\":443\"; ma=2592000"]}}
|
||||||
|
{"level":"error","ts":1767976913.7880945,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"192.168.0.1","remote_port":"8236","client_ip":"192.168.0.1","proto":"HTTP/2.0","method":"GET","host":"www.mingleon.duckdns.org","uri":"/","headers":{"Upgrade-Insecure-Requests":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Whale/4.35.351.13 Safari/537.36"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Mode":["navigate"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["ko,en-US;q=0.9,en;q=0.8,ja;q=0.7"],"Priority":["u=0, i"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Sec-Fetch-Site":["none"],"Sec-Fetch-User":["?1"],"Cache-Control":["max-age=0"],"Sec-Ch-Ua":["\"Chromium\";v=\"142\", \"Whale\";v=\"4\", \"Not.A/Brand\";v=\"99\""],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Dest":["document"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"www.mingleon.duckdns.org"}},"bytes_read":0,"user_id":"","duration":0.0039894,"size":0,"status":502,"resp_headers":{"Server":["Caddy"],"Alt-Svc":["h3=\":443\"; ma=2592000"]}}
|
||||||
|
{"level":"error","ts":1767976914.4625819,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"192.168.0.1","remote_port":"8236","client_ip":"192.168.0.1","proto":"HTTP/2.0","method":"GET","host":"www.mingleon.duckdns.org","uri":"/","headers":{"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Ch-Ua-Platform":["\"Windows\""],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Sec-Fetch-Site":["none"],"Sec-Fetch-Dest":["document"],"Accept-Language":["ko,en-US;q=0.9,en;q=0.8,ja;q=0.7"],"Cache-Control":["max-age=0"],"Upgrade-Insecure-Requests":["1"],"Sec-Fetch-Mode":["navigate"],"Sec-Fetch-User":["?1"],"Sec-Ch-Ua":["\"Chromium\";v=\"142\", \"Whale\";v=\"4\", \"Not.A/Brand\";v=\"99\""],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Whale/4.35.351.13 Safari/537.36"],"Priority":["u=0, i"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"www.mingleon.duckdns.org"}},"bytes_read":0,"user_id":"","duration":0.0016982,"size":0,"status":502,"resp_headers":{"Server":["Caddy"],"Alt-Svc":["h3=\":443\"; ma=2592000"]}}
|
||||||
|
{"level":"error","ts":1767976929.404028,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"192.168.0.1","remote_port":"8236","client_ip":"192.168.0.1","proto":"HTTP/2.0","method":"GET","host":"www.mingleon.duckdns.org","uri":"/","headers":{"Sec-Ch-Ua-Platform":["\"Windows\""],"Sec-Fetch-Site":["none"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["ko,en-US;q=0.9,en;q=0.8,ja;q=0.7"],"Cache-Control":["max-age=0"],"Sec-Ch-Ua":["\"Chromium\";v=\"142\", \"Whale\";v=\"4\", \"Not.A/Brand\";v=\"99\""],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Priority":["u=0, i"],"Sec-Fetch-Mode":["navigate"],"Sec-Fetch-User":["?1"],"Sec-Fetch-Dest":["document"],"Sec-Ch-Ua-Mobile":["?0"],"Upgrade-Insecure-Requests":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Whale/4.35.351.13 Safari/537.36"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"www.mingleon.duckdns.org"}},"bytes_read":0,"user_id":"","duration":0.0038999,"size":0,"status":502,"resp_headers":{"Server":["Caddy"],"Alt-Svc":["h3=\":443\"; ma=2592000"]}}
|
||||||
BIN
caddy/caddy.exe
Normal file
BIN
caddy/caddy.exe
Normal file
Binary file not shown.
@ -13,6 +13,7 @@
|
|||||||
<li><a href="/services" class="nav-link">Services</a></li>
|
<li><a href="/services" class="nav-link">Services</a></li>
|
||||||
<li><a href="/portfolio" class="nav-link">Portfolio</a></li>
|
<li><a href="/portfolio" class="nav-link">Portfolio</a></li>
|
||||||
<li><a href="/gallery" class="nav-link">Gallery</a></li>
|
<li><a href="/gallery" class="nav-link">Gallery</a></li>
|
||||||
|
<li><a href="/partner" class="nav-link">Partner</a></li>
|
||||||
<li><a href="/contact" class="nav-link">Contact</a></li>
|
<li><a href="/contact" class="nav-link">Contact</a></li>
|
||||||
<li><a href="/qna" class="nav-link">Q&A</a></li>
|
<li><a href="/qna" class="nav-link">Q&A</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
729
css/partner.css
Normal file
729
css/partner.css
Normal file
@ -0,0 +1,729 @@
|
|||||||
|
/* ========================================
|
||||||
|
Partner 페이지 전용 스타일
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
/* 파트너 Hero 섹션 */
|
||||||
|
.partner-hero {
|
||||||
|
background: linear-gradient(135deg, rgba(255, 136, 0, 0.85) 0%, rgba(255, 102, 0, 0.85) 100%),
|
||||||
|
url('../extra-image/I Want you for Mingle.png') center center / auto 100% no-repeat;
|
||||||
|
padding: 150px 0 120px;
|
||||||
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
min-height: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.partner-hero::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: rgba(255, 136, 0, 0.2);
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.partner-hero-content {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.partner-hero-title {
|
||||||
|
font-size: 4rem;
|
||||||
|
color: #fff;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.partner-hero-subtitle {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: rgba(255, 255, 255, 0.95);
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 파트너 섹션 공통 스타일 */
|
||||||
|
.partner-conditions-section {
|
||||||
|
background: linear-gradient(135deg, #E3F2FD 0%, #FFF9C4 50%, #FFECB3 100%);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.partner-benefits-section {
|
||||||
|
background: linear-gradient(135deg, #FFF9C4 0%, #FFECB3 50%, #FFE0B2 100%);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.partner-provides-section {
|
||||||
|
background: linear-gradient(135deg, #E3F2FD 0%, #BBDEFB 50%, #90CAF9 100%);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 섹션 타이틀 스타일 */
|
||||||
|
.section-title-styled {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
font-weight: 800;
|
||||||
|
color: #2c3e50;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
background: linear-gradient(135deg, #1976D2 0%, #42A5F5 100%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 스타일된 콘텐츠 래퍼 */
|
||||||
|
.styled-content-wrapper {
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 스타일된 리스트 */
|
||||||
|
.styled-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 스타일된 아이템 */
|
||||||
|
.styled-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 2rem;
|
||||||
|
background: rgba(255, 255, 255, 0.9);
|
||||||
|
padding: 2rem;
|
||||||
|
border-radius: 20px;
|
||||||
|
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
|
||||||
|
border: 3px solid rgba(255, 255, 255, 0.5);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.styled-item:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
box-shadow: 0 12px 35px rgba(0, 0, 0, 0.15);
|
||||||
|
border-color: #42A5F5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 핑크색 원형 번호 배지 */
|
||||||
|
.number-badge {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
background: linear-gradient(135deg, #FF80AB 0%, #FF4081 100%);
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 2.5rem;
|
||||||
|
font-weight: 800;
|
||||||
|
color: white;
|
||||||
|
box-shadow: 0 4px 15px rgba(255, 64, 129, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 아이템 콘텐츠 */
|
||||||
|
.item-content {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-title {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #FF4081;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-desc {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
color: #42A5F5;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 0;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 지원 안내 래퍼 */
|
||||||
|
.application-guide-wrapper {
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 이메일 정보 박스 */
|
||||||
|
.email-info-box {
|
||||||
|
background: linear-gradient(135deg, #fff 0%, #fff8f0 100%);
|
||||||
|
padding: 2.5rem;
|
||||||
|
border-radius: 15px;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
box-shadow: 0 8px 30px rgba(255, 136, 0, 0.15);
|
||||||
|
border: 2px solid var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-icon {
|
||||||
|
font-size: 4rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-info-box h3 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--text-primary);
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-link {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--primary-color);
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 1rem 0;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border: 2px solid var(--primary-color);
|
||||||
|
word-break: break-all;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-link:hover {
|
||||||
|
background: var(--primary-color);
|
||||||
|
color: #fff;
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-note {
|
||||||
|
font-size: 1rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-email-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
margin-top: 1rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #fff;
|
||||||
|
background: linear-gradient(135deg, var(--primary-color) 0%, #ff6600 100%);
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow: 0 4px 15px rgba(255, 136, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-email-btn:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 20px rgba(255, 136, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-email-btn:active {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-email-btn.copied {
|
||||||
|
background: linear-gradient(135deg, #4CAF50 0%, #45a049 100%) !important;
|
||||||
|
box-shadow: 0 4px 15px rgba(76, 175, 80, 0.4) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-email-btn .copy-icon {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-email-btn .copy-text {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 로드맵 스타일 */
|
||||||
|
.roadmap-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 1rem;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
margin: 3rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roadmap-item {
|
||||||
|
background: #fff;
|
||||||
|
padding: 1.5rem;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.1);
|
||||||
|
flex: 1;
|
||||||
|
max-width: 220px;
|
||||||
|
text-align: center;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border: 2px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roadmap-item:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
box-shadow: 0 12px 40px rgba(255, 136, 0, 0.2);
|
||||||
|
border-color: var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.roadmap-item-highlight {
|
||||||
|
background: linear-gradient(135deg, #fff7ed 0%, #ffe8cc 100%);
|
||||||
|
border: 2px solid var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.roadmap-badge {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
background: linear-gradient(135deg, var(--primary-color) 0%, #ff6600 100%);
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 0 auto 1rem;
|
||||||
|
box-shadow: 0 4px 15px rgba(255, 136, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.roadmap-title {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-primary);
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roadmap-date {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--primary-color);
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roadmap-desc {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roadmap-note {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: #666;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roadmap-arrow {
|
||||||
|
font-size: 2rem;
|
||||||
|
color: var(--primary-color);
|
||||||
|
font-weight: bold;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 지원서 양식 템플릿 */
|
||||||
|
.application-form-template {
|
||||||
|
background: #fff;
|
||||||
|
padding: 2.5rem;
|
||||||
|
border-radius: 15px;
|
||||||
|
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.1);
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
border: 2px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
border-bottom: 3px solid var(--primary-color);
|
||||||
|
gap: 1rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-title {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--text-primary);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 복사 버튼 */
|
||||||
|
.copy-template-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
background: linear-gradient(135deg, #ff8800 0%, #ff9933 100%);
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: 700;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow: 0 4px 15px rgba(255, 136, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-template-btn:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 20px rgba(255, 136, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-template-btn:active {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-icon {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-text {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 복사 성공 애니메이션 */
|
||||||
|
.copy-template-btn.copied {
|
||||||
|
background: linear-gradient(135deg, #4CAF50 0%, #45a049 100%) !important;
|
||||||
|
box-shadow: 0 4px 15px rgba(76, 175, 80, 0.4) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-content {
|
||||||
|
/* 복사할 내용 영역 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-section {
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-section h4 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: var(--primary-color);
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.question-item {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
padding: 1rem;
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 8px;
|
||||||
|
border-left: 4px solid var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.question {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-primary);
|
||||||
|
margin: 0 0 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.answer-guide {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: #666;
|
||||||
|
margin: 0.25rem 0;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.answer-sub {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: #999;
|
||||||
|
margin: 0.25rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 지원 안내 박스 */
|
||||||
|
.application-notice-box {
|
||||||
|
background: #fff8f0;
|
||||||
|
padding: 2rem;
|
||||||
|
border-radius: 12px;
|
||||||
|
border: 2px solid #ffd9a3;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.application-notice-box h4 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: var(--text-primary);
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.application-notice-box ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.application-notice-box li {
|
||||||
|
padding: 0.75rem 0;
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
position: relative;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.application-notice-box li::before {
|
||||||
|
content: '•';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
color: var(--primary-color);
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.application-notice-box strong {
|
||||||
|
color: var(--primary-color);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 템플릿 액션 */
|
||||||
|
.template-actions {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-actions .btn {
|
||||||
|
padding: 1.25rem 3rem;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FAQ 섹션 */
|
||||||
|
.faq-list {
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-item {
|
||||||
|
background: #fff;
|
||||||
|
padding: 2rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-item:hover {
|
||||||
|
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-question {
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-answer {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
line-height: 1.7;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CTA 섹션 */
|
||||||
|
.cta-section {
|
||||||
|
background: linear-gradient(135deg, #2c3e50 0%, #34495e 100%);
|
||||||
|
padding: 5rem 0;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-title {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-description {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-info-quick {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 2rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-info-quick span {
|
||||||
|
font-size: 1rem;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 유틸리티 클래스 */
|
||||||
|
.mt-2 {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 파트너 푸터 */
|
||||||
|
.partner-footer {
|
||||||
|
background: #222;
|
||||||
|
color: #fff;
|
||||||
|
padding: 2.5rem 0 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 반응형 디자인 */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.partner-hero {
|
||||||
|
padding: 100px 0 80px;
|
||||||
|
min-height: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.partner-hero-title {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.partner-hero-subtitle {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 스타일된 섹션 반응형 */
|
||||||
|
.section-title-styled {
|
||||||
|
font-size: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 로드맵 반응형 */
|
||||||
|
.roadmap-wrapper {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roadmap-arrow {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roadmap-item {
|
||||||
|
max-width: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.styled-item {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1.5rem;
|
||||||
|
padding: 1.5rem;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-badge {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-title {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-desc {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 지원 안내 섹션 */
|
||||||
|
.application-guide-wrapper {
|
||||||
|
padding: 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-info-box {
|
||||||
|
padding: 2rem 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-link {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.application-form-template {
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-title {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-template-btn {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.question-item {
|
||||||
|
padding: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-info-quick {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-title {
|
||||||
|
font-size: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-description {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.template-actions .btn {
|
||||||
|
width: 100%;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.partner-hero {
|
||||||
|
padding: 120px 0 100px;
|
||||||
|
min-height: 700px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.partner-hero-title {
|
||||||
|
font-size: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.partner-hero-subtitle {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title-styled {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.styled-item {
|
||||||
|
padding: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-badge {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
font-size: 1.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-title {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-desc {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 이메일 링크 모바일 최적화 */
|
||||||
|
.email-link {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
padding: 0.6rem 1rem;
|
||||||
|
word-break: break-all;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-info-box {
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
219
css/popup.css
219
css/popup.css
@ -45,6 +45,32 @@
|
|||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 팝업 스크롤바 커스텀 디자인 */
|
||||||
|
.popup-container::-webkit-scrollbar {
|
||||||
|
width: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-container::-webkit-scrollbar-track {
|
||||||
|
background: rgba(255, 136, 0, 0.1);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-container::-webkit-scrollbar-thumb {
|
||||||
|
background: linear-gradient(135deg, #ff8800 0%, #ff9933 100%);
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-container::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: linear-gradient(135deg, #ff9933 0%, #ffaa44 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Firefox 스크롤바 */
|
||||||
|
.popup-container {
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-color: #ff8800 rgba(255, 136, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes popupSlideIn {
|
@keyframes popupSlideIn {
|
||||||
from {
|
from {
|
||||||
transform: scale(0.8) translateY(-20px);
|
transform: scale(0.8) translateY(-20px);
|
||||||
@ -109,60 +135,61 @@
|
|||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 할인 카드 */
|
/* 팝업 혜택 리스트 */
|
||||||
.discount-card {
|
.popup-benefits-list {
|
||||||
background: white;
|
|
||||||
border-radius: 10px;
|
|
||||||
padding: 15px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
border: 2px solid #ffd9a3;
|
|
||||||
box-shadow: 0 2px 8px rgba(255, 136, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.discount-card-header {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
flex-direction: column;
|
||||||
align-items: center;
|
gap: 12px;
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.discount-card-title {
|
.popup-benefit-item {
|
||||||
|
background: white;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 15px;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 15px;
|
||||||
|
border: 2px solid #ffe8cc;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-benefit-item:hover {
|
||||||
|
border-color: #ff8800;
|
||||||
|
box-shadow: 0 4px 12px rgba(255, 136, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.benefit-number {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background: linear-gradient(135deg, #FF80AB 0%, #FF4081 100%);
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 800;
|
||||||
|
color: white;
|
||||||
|
box-shadow: 0 2px 8px rgba(255, 64, 129, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.benefit-content {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.benefit-content h4 {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #333;
|
color: #FF4081;
|
||||||
|
margin: 0 0 6px 0;
|
||||||
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.discount-badge {
|
.benefit-content p {
|
||||||
background: linear-gradient(135deg, #ff8800, #ff9933);
|
font-size: 0.875rem;
|
||||||
color: white;
|
color: #42A5F5;
|
||||||
padding: 4px 10px;
|
margin: 0;
|
||||||
border-radius: 20px;
|
line-height: 1.4;
|
||||||
font-size: 0.8rem;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.discount-price {
|
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.original-price {
|
|
||||||
color: #999;
|
|
||||||
text-decoration: line-through;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sale-price {
|
|
||||||
color: #ff8800;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.price-note {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
color: #666;
|
|
||||||
margin-top: 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 공지사항 */
|
/* 공지사항 */
|
||||||
@ -180,34 +207,6 @@
|
|||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 이벤트 정보 */
|
|
||||||
.popup-info {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
gap: 10px;
|
|
||||||
margin-top: 15px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-item {
|
|
||||||
background: white;
|
|
||||||
border-radius: 8px;
|
|
||||||
padding: 12px;
|
|
||||||
text-align: center;
|
|
||||||
border: 2px solid #ffe8cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-label {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
color: #666;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-value {
|
|
||||||
font-size: 1rem;
|
|
||||||
font-weight: 700;
|
|
||||||
color: #ff8800;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* CTA 버튼 컨테이너 */
|
/* CTA 버튼 컨테이너 */
|
||||||
.popup-buttons {
|
.popup-buttons {
|
||||||
@ -250,51 +249,9 @@
|
|||||||
box-shadow: 0 4px 12px rgba(255, 136, 0, 0.25);
|
box-shadow: 0 4px 12px rgba(255, 136, 0, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 팝업 푸터 */
|
/* 팝업 바디 하단 여백 조정 */
|
||||||
.popup-footer {
|
.popup-body {
|
||||||
display: flex;
|
padding: 20px 20px 30px 20px;
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
padding: 12px 20px;
|
|
||||||
background: #f8f9fa;
|
|
||||||
border-top: 1px solid #e9ecef;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-checkbox {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 6px;
|
|
||||||
cursor: pointer;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-checkbox input[type="checkbox"] {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
cursor: pointer;
|
|
||||||
accent-color: #ff8800;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-checkbox label {
|
|
||||||
font-size: 0.85rem;
|
|
||||||
color: #666;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-close-btn {
|
|
||||||
background: #6c757d;
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
padding: 6px 16px;
|
|
||||||
border-radius: 6px;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
font-weight: 600;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-close-btn:hover {
|
|
||||||
background: #5a6268;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* X 닫기 버튼 */
|
/* X 닫기 버튼 */
|
||||||
@ -351,25 +308,11 @@
|
|||||||
padding: 15px;
|
padding: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.discount-card {
|
.benefit-content h4 {
|
||||||
padding: 12px;
|
font-size: 0.95rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup-info {
|
.benefit-content p {
|
||||||
grid-template-columns: 1fr;
|
font-size: 0.8rem;
|
||||||
}
|
|
||||||
|
|
||||||
.popup-footer {
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 10px;
|
|
||||||
padding: 12px 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-checkbox {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-close-btn {
|
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
extra-image/I Want you for Mingle.png
Normal file
BIN
extra-image/I Want you for Mingle.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
79
index.html
79
index.html
@ -288,78 +288,63 @@
|
|||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- 오픈 기념 팝업 -->
|
<!-- 파트너 스트리머 모집 팝업 -->
|
||||||
<div class="popup-overlay" id="mainPopup">
|
<div class="popup-overlay" id="mainPopup">
|
||||||
<div class="popup-container">
|
<div class="popup-container">
|
||||||
<button class="popup-close-x" id="popupCloseX">×</button>
|
<button class="popup-close-x" id="popupCloseX">×</button>
|
||||||
|
|
||||||
<div class="popup-header">
|
<div class="popup-header">
|
||||||
<h2 class="popup-title">🎉 밍글 스튜디오 오픈 기념 🎉</h2>
|
<h2 class="popup-title">🎬 파트너 스트리머 모집 🎬</h2>
|
||||||
<p class="popup-subtitle">특별 할인 이벤트</p>
|
<p class="popup-subtitle">밍글 스튜디오와 함께 성장할 버튜버 스트리머를 찾습니다</p>
|
||||||
<div class="popup-badge">최대 20% 할인</div>
|
<div class="popup-badge">지금 지원하세요</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="popup-body">
|
<div class="popup-body">
|
||||||
<div class="popup-section">
|
<div class="popup-section">
|
||||||
<h3 class="popup-section-title">할인 서비스</h3>
|
<h3 class="popup-section-title">파트너 스트리머의 혜택</h3>
|
||||||
|
|
||||||
<div class="discount-card">
|
<div class="popup-benefits-list">
|
||||||
<div class="discount-card-header">
|
<div class="popup-benefit-item">
|
||||||
<span class="discount-card-title">모션캡쳐 스튜디오 대관</span>
|
<div class="benefit-number">1</div>
|
||||||
<span class="discount-badge">20% 할인</span>
|
<div class="benefit-content">
|
||||||
|
<h4>모션캡쳐 스튜디오 무료 사용!</h4>
|
||||||
|
<p>월 2회 이상의 모션캡쳐 방송 지원</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="discount-price">
|
<div class="popup-benefit-item">
|
||||||
<span class="original-price">200,000원/시간</span>
|
<div class="benefit-number">2</div>
|
||||||
<span class="sale-price">160,000원/시간</span>
|
<div class="benefit-content">
|
||||||
|
<h4>밍글의 신기술을 가장 먼저 체험할 기회!</h4>
|
||||||
|
<p>후원 API 및 각종 효과 / 배경 효과 제공</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="price-note">VAT 별도</p>
|
<div class="popup-benefit-item">
|
||||||
</div>
|
<div class="benefit-number">3</div>
|
||||||
|
<div class="benefit-content">
|
||||||
<div class="discount-card">
|
<h4>미니콘서트 제작 지원 (1회)</h4>
|
||||||
<div class="discount-card-header">
|
<p>미니콘서트에 필요한 제작 지원</p>
|
||||||
<span class="discount-card-title">스트리밍글 서비스</span>
|
</div>
|
||||||
<span class="discount-badge">20% 할인</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="discount-price">
|
<div class="popup-benefit-item">
|
||||||
<span class="original-price">2,000,000원</span>
|
<div class="benefit-number">4</div>
|
||||||
<span class="sale-price">1,600,000원</span>
|
<div class="benefit-content">
|
||||||
|
<h4>기획 콘텐츠 제작 및 바추얼 아바타 자문</h4>
|
||||||
|
<p>각종 기술적/기획적 어려움이 있을 경우 자문 제공</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="price-note">1~4인 사용 / 8시간 패키지 / VAT 별도</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="popup-notice">
|
<div class="popup-notice">
|
||||||
<p>※ 뮤직비디오 제작 서비스는 할인이 미적용 됩니다</p>
|
<p>※ 자세한 내용은 파트너 페이지에서 확인하실 수 있습니다</p>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="popup-info">
|
|
||||||
<div class="info-item">
|
|
||||||
<div class="info-label">이벤트 기간</div>
|
|
||||||
<div class="info-value">~ 2025년 2월 말</div>
|
|
||||||
</div>
|
|
||||||
<div class="info-item">
|
|
||||||
<div class="info-label">예약 문의</div>
|
|
||||||
<div class="info-value">help@minglestudio.co.kr</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="popup-buttons">
|
<div class="popup-buttons">
|
||||||
<button class="popup-cta" id="popupCtaBtn">
|
<button class="popup-cta" id="popupCtaBtn">
|
||||||
지금 바로 예약하기 →
|
자세히 보기 →
|
||||||
</button>
|
|
||||||
<button class="popup-cta popup-cta-secondary" id="popupServiceBtn">
|
|
||||||
서비스 내용 보기 →
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="popup-footer">
|
|
||||||
<div class="popup-checkbox">
|
|
||||||
<input type="checkbox" id="dontShowToday">
|
|
||||||
<label for="dontShowToday">하루동안 보지 않기</label>
|
|
||||||
</div>
|
|
||||||
<button class="popup-close-btn" id="popupCloseBtn">닫기</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
375
js/partner.js
Normal file
375
js/partner.js
Normal file
@ -0,0 +1,375 @@
|
|||||||
|
// ========================================
|
||||||
|
// Partner 페이지 전용 JavaScript
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
initCopyButton();
|
||||||
|
initEmailLinkCopy();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 복사 버튼 초기화
|
||||||
|
function initCopyButton() {
|
||||||
|
const copyBtn = document.getElementById('copyTemplateBtn');
|
||||||
|
|
||||||
|
if (copyBtn) {
|
||||||
|
copyBtn.addEventListener('click', function() {
|
||||||
|
copyApplicationTemplate();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 지원서 양식 복사 함수
|
||||||
|
function copyApplicationTemplate() {
|
||||||
|
const templateText = `밍글스튜디오 파트너 스트리머 지원서
|
||||||
|
|
||||||
|
[ 기본 정보 ]
|
||||||
|
1. 현재 데뷔하여 활동하고 계신가요?
|
||||||
|
답변: (예 / 아니오)
|
||||||
|
|
||||||
|
2. 활동하고 계시다면, 활동명은 무엇인가요?
|
||||||
|
답변:
|
||||||
|
|
||||||
|
3. 어떤 방송 플랫폼에서 방송을 하고 계신가요?
|
||||||
|
답변: (예: 유튜브, 트위치, 아프리카TV, SOOP 등)
|
||||||
|
|
||||||
|
4. MCN 또는 기업 소속이신가요?
|
||||||
|
답변: (예 / 아니오)
|
||||||
|
※ 소속된 경우, 소속 회사명을 함께 기재해주세요
|
||||||
|
|
||||||
|
[ 지원 동기 및 계획 ]
|
||||||
|
5. 지원하게 된 계기가 무엇인가요?
|
||||||
|
답변:
|
||||||
|
|
||||||
|
6. 파트너 스트리머가 된다면 어떤 콘텐츠를 진행해보고 싶으신가요?
|
||||||
|
답변:
|
||||||
|
|
||||||
|
[ 경험 및 환경 ]
|
||||||
|
7. 모션 캡처를 경험해보신 적이 있으신가요?
|
||||||
|
답변: (예 / 아니오)
|
||||||
|
|
||||||
|
8. 스튜디오 방문에 어려움이 있으신가요?
|
||||||
|
※ 스튜디오는 인천광역시 부평구에 위치하고 있습니다
|
||||||
|
답변: (어려움 없음 / 다소 어렵지만 가능 / 어려움 있음)
|
||||||
|
|
||||||
|
9. 본인만의 특기가 있다면?
|
||||||
|
답변: (방송이나 유튜브 영상 링크 첨부로 대체 가능)
|
||||||
|
|
||||||
|
[ 연락처 정보 ]
|
||||||
|
• 이름:
|
||||||
|
• 이메일:
|
||||||
|
• 디스코드 아이디: `;
|
||||||
|
|
||||||
|
// 클립보드에 복사
|
||||||
|
navigator.clipboard.writeText(templateText).then(function() {
|
||||||
|
// 성공 피드백
|
||||||
|
const copyBtn = document.getElementById('copyTemplateBtn');
|
||||||
|
const originalText = copyBtn.querySelector('.copy-text').textContent;
|
||||||
|
|
||||||
|
copyBtn.classList.add('copied');
|
||||||
|
copyBtn.querySelector('.copy-text').textContent = '복사 완료!';
|
||||||
|
|
||||||
|
// 2초 후 원래대로 복원
|
||||||
|
setTimeout(function() {
|
||||||
|
copyBtn.classList.remove('copied');
|
||||||
|
copyBtn.querySelector('.copy-text').textContent = originalText;
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
|
// 알림 표시 (commonUtils 사용 가능한 경우)
|
||||||
|
if (window.commonUtils && window.commonUtils.showNotification) {
|
||||||
|
window.commonUtils.showNotification('양식이 클립보드에 복사되었습니다!', 'success');
|
||||||
|
}
|
||||||
|
}).catch(function(err) {
|
||||||
|
console.error('복사 실패:', err);
|
||||||
|
if (window.commonUtils && window.commonUtils.showNotification) {
|
||||||
|
window.commonUtils.showNotification('복사에 실패했습니다. 다시 시도해주세요.', 'error');
|
||||||
|
} else {
|
||||||
|
alert('복사에 실패했습니다. 다시 시도해주세요.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 이메일 링크 클릭 시 복사
|
||||||
|
function initEmailLinkCopy() {
|
||||||
|
const emailLink = document.getElementById('emailLink');
|
||||||
|
|
||||||
|
if (emailLink) {
|
||||||
|
emailLink.addEventListener('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const email = this.textContent.trim();
|
||||||
|
|
||||||
|
navigator.clipboard.writeText(email).then(function() {
|
||||||
|
// 성공 알림
|
||||||
|
if (window.commonUtils && window.commonUtils.showNotification) {
|
||||||
|
window.commonUtils.showNotification('이메일 주소가 복사되었습니다!', 'success');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 링크 시각적 피드백
|
||||||
|
emailLink.style.color = '#4CAF50';
|
||||||
|
setTimeout(function() {
|
||||||
|
emailLink.style.color = '';
|
||||||
|
}, 1000);
|
||||||
|
}).catch(function(err) {
|
||||||
|
console.error('이메일 복사 실패:', err);
|
||||||
|
if (window.commonUtils && window.commonUtils.showNotification) {
|
||||||
|
window.commonUtils.showNotification('복사에 실패했습니다.', 'error');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 파트너 지원 폼 초기화 (사용하지 않음 - 삭제 가능)
|
||||||
|
function initPartnerForm() {
|
||||||
|
const form = document.getElementById('partnerApplicationForm');
|
||||||
|
|
||||||
|
if (form) {
|
||||||
|
form.addEventListener('submit', handleFormSubmit);
|
||||||
|
|
||||||
|
// 실시간 유효성 검사
|
||||||
|
const inputs = form.querySelectorAll('input, textarea');
|
||||||
|
inputs.forEach(input => {
|
||||||
|
if (input.type !== 'radio' && input.type !== 'checkbox') {
|
||||||
|
input.addEventListener('blur', validateField);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 전화번호 자동 포맷팅
|
||||||
|
const phoneInput = document.getElementById('phone');
|
||||||
|
if (phoneInput) {
|
||||||
|
phoneInput.addEventListener('input', formatPhoneNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 조건부 필드 초기화
|
||||||
|
function initConditionalFields() {
|
||||||
|
// MCN/기업 소속 여부에 따라 소속명 입력란 표시
|
||||||
|
const affiliationRadios = document.querySelectorAll('input[name="hasAffiliation"]');
|
||||||
|
const affiliationNameInput = document.getElementById('affiliationName');
|
||||||
|
|
||||||
|
affiliationRadios.forEach(radio => {
|
||||||
|
radio.addEventListener('change', function() {
|
||||||
|
if (this.value === 'yes') {
|
||||||
|
affiliationNameInput.style.display = 'block';
|
||||||
|
affiliationNameInput.required = true;
|
||||||
|
} else {
|
||||||
|
affiliationNameInput.style.display = 'none';
|
||||||
|
affiliationNameInput.required = false;
|
||||||
|
affiliationNameInput.value = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 폼 제출 처리
|
||||||
|
async function handleFormSubmit(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const form = e.target;
|
||||||
|
const submitBtn = form.querySelector('button[type="submit"]');
|
||||||
|
|
||||||
|
// 유효성 검사
|
||||||
|
if (!validateForm(form)) {
|
||||||
|
if (window.commonUtils && window.commonUtils.showNotification) {
|
||||||
|
window.commonUtils.showNotification('모든 필수 항목을 입력해 주세요.', 'error');
|
||||||
|
} else {
|
||||||
|
alert('모든 필수 항목을 입력해 주세요.');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 개인정보 동의 확인
|
||||||
|
const privacyAgree = document.getElementById('privacyAgree');
|
||||||
|
if (!privacyAgree.checked) {
|
||||||
|
if (window.commonUtils && window.commonUtils.showNotification) {
|
||||||
|
window.commonUtils.showNotification('개인정보 수집 및 이용에 동의해 주세요.', 'warning');
|
||||||
|
} else {
|
||||||
|
alert('개인정보 수집 및 이용에 동의해 주세요.');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 제출 버튼 비활성화
|
||||||
|
const originalText = submitBtn.textContent;
|
||||||
|
submitBtn.textContent = '제출 중...';
|
||||||
|
submitBtn.disabled = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 폼 데이터 수집
|
||||||
|
const formData = new FormData(form);
|
||||||
|
const data = Object.fromEntries(formData);
|
||||||
|
|
||||||
|
// 서버로 전송 (실제 구현 필요)
|
||||||
|
await submitApplicationForm(data);
|
||||||
|
|
||||||
|
// 성공 메시지
|
||||||
|
if (window.commonUtils && window.commonUtils.showNotification) {
|
||||||
|
window.commonUtils.showNotification('지원서가 성공적으로 제출되었습니다. 검토 후 연락드리겠습니다!', 'success');
|
||||||
|
} else {
|
||||||
|
alert('지원서가 성공적으로 제출되었습니다. 검토 후 연락드리겠습니다!');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 폼 초기화
|
||||||
|
form.reset();
|
||||||
|
|
||||||
|
// 조건부 필드 숨기기
|
||||||
|
const affiliationNameInput = document.getElementById('affiliationName');
|
||||||
|
if (affiliationNameInput) {
|
||||||
|
affiliationNameInput.style.display = 'none';
|
||||||
|
affiliationNameInput.required = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Form submission error:', error);
|
||||||
|
if (window.commonUtils && window.commonUtils.showNotification) {
|
||||||
|
window.commonUtils.showNotification('전송 중 오류가 발생했습니다. 다시 시도해 주세요.', 'error');
|
||||||
|
} else {
|
||||||
|
alert('전송 중 오류가 발생했습니다. 다시 시도해 주세요.');
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
// 버튼 복원
|
||||||
|
submitBtn.textContent = originalText;
|
||||||
|
submitBtn.disabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 서버 전송 시뮬레이션 (실제 구현 필요)
|
||||||
|
async function submitApplicationForm(data) {
|
||||||
|
// 실제 서버 API 엔드포인트로 전송
|
||||||
|
// 예: await fetch('/api/partner-application', { method: 'POST', body: JSON.stringify(data) })
|
||||||
|
|
||||||
|
// 시뮬레이션을 위한 딜레이
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log('Application data:', data);
|
||||||
|
resolve({ success: true });
|
||||||
|
}, 1500);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 폼 유효성 검사
|
||||||
|
function validateForm(form) {
|
||||||
|
let isValid = true;
|
||||||
|
|
||||||
|
// 모든 필수 입력 필드 검사
|
||||||
|
const requiredInputs = form.querySelectorAll('input[required], textarea[required]');
|
||||||
|
requiredInputs.forEach(input => {
|
||||||
|
if (!validateField({ target: input })) {
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 라디오 버튼 그룹 검사
|
||||||
|
const requiredRadioGroups = ['isActive', 'hasAffiliation', 'hasMocapExperience', 'canVisit'];
|
||||||
|
requiredRadioGroups.forEach(groupName => {
|
||||||
|
const radios = form.querySelectorAll(`input[name="${groupName}"]`);
|
||||||
|
const checked = Array.from(radios).some(radio => radio.checked);
|
||||||
|
if (!checked) {
|
||||||
|
isValid = false;
|
||||||
|
// 라디오 그룹 에러 표시
|
||||||
|
const radioGroup = radios[0]?.closest('.form-group');
|
||||||
|
if (radioGroup) {
|
||||||
|
radioGroup.style.borderLeft = '4px solid #e74c3c';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const radioGroup = radios[0]?.closest('.form-group');
|
||||||
|
if (radioGroup) {
|
||||||
|
radioGroup.style.borderLeft = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 개별 필드 유효성 검사
|
||||||
|
function validateField(e) {
|
||||||
|
const field = e.target;
|
||||||
|
const value = field.value.trim();
|
||||||
|
let isValid = true;
|
||||||
|
let errorMessage = '';
|
||||||
|
|
||||||
|
// 필수 필드 확인
|
||||||
|
if (field.required && !value) {
|
||||||
|
isValid = false;
|
||||||
|
errorMessage = '이 항목은 필수입니다.';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 이메일 검사
|
||||||
|
if (field.type === 'email' && value) {
|
||||||
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
if (!emailRegex.test(value)) {
|
||||||
|
isValid = false;
|
||||||
|
errorMessage = '올바른 이메일 형식이 아닙니다.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 전화번호 검사
|
||||||
|
if (field.type === 'tel' && value) {
|
||||||
|
const phoneRegex = /^[0-9-]+$/;
|
||||||
|
if (!phoneRegex.test(value)) {
|
||||||
|
isValid = false;
|
||||||
|
errorMessage = '올바른 전화번호 형식이 아닙니다.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 에러 표시
|
||||||
|
if (!isValid) {
|
||||||
|
showFieldError(field, errorMessage);
|
||||||
|
} else {
|
||||||
|
clearFieldError(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
return isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 필드 에러 표시
|
||||||
|
function showFieldError(field, message) {
|
||||||
|
field.style.borderColor = '#e74c3c';
|
||||||
|
|
||||||
|
// 기존 에러 메시지 제거
|
||||||
|
const existingError = field.parentElement.querySelector('.error-message');
|
||||||
|
if (existingError) {
|
||||||
|
existingError.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 새 에러 메시지 추가
|
||||||
|
const errorDiv = document.createElement('div');
|
||||||
|
errorDiv.className = 'error-message';
|
||||||
|
errorDiv.style.color = '#e74c3c';
|
||||||
|
errorDiv.style.fontSize = '0.875rem';
|
||||||
|
errorDiv.style.marginTop = '0.5rem';
|
||||||
|
errorDiv.textContent = message;
|
||||||
|
field.parentElement.appendChild(errorDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 필드 에러 제거
|
||||||
|
function clearFieldError(field) {
|
||||||
|
if (field instanceof Event) {
|
||||||
|
field = field.target;
|
||||||
|
}
|
||||||
|
|
||||||
|
field.style.borderColor = '';
|
||||||
|
|
||||||
|
const errorMessage = field.parentElement.querySelector('.error-message');
|
||||||
|
if (errorMessage) {
|
||||||
|
errorMessage.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 전화번호 자동 포맷팅
|
||||||
|
function formatPhoneNumber(e) {
|
||||||
|
const input = e.target;
|
||||||
|
let value = input.value.replace(/[^0-9]/g, '');
|
||||||
|
|
||||||
|
// 자동 하이픈 추가
|
||||||
|
if (value.length <= 3) {
|
||||||
|
input.value = value;
|
||||||
|
} else if (value.length <= 7) {
|
||||||
|
input.value = value.slice(0, 3) + '-' + value.slice(3);
|
||||||
|
} else if (value.length <= 11) {
|
||||||
|
input.value = value.slice(0, 3) + '-' + value.slice(3, 7) + '-' + value.slice(7);
|
||||||
|
} else {
|
||||||
|
input.value = value.slice(0, 3) + '-' + value.slice(3, 7) + '-' + value.slice(7, 11);
|
||||||
|
}
|
||||||
|
}
|
||||||
53
js/popup.js
53
js/popup.js
@ -2,25 +2,6 @@
|
|||||||
* 밍글 스튜디오 메인 팝업 관리
|
* 밍글 스튜디오 메인 팝업 관리
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// 쿠키 관련 함수
|
|
||||||
function setCookie(name, value, days) {
|
|
||||||
const date = new Date();
|
|
||||||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
|
||||||
const expires = "expires=" + date.toUTCString();
|
|
||||||
document.cookie = name + "=" + value + ";" + expires + ";path=/";
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCookie(name) {
|
|
||||||
const nameEQ = name + "=";
|
|
||||||
const ca = document.cookie.split(';');
|
|
||||||
for(let i = 0; i < ca.length; i++) {
|
|
||||||
let c = ca[i];
|
|
||||||
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
|
|
||||||
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 팝업 표시 함수
|
// 팝업 표시 함수
|
||||||
function showPopup() {
|
function showPopup() {
|
||||||
const popup = document.getElementById('mainPopup');
|
const popup = document.getElementById('mainPopup');
|
||||||
@ -33,34 +14,17 @@ function showPopup() {
|
|||||||
// 팝업 닫기 함수
|
// 팝업 닫기 함수
|
||||||
function closePopup() {
|
function closePopup() {
|
||||||
const popup = document.getElementById('mainPopup');
|
const popup = document.getElementById('mainPopup');
|
||||||
const dontShowToday = document.getElementById('dontShowToday');
|
|
||||||
|
|
||||||
if (popup) {
|
if (popup) {
|
||||||
popup.classList.remove('active');
|
popup.classList.remove('active');
|
||||||
document.body.style.overflow = ''; // 스크롤 복원
|
document.body.style.overflow = ''; // 스크롤 복원
|
||||||
|
|
||||||
// "하루동안 보지 않기" 체크된 경우
|
|
||||||
if (dontShowToday && dontShowToday.checked) {
|
|
||||||
setCookie('hideMainPopup', 'true', 1); // 1일간 쿠키 저장
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 페이지 로드 시 실행
|
// 페이지 로드 시 실행
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
// 쿠키 확인
|
// 항상 팝업 표시 (1초 후)
|
||||||
const hidePopup = getCookie('hideMainPopup');
|
setTimeout(showPopup, 1000);
|
||||||
|
|
||||||
// 쿠키가 없으면 팝업 표시 (1초 후)
|
|
||||||
if (!hidePopup) {
|
|
||||||
setTimeout(showPopup, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 닫기 버튼 이벤트
|
|
||||||
const closeBtn = document.getElementById('popupCloseBtn');
|
|
||||||
if (closeBtn) {
|
|
||||||
closeBtn.addEventListener('click', closePopup);
|
|
||||||
}
|
|
||||||
|
|
||||||
// X 버튼 이벤트
|
// X 버튼 이벤트
|
||||||
const closeX = document.getElementById('popupCloseX');
|
const closeX = document.getElementById('popupCloseX');
|
||||||
@ -85,21 +49,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// CTA 버튼 클릭 시 연락처 페이지로 이동
|
// 자세히 보기 버튼 클릭 시 파트너 페이지로 이동
|
||||||
const ctaBtn = document.getElementById('popupCtaBtn');
|
const ctaBtn = document.getElementById('popupCtaBtn');
|
||||||
if (ctaBtn) {
|
if (ctaBtn) {
|
||||||
ctaBtn.addEventListener('click', function() {
|
ctaBtn.addEventListener('click', function() {
|
||||||
closePopup();
|
closePopup();
|
||||||
window.location.href = '/contact';
|
window.location.href = '/partner';
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 서비스 버튼 클릭 시 서비스 페이지로 이동
|
|
||||||
const serviceBtn = document.getElementById('popupServiceBtn');
|
|
||||||
if (serviceBtn) {
|
|
||||||
serviceBtn.addEventListener('click', function() {
|
|
||||||
closePopup();
|
|
||||||
window.location.href = '/services';
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
389
partner.html
Normal file
389
partner.html
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ko">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>파트너 스트리머 모집 - 밍글 스튜디오</title>
|
||||||
|
|
||||||
|
<!-- 파비콘 -->
|
||||||
|
<link rel="icon" type="image/x-icon" href="/mingle-logo.ico">
|
||||||
|
<link rel="shortcut icon" href="/mingle-logo.ico">
|
||||||
|
<link rel="icon" type="image/webp" href="/mingle-logo.webp">
|
||||||
|
|
||||||
|
<!-- Canonical URL -->
|
||||||
|
<link rel="canonical" href="https://minglestudio.co.kr/partner.html">
|
||||||
|
|
||||||
|
<!-- Theme Color -->
|
||||||
|
<meta name="theme-color" content="#ff8800">
|
||||||
|
|
||||||
|
<!-- SEO 메타 태그 -->
|
||||||
|
<meta name="description" content="밍글 스튜디오 파트너 스트리머 모집 - 버튜버 스트리머와 함께 성장하는 밍글 스튜디오. 모션캡쳐 스튜디오 무상 지원 프로그램">
|
||||||
|
<meta name="keywords" content="파트너 스트리머, 버튜버, VTuber, 모션캡쳐, 스트리머 모집, 밍글 스튜디오">
|
||||||
|
<meta name="author" content="밍글 스튜디오">
|
||||||
|
|
||||||
|
<!-- Open Graph -->
|
||||||
|
<meta property="og:title" content="파트너 스트리머 모집 - 밍글 스튜디오">
|
||||||
|
<meta property="og:description" content="버튜버 스트리머와 함께 성장하는 밍글 스튜디오. 모션캡쳐 스튜디오 무상 지원">
|
||||||
|
<meta property="og:url" content="https://minglestudio.co.kr/partner.html">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:image" content="https://minglestudio.co.kr/mingle-logo.webp">
|
||||||
|
<meta property="og:image:width" content="1200">
|
||||||
|
<meta property="og:image:height" content="630">
|
||||||
|
<meta property="og:locale" content="ko_KR">
|
||||||
|
<meta property="og:site_name" content="밍글 스튜디오">
|
||||||
|
|
||||||
|
<!-- Twitter Card -->
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<meta name="twitter:title" content="파트너 스트리머 모집 - 밍글 스튜디오">
|
||||||
|
<meta name="twitter:description" content="버튜버 스트리머와 함께 성장하는 밍글 스튜디오. 모션캡쳐 스튜디오 무상 지원">
|
||||||
|
<meta name="twitter:image" content="https://minglestudio.co.kr/mingle-logo.webp">
|
||||||
|
|
||||||
|
<!-- 폰트 -->
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;500;700&display=swap" rel="stylesheet">
|
||||||
|
<link href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- CSS -->
|
||||||
|
<link rel="stylesheet" href="css/common.css">
|
||||||
|
<link rel="stylesheet" href="css/partner.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- 헤더 -->
|
||||||
|
<div id="header-placeholder"></div>
|
||||||
|
|
||||||
|
<!-- Hero 섹션 -->
|
||||||
|
<section class="partner-hero">
|
||||||
|
<div class="container">
|
||||||
|
<div class="partner-hero-content">
|
||||||
|
<h1 class="partner-hero-title">
|
||||||
|
<span class="gradient-text">파트너 스트리머 모집</span>
|
||||||
|
</h1>
|
||||||
|
<p class="partner-hero-subtitle">
|
||||||
|
밍글 스튜디오와 함께 성장할 버튜버 스트리머를 찾습니다
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 지원 조건 섹션 -->
|
||||||
|
<section class="section partner-conditions-section">
|
||||||
|
<div class="container">
|
||||||
|
<div class="section-header">
|
||||||
|
<h2 class="section-title-styled">파트너 스트리머 지원 조건</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="styled-content-wrapper">
|
||||||
|
<div class="styled-list">
|
||||||
|
<div class="styled-item">
|
||||||
|
<div class="number-badge">1</div>
|
||||||
|
<div class="item-content">
|
||||||
|
<h3 class="item-title">성인 여성분</h3>
|
||||||
|
<p class="item-desc">만 19세 이상의 여성 크리에이터</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="styled-item">
|
||||||
|
<div class="number-badge">2</div>
|
||||||
|
<div class="item-content">
|
||||||
|
<h3 class="item-title">버튜버로 방송을 진행하시는 분</h3>
|
||||||
|
<p class="item-desc">활동 플랫폼 무관 (유튜브, 트위치, 아프리카TV, SOOP 등)</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="styled-item">
|
||||||
|
<div class="number-badge">3</div>
|
||||||
|
<div class="item-content">
|
||||||
|
<h3 class="item-title">MCN 또는 기업 소속 무관</h3>
|
||||||
|
<p class="item-desc">소속이 있어도 지원 가능합니다 (단, 사전 논의 필요)</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 혜택 섹션 -->
|
||||||
|
<section class="section partner-benefits-section">
|
||||||
|
<div class="container">
|
||||||
|
<div class="section-header">
|
||||||
|
<h2 class="section-title-styled">파트너 스트리머에게 바라는 것</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="styled-content-wrapper">
|
||||||
|
<div class="styled-list">
|
||||||
|
<div class="styled-item">
|
||||||
|
<div class="number-badge">1</div>
|
||||||
|
<div class="item-content">
|
||||||
|
<h3 class="item-title">밍글스튜디오의 홍보대사</h3>
|
||||||
|
<p class="item-desc">동네방네 밍글밍글 소문내주실 분!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="styled-item">
|
||||||
|
<div class="number-badge">2</div>
|
||||||
|
<div class="item-content">
|
||||||
|
<h3 class="item-title">스튜디오를 자주 이용하실 수 있으신 분</h3>
|
||||||
|
<p class="item-desc">가만히 있어도 임대료는 나가니까</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="styled-item">
|
||||||
|
<div class="number-badge">3</div>
|
||||||
|
<div class="item-content">
|
||||||
|
<h3 class="item-title">기획 능력이 좋으신 분</h3>
|
||||||
|
<p class="item-desc">상상으로만 남으면 아깝잖아요</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 제공 혜택 섹션 -->
|
||||||
|
<section class="section partner-provides-section">
|
||||||
|
<div class="container">
|
||||||
|
<div class="section-header">
|
||||||
|
<h2 class="section-title-styled">파트너 스트리머의 혜택</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="styled-content-wrapper">
|
||||||
|
<div class="styled-list">
|
||||||
|
<div class="styled-item">
|
||||||
|
<div class="number-badge">1</div>
|
||||||
|
<div class="item-content">
|
||||||
|
<h3 class="item-title">모션캡쳐 스튜디오 무료 사용!</h3>
|
||||||
|
<p class="item-desc">월 2회 이상의 모션캡쳐 방송 지원</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="styled-item">
|
||||||
|
<div class="number-badge">2</div>
|
||||||
|
<div class="item-content">
|
||||||
|
<h3 class="item-title">밍글의 신기술을 가장 먼저 체험할 기회!</h3>
|
||||||
|
<p class="item-desc">후원 API 및 각종 표과 / 배경 표과 제공</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="styled-item">
|
||||||
|
<div class="number-badge">3</div>
|
||||||
|
<div class="item-content">
|
||||||
|
<h3 class="item-title">미니콘서트 제작 지원 (1회)</h3>
|
||||||
|
<p class="item-desc">미니콘서트에 필요한 제작 지원</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="styled-item">
|
||||||
|
<div class="number-badge">4</div>
|
||||||
|
<div class="item-content">
|
||||||
|
<h3 class="item-title">기획 콘텐츠 제작 및 버추얼 아바타 자문</h3>
|
||||||
|
<p class="item-desc">각종 기술적/기획적 어려움이 있을 경우 자문 제공</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 선발 로드맵 섹션 -->
|
||||||
|
<section class="section bg-light">
|
||||||
|
<div class="container">
|
||||||
|
<div class="section-header">
|
||||||
|
<h2 class="section-title-styled">선발 로드맵</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="roadmap-wrapper">
|
||||||
|
<div class="roadmap-item">
|
||||||
|
<div class="roadmap-badge">1</div>
|
||||||
|
<div class="roadmap-content">
|
||||||
|
<h3 class="roadmap-title">지원서 모집</h3>
|
||||||
|
<p class="roadmap-date">2026.01.10 ~ 2026.01.24</p>
|
||||||
|
<p class="roadmap-desc">지원서 양식에 맞춰 이메일로 제출</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="roadmap-arrow">→</div>
|
||||||
|
|
||||||
|
<div class="roadmap-item">
|
||||||
|
<div class="roadmap-badge">2</div>
|
||||||
|
<div class="roadmap-content">
|
||||||
|
<h3 class="roadmap-title">지원서 검토</h3>
|
||||||
|
<p class="roadmap-date">2026.01.25 ~ 2026.01.31</p>
|
||||||
|
<p class="roadmap-desc">제출된 지원서 검토 및 심사</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="roadmap-arrow">→</div>
|
||||||
|
|
||||||
|
<div class="roadmap-item">
|
||||||
|
<div class="roadmap-badge">3</div>
|
||||||
|
<div class="roadmap-content">
|
||||||
|
<h3 class="roadmap-title">발표</h3>
|
||||||
|
<p class="roadmap-date">2026.02.01</p>
|
||||||
|
<p class="roadmap-desc">개별 연락을 통한 합격자 발표</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="roadmap-arrow">→</div>
|
||||||
|
|
||||||
|
<div class="roadmap-item roadmap-item-highlight">
|
||||||
|
<div class="roadmap-badge">4</div>
|
||||||
|
<div class="roadmap-content">
|
||||||
|
<h3 class="roadmap-title">활동기간</h3>
|
||||||
|
<p class="roadmap-date">2026.02.01 ~ 2026.12.31</p>
|
||||||
|
<p class="roadmap-desc">파트너 스트리머 활동 시작<br><span class="roadmap-note">(연장 가능)</span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 지원 방법 안내 섹션 -->
|
||||||
|
<section class="section bg-gradient">
|
||||||
|
<div class="container">
|
||||||
|
<div class="section-header">
|
||||||
|
<h2>지원 방법</h2>
|
||||||
|
<p>아래 양식에 맞춰 이메일로 지원서를 보내주세요</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="application-guide-wrapper">
|
||||||
|
<!-- 이메일 안내 -->
|
||||||
|
<div class="email-info-box">
|
||||||
|
<div class="email-icon">📧</div>
|
||||||
|
<h3>지원서 제출 이메일</h3>
|
||||||
|
<a href="#" class="email-link" id="emailLink">minglestudio@minglestudio.co.kr</a>
|
||||||
|
<p class="email-note">이메일 주소를 클릭하면 복사됩니다</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 지원서 양식 -->
|
||||||
|
<div class="application-form-template">
|
||||||
|
<div class="template-header">
|
||||||
|
<h3 class="template-title">📋 밍글스튜디오 파트너 스트리머 지원서 양식</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="applicationTemplate" class="template-content">
|
||||||
|
<div class="template-section">
|
||||||
|
<h4>[ 기본 정보 ]</h4>
|
||||||
|
<div class="question-item">
|
||||||
|
<p class="question">1. 현재 데뷔하여 활동하고 계신가요?</p>
|
||||||
|
<p class="answer-guide">답변: (예 / 아니오)</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="question-item">
|
||||||
|
<p class="question">2. 활동하고 계시다면, 활동명은 무엇인가요?</p>
|
||||||
|
<p class="answer-guide">답변: </p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="question-item">
|
||||||
|
<p class="question">3. 어떤 방송 플랫폼에서 방송을 하고 계신가요?</p>
|
||||||
|
<p class="answer-guide">답변: (예: 유튜브, 트위치, 아프리카TV, SOOP 등)</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="question-item">
|
||||||
|
<p class="question">4. MCN 또는 기업 소속이신가요?</p>
|
||||||
|
<p class="answer-guide">답변: (예 / 아니오)</p>
|
||||||
|
<p class="answer-sub">※ 소속된 경우, 소속 회사명을 함께 기재해주세요</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="template-section">
|
||||||
|
<h4>[ 지원 동기 및 계획 ]</h4>
|
||||||
|
<div class="question-item">
|
||||||
|
<p class="question">5. 지원하게 된 계기가 무엇인가요?</p>
|
||||||
|
<p class="answer-guide">답변: </p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="question-item">
|
||||||
|
<p class="question">6. 파트너 스트리머가 된다면 어떤 콘텐츠를 진행해보고 싶으신가요?</p>
|
||||||
|
<p class="answer-guide">답변: </p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="template-section">
|
||||||
|
<h4>[ 경험 및 환경 ]</h4>
|
||||||
|
<div class="question-item">
|
||||||
|
<p class="question">7. 모션 캡처를 경험해보신 적이 있으신가요?</p>
|
||||||
|
<p class="answer-guide">답변: (예 / 아니오)</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="question-item">
|
||||||
|
<p class="question">8. 스튜디오 방문에 어려움이 있으신가요?</p>
|
||||||
|
<p class="answer-sub">※ 스튜디오는 인천광역시 부평구에 위치하고 있습니다</p>
|
||||||
|
<p class="answer-guide">답변: (어려움 없음 / 다소 어렵지만 가능 / 어려움 있음)</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="question-item">
|
||||||
|
<p class="question">9. 본인만의 특기가 있다면?</p>
|
||||||
|
<p class="answer-guide">답변: (방송이나 유튜브 영상 링크 첨부로 대체 가능)</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="template-section">
|
||||||
|
<h4>[ 연락처 정보 ]</h4>
|
||||||
|
<div class="question-item">
|
||||||
|
<p class="question">• 이름:</p>
|
||||||
|
</div>
|
||||||
|
<div class="question-item">
|
||||||
|
<p class="question">• 이메일:</p>
|
||||||
|
</div>
|
||||||
|
<div class="question-item">
|
||||||
|
<p class="question">• 디스코드 아이디:</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 양식 복사 버튼 -->
|
||||||
|
<div style="text-align: center; margin-top: 2rem;">
|
||||||
|
<button id="copyTemplateBtn" class="copy-template-btn">
|
||||||
|
<span class="copy-icon">📋</span>
|
||||||
|
<span class="copy-text">양식 복사하기</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 지원 안내 -->
|
||||||
|
<div class="application-notice-box">
|
||||||
|
<h4>📌 지원 시 유의사항</h4>
|
||||||
|
<ul>
|
||||||
|
<li>위 "양식 복사하기" 버튼으로 양식을 복사한 후 답변을 작성하여 <strong>minglestudio@minglestudio.co.kr</strong>로 보내주세요</li>
|
||||||
|
<li>이메일 제목은 <strong>"[파트너 스트리머 지원] 활동명"</strong> 형식으로 작성해주세요</li>
|
||||||
|
<li>지원서 검토 후 개별 연락 드립니다</li>
|
||||||
|
<li>포트폴리오나 방송 영상이 있다면 함께 첨부해주시면 좋습니다</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- CTA 섹션 -->
|
||||||
|
<section class="cta-section">
|
||||||
|
<div class="container text-center">
|
||||||
|
<h2 class="cta-title">궁금한 점이 있으신가요?</h2>
|
||||||
|
<p class="cta-description">
|
||||||
|
파트너 스트리머 모집에 대한 문의사항은 언제든 연락주세요
|
||||||
|
</p>
|
||||||
|
<div class="contact-info-quick">
|
||||||
|
<span>📧 minglestudio@minglestudio.co.kr</span>
|
||||||
|
<span>📞 010-9288-9190</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 푸터 -->
|
||||||
|
<div id="footer-placeholder"></div>
|
||||||
|
|
||||||
|
<!-- 백업 푸터 -->
|
||||||
|
<footer class="partner-footer">
|
||||||
|
<div class="container" style="text-align:center;">
|
||||||
|
<div style="font-size:1.15rem;font-weight:700;letter-spacing:0.02em;">회사명: 밍글 스튜디오 | 대표: 김희진</div>
|
||||||
|
<div style="margin:0.3rem 0 0.2rem;">주소: (21330) 인천광역시 부평구 주부토로 236, 인천테크노밸리 U1센터 A동 B105호</div>
|
||||||
|
<div style="margin:0.3rem 0 0.2rem;">전화: 010-9288-9190 | 비즈니스 문의: minglestudio@minglestudio.co.kr | 예약 문의: help@minglestudio.co.kr</div>
|
||||||
|
<div style="margin:0.3rem 0 0.2rem;">사업자등록번호: 208-12-73755</div>
|
||||||
|
<div style="color:#bbb;font-size:0.98rem;margin-top:0.7rem;">© 2025 밍글 스튜디오. All rights reserved.</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<!-- JavaScript -->
|
||||||
|
<script src="js/common.js"></script>
|
||||||
|
<script src="js/partner.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
64
server.py
64
server.py
@ -274,6 +274,33 @@ def find_available_port(start_port=8001):
|
|||||||
print(f"No available port found in range {start_port}-{start_port+19}")
|
print(f"No available port found in range {start_port}-{start_port+19}")
|
||||||
return start_port # 찾지 못하면 기본값 반환
|
return start_port # 찾지 못하면 기본값 반환
|
||||||
|
|
||||||
|
def create_self_signed_cert():
|
||||||
|
"""자체 서명 인증서 생성"""
|
||||||
|
cert_file = 'server.crt'
|
||||||
|
key_file = 'server.key'
|
||||||
|
|
||||||
|
# 인증서가 이미 존재하면 재사용
|
||||||
|
if os.path.exists(cert_file) and os.path.exists(key_file):
|
||||||
|
print(f"Using existing SSL certificate: {cert_file}")
|
||||||
|
return cert_file, key_file
|
||||||
|
|
||||||
|
print("Generating self-signed SSL certificate...")
|
||||||
|
try:
|
||||||
|
import subprocess
|
||||||
|
# OpenSSL을 사용하여 자체 서명 인증서 생성
|
||||||
|
subprocess.run([
|
||||||
|
'openssl', 'req', '-x509', '-newkey', 'rsa:4096',
|
||||||
|
'-keyout', key_file, '-out', cert_file,
|
||||||
|
'-days', '365', '-nodes',
|
||||||
|
'-subj', '/CN=localhost'
|
||||||
|
], check=True, capture_output=True)
|
||||||
|
print(f"SSL certificate created: {cert_file}, {key_file}")
|
||||||
|
return cert_file, key_file
|
||||||
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||||
|
print("Warning: OpenSSL not found. Cannot create SSL certificate.")
|
||||||
|
print("Install OpenSSL or use the caddy server for HTTPS.")
|
||||||
|
return None, None
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""메인 서버 실행 함수"""
|
"""메인 서버 실행 함수"""
|
||||||
# 현재 디렉토리가 프로젝트 루트인지 확인
|
# 현재 디렉토리가 프로젝트 루트인지 확인
|
||||||
@ -285,10 +312,15 @@ def main():
|
|||||||
# 사용 가능한 포트 찾기
|
# 사용 가능한 포트 찾기
|
||||||
available_port = find_available_port(PORT)
|
available_port = find_available_port(PORT)
|
||||||
|
|
||||||
|
# Force HTTP mode (Caddy handles HTTPS)
|
||||||
|
use_https = False
|
||||||
|
protocol = "http"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 서버 시작
|
# 서버 시작
|
||||||
httpd = socketserver.TCPServer((HOST, available_port), CustomHTTPRequestHandler)
|
httpd = socketserver.TCPServer((HOST, available_port), CustomHTTPRequestHandler)
|
||||||
httpd.allow_reuse_address = True # 주소 재사용 허용
|
httpd.allow_reuse_address = True # 주소 재사용 허용
|
||||||
|
|
||||||
with httpd:
|
with httpd:
|
||||||
# 로컬 및 외부 접근 주소 표시
|
# 로컬 및 외부 접근 주소 표시
|
||||||
import socket
|
import socket
|
||||||
@ -296,20 +328,24 @@ def main():
|
|||||||
|
|
||||||
print("Mingle Studio Development Server Started!")
|
print("Mingle Studio Development Server Started!")
|
||||||
print("="*60)
|
print("="*60)
|
||||||
print(f"Local Access: http://localhost:{available_port}")
|
print(f"Local Access: {protocol}://localhost:{available_port}")
|
||||||
print(f"Network Access: http://{local_ip}:{available_port}")
|
print(f"Network Access: {protocol}://{local_ip}:{available_port}")
|
||||||
print(f"Root Directory: {os.getcwd()}")
|
print(f"Root Directory: {os.getcwd()}")
|
||||||
|
if use_https:
|
||||||
|
print("⚠️ Using self-signed certificate - browser will show security warning")
|
||||||
|
print(" Click 'Advanced' → 'Proceed' to continue")
|
||||||
print("="*60)
|
print("="*60)
|
||||||
print("Main Pages:")
|
print("Main Pages:")
|
||||||
print(f" Home: http://localhost:{available_port}/")
|
print(f" Home: {protocol}://localhost:{available_port}/")
|
||||||
print(f" About: http://localhost:{available_port}/about")
|
print(f" About: {protocol}://localhost:{available_port}/about")
|
||||||
print(f" Services: http://localhost:{available_port}/services")
|
print(f" Services: {protocol}://localhost:{available_port}/services")
|
||||||
print(f" Portfolio: http://localhost:{available_port}/portfolio")
|
print(f" Portfolio: {protocol}://localhost:{available_port}/portfolio")
|
||||||
print(f" Gallery: http://localhost:{available_port}/gallery")
|
print(f" Gallery: {protocol}://localhost:{available_port}/gallery")
|
||||||
print(f" Contact: http://localhost:{available_port}/contact")
|
print(f" Contact: {protocol}://localhost:{available_port}/contact")
|
||||||
print(f" Q&A: http://localhost:{available_port}/qna")
|
print(f" Q&A: {protocol}://localhost:{available_port}/qna")
|
||||||
print(f" Backgrounds: http://localhost:{available_port}/backgrounds")
|
print(f" Backgrounds: {protocol}://localhost:{available_port}/backgrounds")
|
||||||
print(f" Props: http://localhost:{available_port}/props")
|
print(f" Props: {protocol}://localhost:{available_port}/props")
|
||||||
|
print(f" Partner: {protocol}://localhost:{available_port}/partner")
|
||||||
print("="*60)
|
print("="*60)
|
||||||
print("API Endpoints:")
|
print("API Endpoints:")
|
||||||
print(f" GET /api/backgrounds - 배경 데이터 조회")
|
print(f" GET /api/backgrounds - 배경 데이터 조회")
|
||||||
@ -319,14 +355,14 @@ def main():
|
|||||||
print("="*60)
|
print("="*60)
|
||||||
print("External Access Setup:")
|
print("External Access Setup:")
|
||||||
print(f" 1. Setup port forwarding for port {available_port} on router")
|
print(f" 1. Setup port forwarding for port {available_port} on router")
|
||||||
print(f" 2. Access via public IP: http://[PUBLIC_IP]:{available_port}")
|
print(f" 2. Access via public IP: {protocol}://[PUBLIC_IP]:{available_port}")
|
||||||
print(f" 3. Same network: http://{local_ip}:{available_port}")
|
print(f" 3. Same network: {protocol}://{local_ip}:{available_port}")
|
||||||
print("="*60)
|
print("="*60)
|
||||||
print("Tip: Press Ctrl+C to stop the server.")
|
print("Tip: Press Ctrl+C to stop the server.")
|
||||||
print("Opening browser automatically...")
|
print("Opening browser automatically...")
|
||||||
|
|
||||||
# 기본 브라우저에서 자동으로 열기 (로컬호스트로)
|
# 기본 브라우저에서 자동으로 열기 (로컬호스트로)
|
||||||
webbrowser.open(f"http://localhost:{available_port}")
|
webbrowser.open(f"{protocol}://localhost:{available_port}")
|
||||||
|
|
||||||
# 서버 실행
|
# 서버 실행
|
||||||
httpd.serve_forever()
|
httpd.serve_forever()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user