메인 페이지 화면설계서 적용
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,144 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// This file contains all application-wide SASS mixins
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Media query mixins
|
||||
@mixin respond-to($breakpoint) {
|
||||
@if $breakpoint == 'xs' {
|
||||
@media (max-width: #{$breakpoint-xs}) { @content; }
|
||||
} @else if $breakpoint == 'sm' {
|
||||
@media (max-width: #{$breakpoint-sm}) { @content; }
|
||||
} @else if $breakpoint == 'md' {
|
||||
@media (max-width: #{$breakpoint-md}) { @content; }
|
||||
} @else if $breakpoint == 'lg' {
|
||||
@media (min-width: #{$breakpoint-lg}) { @content; }
|
||||
} @else if $breakpoint == 'xl' {
|
||||
@media (min-width: #{$breakpoint-xl}) { @content; }
|
||||
} @else if $breakpoint == 'mobile' {
|
||||
@media (max-width: #{$breakpoint-lg}) { @content; }
|
||||
} @else if $breakpoint == 'tablet' {
|
||||
@media (max-width: #{$breakpoint-md}) { @content; }
|
||||
}
|
||||
}
|
||||
|
||||
// Flexbox mixins
|
||||
@mixin flex-center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@mixin flex-between {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
// Button mixin
|
||||
@mixin button-base {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: $spacing-sm;
|
||||
padding: $button-padding-y $button-padding-x;
|
||||
border-radius: $border-radius-lg;
|
||||
font-weight: $font-weight-semibold;
|
||||
font-size: $font-size-base;
|
||||
text-decoration: none;
|
||||
transition: $transition-base;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
}
|
||||
|
||||
// Card mixin
|
||||
@mixin card {
|
||||
background: $white;
|
||||
border-radius: $border-radius-2xl;
|
||||
padding: $card-padding;
|
||||
transition: $transition-base;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: $shadow-lg;
|
||||
}
|
||||
}
|
||||
|
||||
// Gradient text
|
||||
@mixin gradient-text($gradient) {
|
||||
background: $gradient;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
// Truncate text
|
||||
@mixin text-truncate {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
// Absolute center
|
||||
@mixin absolute-center {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
// Backdrop blur
|
||||
@mixin backdrop-blur($amount: 10px) {
|
||||
backdrop-filter: blur($amount);
|
||||
-webkit-backdrop-filter: blur($amount);
|
||||
}
|
||||
|
||||
// Animation mixins
|
||||
@mixin animate-float {
|
||||
animation: float 20s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@mixin animate-bounce {
|
||||
animation: bounce 2s infinite;
|
||||
}
|
||||
|
||||
@mixin animate-slide-in-down {
|
||||
animation: slideInDown 0.6s ease-out;
|
||||
}
|
||||
|
||||
@mixin animate-slide-in-up {
|
||||
animation: slideInUp 0.8s ease-out;
|
||||
}
|
||||
|
||||
@mixin animate-fade-in {
|
||||
animation: fadeIn 1.2s ease-out;
|
||||
}
|
||||
|
||||
// Hover lift effect
|
||||
@mixin hover-lift {
|
||||
transition: $transition-base;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-8px);
|
||||
box-shadow: $shadow-xl;
|
||||
}
|
||||
}
|
||||
|
||||
// Glass effect
|
||||
@mixin glass-effect {
|
||||
background: rgba($white, 0.95);
|
||||
@include backdrop-blur(10px);
|
||||
border: 1px solid rgba($white, 0.18);
|
||||
}
|
||||
|
||||
// Pattern circle
|
||||
@mixin pattern-circle($size, $color) {
|
||||
width: $size;
|
||||
height: $size;
|
||||
background: $color;
|
||||
border-radius: 50%;
|
||||
opacity: 0.1;
|
||||
position: absolute;
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// This file contains all application-wide SASS variables
|
||||
// Based on design/styles-v2.css - Modern vibrant design system
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Color Palette - Vibrant and Modern
|
||||
// Primary colors
|
||||
$primary-blue: #4B9BFF; // Bright blue (main brand color)
|
||||
$secondary-blue: #2E7FF7; // Deep blue
|
||||
$accent-cyan: #00D4FF; // Sky blue accent
|
||||
$accent-yellow: #FFD93D; // Yellow accent
|
||||
$accent-orange: #FF6B6B; // Orange accent
|
||||
$accent-green: #6BCF7F; // Green accent
|
||||
$accent-purple: #A78BFA; // Purple accent
|
||||
|
||||
// Neutral colors
|
||||
$text-dark: #1A1A2E; // Main text color
|
||||
$text-gray: #64748B; // Secondary text
|
||||
$text-light: #94A3B8; // Light text
|
||||
$white: #FFFFFF; // Pure white
|
||||
$gray-bg: #F8FAFC; // Light background
|
||||
$light-bg: #EFF6FF; // Blue tinted background
|
||||
$border-gray: #E2E8F0; // Border color
|
||||
$black: #000000; // Pure black
|
||||
$gray-800: #1F2937; // Dark gray
|
||||
$gray-900: #111827; // Darker gray
|
||||
|
||||
// Gradients
|
||||
$gradient-primary: linear-gradient(135deg, $primary-blue 0%, $secondary-blue 100%);
|
||||
$gradient-accent: linear-gradient(135deg, $accent-cyan 0%, $primary-blue 100%);
|
||||
$gradient-warm: linear-gradient(135deg, $accent-yellow 0%, $accent-orange 100%);
|
||||
|
||||
// Shadows
|
||||
$shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||
$shadow-md: 0 4px 12px rgba(75, 155, 255, 0.1);
|
||||
$shadow-lg: 0 8px 24px rgba(75, 155, 255, 0.15);
|
||||
$shadow-xl: 0 16px 40px rgba(75, 155, 255, 0.2);
|
||||
|
||||
// Typography
|
||||
$font-family-primary: 'Pretendard', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans KR', sans-serif;
|
||||
$font-family-mono: 'Fira Code', 'Courier New', monospace;
|
||||
|
||||
// Font sizes
|
||||
$font-size-xs: 12px;
|
||||
$font-size-sm: 14px;
|
||||
$font-size-base: 16px;
|
||||
$font-size-md: 18px;
|
||||
$font-size-lg: 20px;
|
||||
$font-size-xl: 24px;
|
||||
$font-size-2xl: 32px;
|
||||
$font-size-3xl: 40px;
|
||||
$font-size-4xl: 48px;
|
||||
$font-size-5xl: 56px;
|
||||
|
||||
// Font weights
|
||||
$font-weight-regular: 400;
|
||||
$font-weight-medium: 500;
|
||||
$font-weight-semibold: 600;
|
||||
$font-weight-bold: 700;
|
||||
$font-weight-extrabold: 800;
|
||||
|
||||
// Line heights
|
||||
$line-height-tight: 1.2;
|
||||
$line-height-normal: 1.6;
|
||||
$line-height-loose: 1.8;
|
||||
|
||||
// Spacing
|
||||
$spacing-xs: 4px;
|
||||
$spacing-sm: 8px;
|
||||
$spacing-md: 16px;
|
||||
$spacing-lg: 24px;
|
||||
$spacing-xl: 32px;
|
||||
$spacing-2xl: 40px;
|
||||
$spacing-3xl: 48px;
|
||||
$spacing-4xl: 64px;
|
||||
$spacing-5xl: 80px;
|
||||
$spacing-6xl: 100px;
|
||||
|
||||
// Border radius
|
||||
$border-radius-sm: 6px;
|
||||
$border-radius-md: 8px;
|
||||
$border-radius-lg: 12px;
|
||||
$border-radius-xl: 16px;
|
||||
$border-radius-2xl: 20px;
|
||||
$border-radius-full: 50px;
|
||||
$border-radius-circle: 50%;
|
||||
|
||||
// Layout
|
||||
$container-max-width: 1280px;
|
||||
$header-height: 80px;
|
||||
|
||||
// Breakpoints
|
||||
$breakpoint-xs: 480px;
|
||||
$breakpoint-sm: 768px;
|
||||
$breakpoint-md: 1024px;
|
||||
$breakpoint-lg: 1280px;
|
||||
$breakpoint-xl: 1440px;
|
||||
|
||||
// Z-index
|
||||
$z-index-dropdown: 100;
|
||||
$z-index-sticky: 200;
|
||||
$z-index-fixed: 300;
|
||||
$z-index-header: 350;
|
||||
$z-index-modal-backdrop: 400;
|
||||
$z-index-modal: 500;
|
||||
$z-index-popover: 600;
|
||||
$z-index-tooltip: 700;
|
||||
$z-index-notification: 800;
|
||||
|
||||
// Animation
|
||||
$transition-base: all 0.3s ease;
|
||||
$transition-fast: all 0.15s ease;
|
||||
$transition-slow: all 0.5s ease;
|
||||
|
||||
// Component specific variables
|
||||
$button-padding-x: 32px;
|
||||
$button-padding-y: 16px;
|
||||
$card-padding: 32px;
|
||||
$input-padding-x: 16px;
|
||||
$input-padding-y: 12px;
|
||||
$input-height: 48px;
|
||||
@@ -0,0 +1,330 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Animation keyframes and utilities
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Float animation
|
||||
@keyframes float {
|
||||
0%, 100% {
|
||||
transform: translateY(0) rotate(0deg);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-30px) rotate(10deg);
|
||||
}
|
||||
}
|
||||
|
||||
// Bounce animation
|
||||
@keyframes bounce {
|
||||
0%, 100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
}
|
||||
|
||||
// Slide in from top
|
||||
@keyframes slideInDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Slide in from bottom
|
||||
@keyframes slideInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Slide in from left
|
||||
@keyframes slideInLeft {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Slide in from right
|
||||
@keyframes slideInRight {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Fade in
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Fade in and scale
|
||||
@keyframes fadeInScale {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.9);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Spin
|
||||
@keyframes spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
// Pulse
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Shimmer effect
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
transform: translateX(-100%) rotate(45deg);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(100%) rotate(45deg);
|
||||
}
|
||||
}
|
||||
|
||||
// Wave
|
||||
@keyframes wave {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
10% {
|
||||
transform: rotate(14deg);
|
||||
}
|
||||
20% {
|
||||
transform: rotate(-8deg);
|
||||
}
|
||||
30% {
|
||||
transform: rotate(14deg);
|
||||
}
|
||||
40% {
|
||||
transform: rotate(-4deg);
|
||||
}
|
||||
50% {
|
||||
transform: rotate(10deg);
|
||||
}
|
||||
60% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
// Pop in
|
||||
@keyframes popIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(0.5);
|
||||
}
|
||||
80% {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Popup fade in (for modals)
|
||||
@keyframes popupFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Ripple effect
|
||||
@keyframes ripple {
|
||||
0% {
|
||||
transform: scale(0);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: scale(4);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Gradient animation
|
||||
@keyframes gradientShift {
|
||||
0% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
50% {
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
100% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
// Animation utility classes
|
||||
.animate-float {
|
||||
animation: float 20s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.animate-bounce {
|
||||
animation: bounce 2s infinite;
|
||||
}
|
||||
|
||||
.animate-spin {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
.animate-pulse {
|
||||
animation: pulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.animate-fade-in {
|
||||
animation: fadeIn 0.6s ease-out;
|
||||
}
|
||||
|
||||
.animate-slide-up {
|
||||
animation: slideInUp 0.8s ease-out;
|
||||
}
|
||||
|
||||
.animate-slide-down {
|
||||
animation: slideInDown 0.6s ease-out;
|
||||
}
|
||||
|
||||
.animate-pop {
|
||||
animation: popIn 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
}
|
||||
|
||||
// Animation delays
|
||||
.delay-1 {
|
||||
animation-delay: 0.1s;
|
||||
}
|
||||
|
||||
.delay-2 {
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.delay-3 {
|
||||
animation-delay: 0.3s;
|
||||
}
|
||||
|
||||
.delay-4 {
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
.delay-5 {
|
||||
animation-delay: 0.5s;
|
||||
}
|
||||
|
||||
// Animation durations
|
||||
.duration-fast {
|
||||
animation-duration: 0.3s;
|
||||
}
|
||||
|
||||
.duration-normal {
|
||||
animation-duration: 0.6s;
|
||||
}
|
||||
|
||||
.duration-slow {
|
||||
animation-duration: 1s;
|
||||
}
|
||||
|
||||
.duration-slower {
|
||||
animation-duration: 2s;
|
||||
}
|
||||
|
||||
// Hover animation triggers
|
||||
.hover-grow {
|
||||
transition: transform 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
}
|
||||
|
||||
.hover-lift {
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: $shadow-lg;
|
||||
}
|
||||
}
|
||||
|
||||
.hover-rotate {
|
||||
transition: transform 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: rotate(5deg);
|
||||
}
|
||||
}
|
||||
|
||||
.hover-shine {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
left: -50%;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
background: linear-gradient(
|
||||
45deg,
|
||||
transparent 30%,
|
||||
rgba(255, 255, 255, 0.2) 50%,
|
||||
transparent 70%
|
||||
);
|
||||
transform: rotate(45deg);
|
||||
transition: transform 0.6s ease;
|
||||
transform: translateX(-200%);
|
||||
}
|
||||
|
||||
&:hover::before {
|
||||
transform: translateX(200%) rotate(45deg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Reset and normalize styles
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
font-size: 16px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: $font-family-primary;
|
||||
line-height: $line-height-normal;
|
||||
color: $text-dark;
|
||||
background-color: $white;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
// Lists
|
||||
ul, ol {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
// Links
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
transition: $transition-base;
|
||||
}
|
||||
|
||||
// Images
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
// Buttons
|
||||
button {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
cursor: pointer;
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
// Forms
|
||||
input,
|
||||
textarea,
|
||||
select {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
// Tables
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
// Headings
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: $font-weight-bold;
|
||||
line-height: $line-height-tight;
|
||||
}
|
||||
|
||||
// Semantic HTML5 elements
|
||||
article, aside, details, figcaption, figure,
|
||||
footer, header, hgroup, main, menu, nav,
|
||||
section, summary {
|
||||
display: block;
|
||||
}
|
||||
|
||||
// Selection
|
||||
::selection {
|
||||
background-color: rgba($primary-blue, 0.2);
|
||||
color: $text-dark;
|
||||
}
|
||||
|
||||
::-moz-selection {
|
||||
background-color: rgba($primary-blue, 0.2);
|
||||
color: $text-dark;
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Basic typography styles
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Body text
|
||||
body {
|
||||
font-size: $font-size-base;
|
||||
font-weight: $font-weight-regular;
|
||||
color: $text-dark;
|
||||
}
|
||||
|
||||
// Headings
|
||||
h1, .h1 {
|
||||
font-size: $font-size-5xl;
|
||||
font-weight: $font-weight-extrabold;
|
||||
margin-bottom: $spacing-lg;
|
||||
|
||||
@include respond-to('sm') {
|
||||
font-size: $font-size-3xl;
|
||||
}
|
||||
|
||||
@include respond-to('xs') {
|
||||
font-size: $font-size-2xl;
|
||||
}
|
||||
}
|
||||
|
||||
h2, .h2 {
|
||||
font-size: $font-size-4xl;
|
||||
font-weight: $font-weight-bold;
|
||||
margin-bottom: $spacing-md;
|
||||
|
||||
@include respond-to('sm') {
|
||||
font-size: $font-size-2xl;
|
||||
}
|
||||
|
||||
@include respond-to('xs') {
|
||||
font-size: $font-size-xl;
|
||||
}
|
||||
}
|
||||
|
||||
h3, .h3 {
|
||||
font-size: $font-size-3xl;
|
||||
font-weight: $font-weight-bold;
|
||||
margin-bottom: $spacing-md;
|
||||
|
||||
@include respond-to('sm') {
|
||||
font-size: $font-size-xl;
|
||||
}
|
||||
}
|
||||
|
||||
h4, .h4 {
|
||||
font-size: $font-size-2xl;
|
||||
font-weight: $font-weight-semibold;
|
||||
margin-bottom: $spacing-sm;
|
||||
}
|
||||
|
||||
h5, .h5 {
|
||||
font-size: $font-size-xl;
|
||||
font-weight: $font-weight-semibold;
|
||||
margin-bottom: $spacing-sm;
|
||||
}
|
||||
|
||||
h6, .h6 {
|
||||
font-size: $font-size-lg;
|
||||
font-weight: $font-weight-semibold;
|
||||
margin-bottom: $spacing-sm;
|
||||
}
|
||||
|
||||
// Paragraphs
|
||||
p {
|
||||
margin-bottom: $spacing-md;
|
||||
line-height: $line-height-normal;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Text utilities
|
||||
.text-gradient {
|
||||
@include gradient-text($gradient-primary);
|
||||
}
|
||||
|
||||
.text-gradient-accent {
|
||||
@include gradient-text($gradient-accent);
|
||||
}
|
||||
|
||||
.text-gradient-warm {
|
||||
@include gradient-text($gradient-warm);
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
color: $primary-blue;
|
||||
}
|
||||
|
||||
.text-secondary {
|
||||
color: $secondary-blue;
|
||||
}
|
||||
|
||||
.text-dark {
|
||||
color: $text-dark;
|
||||
}
|
||||
|
||||
.text-gray {
|
||||
color: $text-gray;
|
||||
}
|
||||
|
||||
.text-light {
|
||||
color: $text-light;
|
||||
}
|
||||
|
||||
.text-white {
|
||||
color: $white;
|
||||
}
|
||||
|
||||
// Text alignment
|
||||
.text-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
// Font weights
|
||||
.font-regular {
|
||||
font-weight: $font-weight-regular;
|
||||
}
|
||||
|
||||
.font-medium {
|
||||
font-weight: $font-weight-medium;
|
||||
}
|
||||
|
||||
.font-semibold {
|
||||
font-weight: $font-weight-semibold;
|
||||
}
|
||||
|
||||
.font-bold {
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
|
||||
.font-extrabold {
|
||||
font-weight: $font-weight-extrabold;
|
||||
}
|
||||
|
||||
// Text sizes
|
||||
.text-xs {
|
||||
font-size: $font-size-xs;
|
||||
}
|
||||
|
||||
.text-sm {
|
||||
font-size: $font-size-sm;
|
||||
}
|
||||
|
||||
.text-base {
|
||||
font-size: $font-size-base;
|
||||
}
|
||||
|
||||
.text-lg {
|
||||
font-size: $font-size-lg;
|
||||
}
|
||||
|
||||
.text-xl {
|
||||
font-size: $font-size-xl;
|
||||
}
|
||||
|
||||
// Special text styles
|
||||
.lead {
|
||||
font-size: $font-size-lg;
|
||||
font-weight: $font-weight-regular;
|
||||
line-height: $line-height-loose;
|
||||
color: $text-gray;
|
||||
}
|
||||
|
||||
.caption {
|
||||
font-size: $font-size-sm;
|
||||
color: $text-gray;
|
||||
}
|
||||
|
||||
.code {
|
||||
font-family: $font-family-mono;
|
||||
font-size: $font-size-sm;
|
||||
background: $gray-bg;
|
||||
padding: 2px 6px;
|
||||
border-radius: $border-radius-sm;
|
||||
}
|
||||
|
||||
// Links
|
||||
a {
|
||||
color: $primary-blue;
|
||||
|
||||
&:hover {
|
||||
color: $secondary-blue;
|
||||
}
|
||||
}
|
||||
|
||||
// Blockquote
|
||||
blockquote {
|
||||
padding: $spacing-md;
|
||||
margin: $spacing-md 0;
|
||||
border-left: 4px solid $primary-blue;
|
||||
background: $gray-bg;
|
||||
font-style: italic;
|
||||
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Horizontal rule
|
||||
hr {
|
||||
border: none;
|
||||
border-top: 1px solid $border-gray;
|
||||
margin: $spacing-xl 0;
|
||||
}
|
||||
@@ -0,0 +1,497 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Utility classes
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Container
|
||||
.container {
|
||||
max-width: $container-max-width;
|
||||
margin: 0 auto;
|
||||
padding: 0 $spacing-lg;
|
||||
|
||||
@include respond-to('sm') {
|
||||
padding: 0 $spacing-md;
|
||||
}
|
||||
}
|
||||
|
||||
// Display utilities
|
||||
.d-none {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.d-block {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.d-inline-block {
|
||||
display: inline-block !important;
|
||||
}
|
||||
|
||||
.d-flex {
|
||||
display: flex !important;
|
||||
}
|
||||
|
||||
.d-inline-flex {
|
||||
display: inline-flex !important;
|
||||
}
|
||||
|
||||
.d-grid {
|
||||
display: grid !important;
|
||||
}
|
||||
|
||||
// Flexbox utilities
|
||||
.flex-center {
|
||||
@include flex-center;
|
||||
}
|
||||
|
||||
.flex-between {
|
||||
@include flex-between;
|
||||
}
|
||||
|
||||
.flex-column {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.flex-wrap {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.align-start {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.align-end {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.justify-center {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.justify-start {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.justify-end {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.justify-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.justify-around {
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
// Gap utilities
|
||||
.gap-xs {
|
||||
gap: $spacing-xs;
|
||||
}
|
||||
|
||||
.gap-sm {
|
||||
gap: $spacing-sm;
|
||||
}
|
||||
|
||||
.gap-md {
|
||||
gap: $spacing-md;
|
||||
}
|
||||
|
||||
.gap-lg {
|
||||
gap: $spacing-lg;
|
||||
}
|
||||
|
||||
.gap-xl {
|
||||
gap: $spacing-xl;
|
||||
}
|
||||
|
||||
// Margin utilities
|
||||
@each $size, $value in (
|
||||
0: 0,
|
||||
xs: $spacing-xs,
|
||||
sm: $spacing-sm,
|
||||
md: $spacing-md,
|
||||
lg: $spacing-lg,
|
||||
xl: $spacing-xl,
|
||||
2xl: $spacing-2xl,
|
||||
3xl: $spacing-3xl,
|
||||
4xl: $spacing-4xl,
|
||||
auto: auto
|
||||
) {
|
||||
.m-#{$size} {
|
||||
margin: $value !important;
|
||||
}
|
||||
|
||||
.mt-#{$size} {
|
||||
margin-top: $value !important;
|
||||
}
|
||||
|
||||
.mb-#{$size} {
|
||||
margin-bottom: $value !important;
|
||||
}
|
||||
|
||||
.ml-#{$size} {
|
||||
margin-left: $value !important;
|
||||
}
|
||||
|
||||
.mr-#{$size} {
|
||||
margin-right: $value !important;
|
||||
}
|
||||
|
||||
.mx-#{$size} {
|
||||
margin-left: $value !important;
|
||||
margin-right: $value !important;
|
||||
}
|
||||
|
||||
.my-#{$size} {
|
||||
margin-top: $value !important;
|
||||
margin-bottom: $value !important;
|
||||
}
|
||||
}
|
||||
|
||||
// Padding utilities
|
||||
@each $size, $value in (
|
||||
0: 0,
|
||||
xs: $spacing-xs,
|
||||
sm: $spacing-sm,
|
||||
md: $spacing-md,
|
||||
lg: $spacing-lg,
|
||||
xl: $spacing-xl,
|
||||
2xl: $spacing-2xl,
|
||||
3xl: $spacing-3xl,
|
||||
4xl: $spacing-4xl
|
||||
) {
|
||||
.p-#{$size} {
|
||||
padding: $value !important;
|
||||
}
|
||||
|
||||
.pt-#{$size} {
|
||||
padding-top: $value !important;
|
||||
}
|
||||
|
||||
.pb-#{$size} {
|
||||
padding-bottom: $value !important;
|
||||
}
|
||||
|
||||
.pl-#{$size} {
|
||||
padding-left: $value !important;
|
||||
}
|
||||
|
||||
.pr-#{$size} {
|
||||
padding-right: $value !important;
|
||||
}
|
||||
|
||||
.px-#{$size} {
|
||||
padding-left: $value !important;
|
||||
padding-right: $value !important;
|
||||
}
|
||||
|
||||
.py-#{$size} {
|
||||
padding-top: $value !important;
|
||||
padding-bottom: $value !important;
|
||||
}
|
||||
}
|
||||
|
||||
// Width utilities
|
||||
.w-25 {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.w-50 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.w-75 {
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.w-100 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.w-auto {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
// Height utilities
|
||||
.h-25 {
|
||||
height: 25%;
|
||||
}
|
||||
|
||||
.h-50 {
|
||||
height: 50%;
|
||||
}
|
||||
|
||||
.h-75 {
|
||||
height: 75%;
|
||||
}
|
||||
|
||||
.h-100 {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.h-auto {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.vh-100 {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
// Position utilities
|
||||
.position-relative {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.position-absolute {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.position-fixed {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.position-sticky {
|
||||
position: sticky;
|
||||
}
|
||||
|
||||
// Background utilities
|
||||
.bg-primary {
|
||||
background: $primary-blue;
|
||||
}
|
||||
|
||||
.bg-secondary {
|
||||
background: $secondary-blue;
|
||||
}
|
||||
|
||||
.bg-white {
|
||||
background: $white;
|
||||
}
|
||||
|
||||
.bg-gray {
|
||||
background: $gray-bg;
|
||||
}
|
||||
|
||||
.bg-light {
|
||||
background: $light-bg;
|
||||
}
|
||||
|
||||
.bg-gradient-primary {
|
||||
background: $gradient-primary;
|
||||
}
|
||||
|
||||
.bg-gradient-accent {
|
||||
background: $gradient-accent;
|
||||
}
|
||||
|
||||
.bg-gradient-warm {
|
||||
background: $gradient-warm;
|
||||
}
|
||||
|
||||
// Border utilities
|
||||
.border {
|
||||
border: 1px solid $border-gray;
|
||||
}
|
||||
|
||||
.border-0 {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.border-top {
|
||||
border-top: 1px solid $border-gray;
|
||||
}
|
||||
|
||||
.border-bottom {
|
||||
border-bottom: 1px solid $border-gray;
|
||||
}
|
||||
|
||||
.border-left {
|
||||
border-left: 1px solid $border-gray;
|
||||
}
|
||||
|
||||
.border-right {
|
||||
border-right: 1px solid $border-gray;
|
||||
}
|
||||
|
||||
.border-primary {
|
||||
border-color: $primary-blue;
|
||||
}
|
||||
|
||||
// Border radius utilities
|
||||
.rounded-0 {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.rounded-sm {
|
||||
border-radius: $border-radius-sm;
|
||||
}
|
||||
|
||||
.rounded {
|
||||
border-radius: $border-radius-md;
|
||||
}
|
||||
|
||||
.rounded-lg {
|
||||
border-radius: $border-radius-lg;
|
||||
}
|
||||
|
||||
.rounded-xl {
|
||||
border-radius: $border-radius-xl;
|
||||
}
|
||||
|
||||
.rounded-full {
|
||||
border-radius: $border-radius-full;
|
||||
}
|
||||
|
||||
.rounded-circle {
|
||||
border-radius: $border-radius-circle;
|
||||
}
|
||||
|
||||
// Shadow utilities
|
||||
.shadow-none {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.shadow-sm {
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
|
||||
.shadow {
|
||||
box-shadow: $shadow-md;
|
||||
}
|
||||
|
||||
.shadow-lg {
|
||||
box-shadow: $shadow-lg;
|
||||
}
|
||||
|
||||
.shadow-xl {
|
||||
box-shadow: $shadow-xl;
|
||||
}
|
||||
|
||||
// Overflow utilities
|
||||
.overflow-hidden {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.overflow-auto {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.overflow-x-hidden {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.overflow-y-hidden {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.overflow-x-auto {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.overflow-y-auto {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
// Z-index utilities
|
||||
.z-0 {
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.z-10 {
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.z-20 {
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.z-30 {
|
||||
z-index: 30;
|
||||
}
|
||||
|
||||
.z-40 {
|
||||
z-index: 40;
|
||||
}
|
||||
|
||||
.z-50 {
|
||||
z-index: 50;
|
||||
}
|
||||
|
||||
// Responsive utilities
|
||||
@include respond-to('sm') {
|
||||
.sm-hide {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@include respond-to('md') {
|
||||
.md-hide {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-only {
|
||||
@media (min-width: #{$breakpoint-sm + 1px}) {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.desktop-only {
|
||||
@include respond-to('sm') {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
// Cursor utilities
|
||||
.cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cursor-default {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.cursor-not-allowed {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
// Opacity utilities
|
||||
.opacity-0 {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.opacity-25 {
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
.opacity-50 {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.opacity-75 {
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.opacity-100 {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
// Transition utilities
|
||||
.transition {
|
||||
transition: $transition-base;
|
||||
}
|
||||
|
||||
.transition-fast {
|
||||
transition: $transition-fast;
|
||||
}
|
||||
|
||||
.transition-slow {
|
||||
transition: $transition-slow;
|
||||
}
|
||||
|
||||
.transition-none {
|
||||
transition: none;
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Button styles - Modern vibrant design
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Base button
|
||||
.btn {
|
||||
@include button-base;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
// Button sizes
|
||||
&-sm {
|
||||
padding: $spacing-sm $spacing-md;
|
||||
font-size: $font-size-sm;
|
||||
}
|
||||
|
||||
&-md {
|
||||
padding: $spacing-md $spacing-lg;
|
||||
font-size: $font-size-base;
|
||||
}
|
||||
|
||||
&-lg {
|
||||
padding: $spacing-md $spacing-xl;
|
||||
font-size: $font-size-md;
|
||||
}
|
||||
|
||||
&-xl {
|
||||
padding: $spacing-lg $spacing-2xl;
|
||||
font-size: $font-size-lg;
|
||||
}
|
||||
|
||||
// Button variants
|
||||
&-primary {
|
||||
background: $gradient-primary;
|
||||
color: $white;
|
||||
box-shadow: $shadow-md;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: $shadow-xl;
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
}
|
||||
|
||||
&-secondary {
|
||||
background: $white;
|
||||
color: $primary-blue;
|
||||
border: 2px solid $primary-blue;
|
||||
|
||||
&:hover {
|
||||
background: $light-bg;
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
}
|
||||
|
||||
&-accent {
|
||||
background: $gradient-accent;
|
||||
color: $white;
|
||||
box-shadow: $shadow-md;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: $shadow-xl;
|
||||
}
|
||||
}
|
||||
|
||||
&-warm {
|
||||
background: $gradient-warm;
|
||||
color: $white;
|
||||
box-shadow: $shadow-md;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: $shadow-xl;
|
||||
}
|
||||
}
|
||||
|
||||
&-success {
|
||||
background: $accent-green;
|
||||
color: $white;
|
||||
|
||||
&:hover {
|
||||
background: darken($accent-green, 10%);
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
}
|
||||
|
||||
&-danger {
|
||||
background: $accent-orange;
|
||||
color: $white;
|
||||
|
||||
&:hover {
|
||||
background: darken($accent-orange, 10%);
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
}
|
||||
|
||||
&-ghost {
|
||||
background: transparent;
|
||||
color: $primary-blue;
|
||||
border: 2px solid transparent;
|
||||
|
||||
&:hover {
|
||||
background: rgba($primary-blue, 0.1);
|
||||
border-color: $primary-blue;
|
||||
}
|
||||
}
|
||||
|
||||
&-outline {
|
||||
background: transparent;
|
||||
color: $text-dark;
|
||||
border: 2px solid $border-gray;
|
||||
|
||||
&:hover {
|
||||
border-color: $primary-blue;
|
||||
color: $primary-blue;
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
}
|
||||
|
||||
// Button states
|
||||
&:disabled,
|
||||
&.disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&.loading {
|
||||
color: transparent;
|
||||
pointer-events: none;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
@include absolute-center;
|
||||
border: 2px solid $white;
|
||||
border-radius: 50%;
|
||||
border-top-color: transparent;
|
||||
animation: spin 0.6s linear infinite;
|
||||
}
|
||||
}
|
||||
|
||||
// Button with icon
|
||||
&-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
padding: 0;
|
||||
border-radius: $border-radius-circle;
|
||||
|
||||
&.btn-sm {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
&.btn-lg {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
}
|
||||
}
|
||||
|
||||
// Full width button
|
||||
&-block {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
// Button group
|
||||
&-group {
|
||||
display: inline-flex;
|
||||
gap: -1px;
|
||||
|
||||
.btn {
|
||||
border-radius: 0;
|
||||
|
||||
&:first-child {
|
||||
border-top-left-radius: $border-radius-lg;
|
||||
border-bottom-left-radius: $border-radius-lg;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-top-right-radius: $border-radius-lg;
|
||||
border-bottom-right-radius: $border-radius-lg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Floating action button
|
||||
.fab {
|
||||
position: fixed;
|
||||
bottom: $spacing-xl;
|
||||
right: $spacing-xl;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: $gradient-primary;
|
||||
border: none;
|
||||
border-radius: $border-radius-circle;
|
||||
color: $white;
|
||||
font-size: $font-size-xl;
|
||||
cursor: pointer;
|
||||
box-shadow: $shadow-lg;
|
||||
transition: $transition-base;
|
||||
z-index: $z-index-fixed;
|
||||
@include flex-center;
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.1);
|
||||
box-shadow: $shadow-xl;
|
||||
|
||||
.fab-label {
|
||||
opacity: 1;
|
||||
transform: translateX(-10px);
|
||||
}
|
||||
}
|
||||
|
||||
.fab-label {
|
||||
position: absolute;
|
||||
right: 70px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: $text-dark;
|
||||
color: $white;
|
||||
padding: $spacing-sm $spacing-md;
|
||||
border-radius: $border-radius-md;
|
||||
font-size: $font-size-sm;
|
||||
white-space: nowrap;
|
||||
opacity: 0;
|
||||
transition: $transition-base;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
// CTA buttons
|
||||
.btn-cta {
|
||||
&-primary {
|
||||
@include button-base;
|
||||
background: $white;
|
||||
color: $primary-blue;
|
||||
padding: $spacing-md $spacing-2xl;
|
||||
font-size: $font-size-md;
|
||||
box-shadow: $shadow-lg;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: $shadow-xl;
|
||||
}
|
||||
}
|
||||
|
||||
&-secondary {
|
||||
@include button-base;
|
||||
background: transparent;
|
||||
color: $white;
|
||||
border: 2px solid $white;
|
||||
padding: $spacing-md $spacing-2xl;
|
||||
font-size: $font-size-md;
|
||||
|
||||
&:hover {
|
||||
background: rgba($white, 0.1);
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,386 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Card styles - Modern vibrant design
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Base card
|
||||
.card {
|
||||
@include card;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
// Card hover effect
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
left: -50%;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
background: linear-gradient(
|
||||
45deg,
|
||||
transparent 30%,
|
||||
rgba($primary-blue, 0.03) 50%,
|
||||
transparent 70%
|
||||
);
|
||||
transform: rotate(45deg);
|
||||
transition: $transition-slow;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&:hover::before {
|
||||
animation: shimmer 0.6s ease;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
// API showcase cards
|
||||
.api-card {
|
||||
@include card;
|
||||
text-align: center;
|
||||
border: 2px solid $border-gray;
|
||||
|
||||
&:hover {
|
||||
border-color: $primary-blue;
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
|
||||
// Popular variant
|
||||
&-popular {
|
||||
border-color: $accent-yellow;
|
||||
background: linear-gradient(180deg, rgba($accent-yellow, 0.05) 0%, $white 100%);
|
||||
}
|
||||
|
||||
// New variant
|
||||
&-new {
|
||||
border-color: $accent-green;
|
||||
background: linear-gradient(180deg, rgba($accent-green, 0.05) 0%, $white 100%);
|
||||
}
|
||||
|
||||
// API badge
|
||||
.api-badge {
|
||||
position: absolute;
|
||||
top: -12px;
|
||||
right: 20px;
|
||||
padding: $spacing-xs $spacing-md;
|
||||
background: $accent-yellow;
|
||||
color: $text-dark;
|
||||
border-radius: $border-radius-2xl;
|
||||
font-size: $font-size-xs;
|
||||
font-weight: $font-weight-bold;
|
||||
text-transform: uppercase;
|
||||
|
||||
&.new {
|
||||
background: $accent-green;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
&.beta {
|
||||
background: $accent-purple;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
|
||||
// API icon
|
||||
.api-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin: 0 auto $spacing-lg;
|
||||
@include flex-center;
|
||||
font-size: 28px;
|
||||
background: $light-bg;
|
||||
color: $primary-blue;
|
||||
border-radius: $border-radius-xl;
|
||||
transition: $transition-base;
|
||||
}
|
||||
|
||||
&:hover .api-icon {
|
||||
transform: scale(1.1);
|
||||
background: $gradient-primary;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
// API content
|
||||
.api-name {
|
||||
font-size: $font-size-lg;
|
||||
font-weight: $font-weight-bold;
|
||||
margin-bottom: $spacing-md;
|
||||
color: $text-dark;
|
||||
}
|
||||
|
||||
.api-description {
|
||||
color: $text-gray;
|
||||
line-height: $line-height-normal;
|
||||
margin-bottom: $spacing-lg;
|
||||
font-size: $font-size-sm;
|
||||
}
|
||||
|
||||
// API features
|
||||
.api-features {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: $spacing-sm;
|
||||
margin-bottom: $spacing-lg;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.feature-tag {
|
||||
padding: $spacing-xs $spacing-sm;
|
||||
background: $gray-bg;
|
||||
color: $text-gray;
|
||||
border-radius: $border-radius-2xl;
|
||||
font-size: $font-size-xs;
|
||||
font-weight: $font-weight-medium;
|
||||
}
|
||||
}
|
||||
|
||||
// API link
|
||||
.api-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: $spacing-xs;
|
||||
color: $primary-blue;
|
||||
font-weight: $font-weight-semibold;
|
||||
font-size: $font-size-sm;
|
||||
transition: $transition-base;
|
||||
|
||||
&:hover {
|
||||
gap: $spacing-sm;
|
||||
color: $secondary-blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Experience cards
|
||||
.experience-card {
|
||||
@include card;
|
||||
text-align: center;
|
||||
|
||||
.card-icon {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
margin: 0 auto $spacing-lg;
|
||||
@include flex-center;
|
||||
font-size: $font-size-xl;
|
||||
background: $gradient-primary;
|
||||
color: $white;
|
||||
border-radius: $border-radius-xl;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: $font-size-lg;
|
||||
font-weight: $font-weight-bold;
|
||||
margin-bottom: $spacing-md;
|
||||
color: $text-dark;
|
||||
}
|
||||
|
||||
p {
|
||||
color: $text-gray;
|
||||
line-height: $line-height-normal;
|
||||
margin-bottom: $spacing-lg;
|
||||
font-size: $font-size-sm;
|
||||
}
|
||||
|
||||
// Card metric
|
||||
.card-metric {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-top: $spacing-lg;
|
||||
border-top: 1px solid $border-gray;
|
||||
|
||||
.metric-value {
|
||||
font-size: $font-size-xl;
|
||||
font-weight: $font-weight-extrabold;
|
||||
color: $primary-blue;
|
||||
}
|
||||
|
||||
.metric-label {
|
||||
font-size: $font-size-xs;
|
||||
color: $text-gray;
|
||||
font-weight: $font-weight-medium;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Feature cards
|
||||
.feature-card {
|
||||
@include card;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: $spacing-lg;
|
||||
|
||||
.feature-icon {
|
||||
flex-shrink: 0;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
@include flex-center;
|
||||
background: $gradient-primary;
|
||||
color: $white;
|
||||
border-radius: $border-radius-lg;
|
||||
font-size: $font-size-xl;
|
||||
}
|
||||
|
||||
.feature-content {
|
||||
flex: 1;
|
||||
|
||||
h4 {
|
||||
font-size: $font-size-md;
|
||||
font-weight: $font-weight-semibold;
|
||||
margin-bottom: $spacing-sm;
|
||||
color: $text-dark;
|
||||
}
|
||||
|
||||
p {
|
||||
color: $text-gray;
|
||||
line-height: $line-height-normal;
|
||||
font-size: $font-size-sm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Testimonial cards
|
||||
.testimonial-card {
|
||||
@include card;
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: '"';
|
||||
position: absolute;
|
||||
top: $spacing-md;
|
||||
left: $spacing-md;
|
||||
font-size: 60px;
|
||||
color: $primary-blue;
|
||||
opacity: 0.1;
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
|
||||
.testimonial-content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
font-size: $font-size-base;
|
||||
line-height: $line-height-loose;
|
||||
color: $text-dark;
|
||||
margin-bottom: $spacing-lg;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.testimonial-author {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $spacing-md;
|
||||
|
||||
.author-avatar {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: $border-radius-circle;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.author-info {
|
||||
.author-name {
|
||||
font-weight: $font-weight-semibold;
|
||||
color: $text-dark;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.author-title {
|
||||
font-size: $font-size-sm;
|
||||
color: $text-gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pricing cards
|
||||
.pricing-card {
|
||||
@include card;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
|
||||
&.featured {
|
||||
border: 2px solid $primary-blue;
|
||||
transform: scale(1.05);
|
||||
|
||||
.pricing-badge {
|
||||
position: absolute;
|
||||
top: -14px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
padding: $spacing-xs $spacing-md;
|
||||
background: $gradient-primary;
|
||||
color: $white;
|
||||
border-radius: $border-radius-full;
|
||||
font-size: $font-size-xs;
|
||||
font-weight: $font-weight-bold;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
|
||||
.pricing-header {
|
||||
padding-bottom: $spacing-lg;
|
||||
border-bottom: 1px solid $border-gray;
|
||||
margin-bottom: $spacing-lg;
|
||||
|
||||
h3 {
|
||||
font-size: $font-size-xl;
|
||||
font-weight: $font-weight-bold;
|
||||
margin-bottom: $spacing-sm;
|
||||
color: $text-dark;
|
||||
}
|
||||
|
||||
.price {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: center;
|
||||
gap: $spacing-xs;
|
||||
|
||||
.currency {
|
||||
font-size: $font-size-lg;
|
||||
color: $text-gray;
|
||||
}
|
||||
|
||||
.amount {
|
||||
font-size: $font-size-4xl;
|
||||
font-weight: $font-weight-extrabold;
|
||||
@include gradient-text($gradient-primary);
|
||||
}
|
||||
|
||||
.period {
|
||||
font-size: $font-size-base;
|
||||
color: $text-gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pricing-features {
|
||||
list-style: none;
|
||||
margin-bottom: $spacing-lg;
|
||||
|
||||
li {
|
||||
padding: $spacing-sm 0;
|
||||
color: $text-gray;
|
||||
font-size: $font-size-sm;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $spacing-sm;
|
||||
|
||||
&::before {
|
||||
content: '✓';
|
||||
color: $accent-green;
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
opacity: 0.5;
|
||||
|
||||
&::before {
|
||||
content: '×';
|
||||
color: $text-light;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pricing-cta {
|
||||
margin-top: auto;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// CTA (Call to Action) section styles
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
.final-cta {
|
||||
position: relative;
|
||||
padding: $spacing-6xl * 1.5 0;
|
||||
background: $gradient-primary;
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Form styles
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Form group
|
||||
.form-group {
|
||||
margin-bottom: $spacing-lg;
|
||||
|
||||
label {
|
||||
display: block;
|
||||
font-size: $font-size-sm;
|
||||
font-weight: $font-weight-medium;
|
||||
color: $text-dark;
|
||||
margin-bottom: $spacing-sm;
|
||||
|
||||
.required {
|
||||
color: $accent-orange;
|
||||
margin-left: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.form-hint {
|
||||
font-size: $font-size-xs;
|
||||
color: $text-gray;
|
||||
margin-top: $spacing-xs;
|
||||
}
|
||||
|
||||
.form-error {
|
||||
font-size: $font-size-xs;
|
||||
color: $accent-orange;
|
||||
margin-top: $spacing-xs;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $spacing-xs;
|
||||
}
|
||||
}
|
||||
|
||||
// Form control base
|
||||
.form-control {
|
||||
width: 100%;
|
||||
padding: $input-padding-y $input-padding-x;
|
||||
font-size: $font-size-base;
|
||||
font-family: $font-family-primary;
|
||||
color: $text-dark;
|
||||
background: $white;
|
||||
border: 2px solid $border-gray;
|
||||
border-radius: $border-radius-md;
|
||||
transition: $transition-base;
|
||||
|
||||
&::placeholder {
|
||||
color: $text-light;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: $primary-blue;
|
||||
box-shadow: 0 0 0 3px rgba($primary-blue, 0.1);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background: $gray-bg;
|
||||
color: $text-gray;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
// Size variations
|
||||
&-sm {
|
||||
padding: $spacing-sm $spacing-md;
|
||||
font-size: $font-size-sm;
|
||||
}
|
||||
|
||||
&-lg {
|
||||
padding: $spacing-md $spacing-lg;
|
||||
font-size: $font-size-md;
|
||||
}
|
||||
|
||||
// State variations
|
||||
&.is-valid {
|
||||
border-color: $accent-green;
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 3px rgba($accent-green, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
&.is-invalid {
|
||||
border-color: $accent-orange;
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 3px rgba($accent-orange, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Textarea
|
||||
textarea.form-control {
|
||||
min-height: 120px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
// Select
|
||||
select.form-control {
|
||||
appearance: none;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M6 8L0 0h12z' fill='%2364748B'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
background-position: right $spacing-md center;
|
||||
background-size: 12px;
|
||||
padding-right: $spacing-2xl;
|
||||
}
|
||||
|
||||
// Checkbox and Radio
|
||||
.form-check {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: $spacing-md;
|
||||
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: $spacing-sm;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
label {
|
||||
margin-bottom: 0;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
|
||||
input,
|
||||
label {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Switch toggle
|
||||
.form-switch {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $spacing-md;
|
||||
|
||||
.switch {
|
||||
position: relative;
|
||||
width: 48px;
|
||||
height: 24px;
|
||||
background: $border-gray;
|
||||
border-radius: $border-radius-full;
|
||||
cursor: pointer;
|
||||
transition: $transition-base;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: $white;
|
||||
border-radius: $border-radius-circle;
|
||||
transition: $transition-base;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: $primary-blue;
|
||||
|
||||
&::after {
|
||||
transform: translateX(24px);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Input group
|
||||
.input-group {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
.input-group-text {
|
||||
padding: $input-padding-y $input-padding-x;
|
||||
font-size: $font-size-base;
|
||||
color: $text-gray;
|
||||
background: $gray-bg;
|
||||
border: 2px solid $border-gray;
|
||||
border-radius: $border-radius-md 0 0 $border-radius-md;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
border-radius: 0 $border-radius-md $border-radius-md 0;
|
||||
}
|
||||
|
||||
&.input-group-append {
|
||||
.input-group-text {
|
||||
border-radius: 0 $border-radius-md $border-radius-md 0;
|
||||
border-right: 2px solid $border-gray;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
border-radius: $border-radius-md 0 0 $border-radius-md;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Form inline
|
||||
.form-inline {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
gap: $spacing-md;
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
|
||||
.form-group {
|
||||
margin-bottom: $spacing-md;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Form row
|
||||
.form-row {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: $spacing-lg;
|
||||
|
||||
@include respond-to('sm') {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Modal styles
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Modal backdrop
|
||||
.modal-backdrop {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: $z-index-modal-backdrop;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: $transition-base;
|
||||
|
||||
&.show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
// Modal wrapper
|
||||
.modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: $z-index-modal;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: $spacing-lg;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: $transition-base;
|
||||
|
||||
&.show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
|
||||
.modal-dialog {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Modal dialog
|
||||
.modal-dialog {
|
||||
position: relative;
|
||||
background: $white;
|
||||
border-radius: $border-radius-xl;
|
||||
box-shadow: $shadow-xl;
|
||||
max-width: 500px;
|
||||
width: 100%;
|
||||
max-height: 90vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transform: scale(0.95);
|
||||
transition: $transition-base;
|
||||
|
||||
// Size variations
|
||||
&.modal-sm {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
&.modal-lg {
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
&.modal-xl {
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
&.modal-fullscreen {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Modal header
|
||||
.modal-header {
|
||||
padding: $spacing-lg;
|
||||
border-bottom: 1px solid $border-gray;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.modal-title {
|
||||
font-size: $font-size-xl;
|
||||
font-weight: $font-weight-semibold;
|
||||
color: $text-dark;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
@include flex-center;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: $border-radius-md;
|
||||
color: $text-gray;
|
||||
font-size: $font-size-xl;
|
||||
cursor: pointer;
|
||||
transition: $transition-base;
|
||||
|
||||
&:hover {
|
||||
background: $gray-bg;
|
||||
color: $text-dark;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Modal body
|
||||
.modal-body {
|
||||
padding: $spacing-lg;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
color: $text-dark;
|
||||
line-height: $line-height-normal;
|
||||
}
|
||||
|
||||
// Modal footer
|
||||
.modal-footer {
|
||||
padding: $spacing-lg;
|
||||
border-top: 1px solid $border-gray;
|
||||
display: flex;
|
||||
gap: $spacing-md;
|
||||
justify-content: flex-end;
|
||||
|
||||
&.modal-footer-center {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&.modal-footer-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
// Alert modal
|
||||
.modal-alert {
|
||||
.modal-dialog {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
text-align: center;
|
||||
padding: $spacing-xl;
|
||||
|
||||
.alert-icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
margin: 0 auto $spacing-lg;
|
||||
@include flex-center;
|
||||
font-size: $font-size-2xl;
|
||||
border-radius: $border-radius-circle;
|
||||
|
||||
&.alert-success {
|
||||
background: rgba($accent-green, 0.1);
|
||||
color: $accent-green;
|
||||
}
|
||||
|
||||
&.alert-warning {
|
||||
background: rgba($accent-yellow, 0.1);
|
||||
color: $accent-yellow;
|
||||
}
|
||||
|
||||
&.alert-danger {
|
||||
background: rgba($accent-orange, 0.1);
|
||||
color: $accent-orange;
|
||||
}
|
||||
|
||||
&.alert-info {
|
||||
background: rgba($primary-blue, 0.1);
|
||||
color: $primary-blue;
|
||||
}
|
||||
}
|
||||
|
||||
.alert-title {
|
||||
font-size: $font-size-xl;
|
||||
font-weight: $font-weight-semibold;
|
||||
margin-bottom: $spacing-sm;
|
||||
color: $text-dark;
|
||||
}
|
||||
|
||||
.alert-message {
|
||||
color: $text-gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Navigation component styles
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Breadcrumb navigation
|
||||
.breadcrumb {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $spacing-sm;
|
||||
padding: $spacing-md 0;
|
||||
font-size: $font-size-sm;
|
||||
|
||||
.breadcrumb-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $spacing-sm;
|
||||
color: $text-gray;
|
||||
|
||||
a {
|
||||
color: $text-gray;
|
||||
transition: $transition-base;
|
||||
|
||||
&:hover {
|
||||
color: $primary-blue;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: $text-dark;
|
||||
font-weight: $font-weight-medium;
|
||||
}
|
||||
|
||||
&:not(:last-child)::after {
|
||||
content: '/';
|
||||
color: $text-light;
|
||||
margin-left: $spacing-sm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tab navigation
|
||||
.nav-tabs {
|
||||
display: flex;
|
||||
gap: $spacing-xs;
|
||||
border-bottom: 2px solid $border-gray;
|
||||
margin-bottom: $spacing-xl;
|
||||
|
||||
.nav-item {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $spacing-sm;
|
||||
padding: $spacing-md $spacing-lg;
|
||||
color: $text-gray;
|
||||
font-weight: $font-weight-medium;
|
||||
border-bottom: 2px solid transparent;
|
||||
margin-bottom: -2px;
|
||||
transition: $transition-base;
|
||||
|
||||
&:hover {
|
||||
color: $text-dark;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: $primary-blue;
|
||||
border-bottom-color: $primary-blue;
|
||||
}
|
||||
|
||||
.badge {
|
||||
padding: 2px 6px;
|
||||
background: $gray-bg;
|
||||
color: $text-gray;
|
||||
border-radius: $border-radius-full;
|
||||
font-size: 11px;
|
||||
font-weight: $font-weight-semibold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pills navigation
|
||||
.nav-pills {
|
||||
display: flex;
|
||||
gap: $spacing-sm;
|
||||
padding: $spacing-xs;
|
||||
background: $gray-bg;
|
||||
border-radius: $border-radius-lg;
|
||||
|
||||
.nav-link {
|
||||
padding: $spacing-sm $spacing-lg;
|
||||
color: $text-gray;
|
||||
font-weight: $font-weight-medium;
|
||||
border-radius: $border-radius-md;
|
||||
transition: $transition-base;
|
||||
|
||||
&:hover {
|
||||
color: $text-dark;
|
||||
background: rgba($white, 0.5);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: $white;
|
||||
color: $primary-blue;
|
||||
box-shadow: $shadow-sm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sidebar navigation
|
||||
.sidebar-nav {
|
||||
.nav-section {
|
||||
margin-bottom: $spacing-xl;
|
||||
|
||||
.nav-title {
|
||||
font-size: $font-size-xs;
|
||||
font-weight: $font-weight-semibold;
|
||||
text-transform: uppercase;
|
||||
color: $text-gray;
|
||||
padding: $spacing-sm $spacing-md;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-menu {
|
||||
list-style: none;
|
||||
|
||||
.nav-item {
|
||||
margin-bottom: $spacing-xs;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $spacing-md;
|
||||
padding: $spacing-sm $spacing-md;
|
||||
color: $text-dark;
|
||||
border-radius: $border-radius-md;
|
||||
transition: $transition-base;
|
||||
|
||||
.nav-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
@include flex-center;
|
||||
font-size: $font-size-md;
|
||||
color: $text-gray;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: $gray-bg;
|
||||
color: $primary-blue;
|
||||
|
||||
.nav-icon {
|
||||
color: $primary-blue;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: $light-bg;
|
||||
color: $primary-blue;
|
||||
font-weight: $font-weight-medium;
|
||||
|
||||
.nav-icon {
|
||||
color: $primary-blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Nested menu
|
||||
.nav-submenu {
|
||||
margin-left: $spacing-2xl;
|
||||
margin-top: $spacing-xs;
|
||||
list-style: none;
|
||||
|
||||
.nav-link {
|
||||
font-size: $font-size-sm;
|
||||
padding: $spacing-xs $spacing-md;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pagination
|
||||
.pagination {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $spacing-xs;
|
||||
|
||||
.page-item {
|
||||
&.disabled {
|
||||
.page-link {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
.page-link {
|
||||
background: $primary-blue;
|
||||
color: $white;
|
||||
border-color: $primary-blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.page-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 36px;
|
||||
height: 36px;
|
||||
padding: 0 $spacing-sm;
|
||||
background: $white;
|
||||
border: 1px solid $border-gray;
|
||||
border-radius: $border-radius-md;
|
||||
color: $text-dark;
|
||||
font-size: $font-size-sm;
|
||||
font-weight: $font-weight-medium;
|
||||
transition: $transition-base;
|
||||
|
||||
&:hover {
|
||||
background: $gray-bg;
|
||||
border-color: $primary-blue;
|
||||
color: $primary-blue;
|
||||
}
|
||||
|
||||
&.page-prev,
|
||||
&.page-next {
|
||||
font-size: $font-size-md;
|
||||
}
|
||||
}
|
||||
|
||||
.page-dots {
|
||||
padding: 0 $spacing-sm;
|
||||
color: $text-gray;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Partners section styles
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
.partners {
|
||||
padding: $spacing-5xl 0;
|
||||
background: $white;
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Container and section styles
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Main container
|
||||
.container {
|
||||
max-width: $container-max-width;
|
||||
margin: 0 auto;
|
||||
padding: 0 $spacing-lg;
|
||||
|
||||
@include respond-to('sm') {
|
||||
padding: 0 $spacing-md;
|
||||
}
|
||||
|
||||
// Container variations
|
||||
&-fluid {
|
||||
max-width: 100%;
|
||||
padding: 0 $spacing-lg;
|
||||
}
|
||||
|
||||
&-narrow {
|
||||
max-width: 960px;
|
||||
}
|
||||
|
||||
&-wide {
|
||||
max-width: 1440px;
|
||||
}
|
||||
}
|
||||
|
||||
// Section spacing
|
||||
.section {
|
||||
padding: $spacing-6xl 0;
|
||||
|
||||
@include respond-to('sm') {
|
||||
padding: $spacing-4xl 0;
|
||||
}
|
||||
|
||||
// Section variations
|
||||
&-sm {
|
||||
padding: $spacing-3xl 0;
|
||||
}
|
||||
|
||||
&-lg {
|
||||
padding: $spacing-6xl * 1.5 0;
|
||||
}
|
||||
|
||||
&-no-top {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
&-no-bottom {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Section backgrounds
|
||||
.section-bg {
|
||||
&-gray {
|
||||
background: $gray-bg;
|
||||
}
|
||||
|
||||
&-light {
|
||||
background: $light-bg;
|
||||
}
|
||||
|
||||
&-gradient {
|
||||
background: linear-gradient(180deg, $white 0%, $light-bg 100%);
|
||||
}
|
||||
|
||||
&-gradient-reverse {
|
||||
background: linear-gradient(180deg, $light-bg 0%, $white 100%);
|
||||
}
|
||||
|
||||
&-primary {
|
||||
background: $gradient-primary;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
&-dark {
|
||||
background: $text-dark;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
|
||||
// Section header
|
||||
.section-header {
|
||||
text-align: center;
|
||||
margin-bottom: $spacing-4xl;
|
||||
|
||||
@include respond-to('sm') {
|
||||
margin-bottom: $spacing-3xl;
|
||||
}
|
||||
|
||||
.section-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: $spacing-xs;
|
||||
padding: $spacing-xs $spacing-md;
|
||||
background: $light-bg;
|
||||
color: $primary-blue;
|
||||
border-radius: $border-radius-full;
|
||||
font-size: $font-size-sm;
|
||||
font-weight: $font-weight-semibold;
|
||||
margin-bottom: $spacing-md;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: $font-size-3xl;
|
||||
font-weight: $font-weight-bold;
|
||||
margin-bottom: $spacing-md;
|
||||
color: $text-dark;
|
||||
|
||||
@include respond-to('sm') {
|
||||
font-size: $font-size-2xl;
|
||||
}
|
||||
|
||||
.title-highlight {
|
||||
@include gradient-text($gradient-accent);
|
||||
}
|
||||
}
|
||||
|
||||
.section-subtitle {
|
||||
font-size: $font-size-md;
|
||||
color: $text-gray;
|
||||
line-height: $line-height-normal;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
|
||||
@include respond-to('sm') {
|
||||
font-size: $font-size-base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Content wrapper
|
||||
.content-wrapper {
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.main-content {
|
||||
flex: 1;
|
||||
padding-top: $header-height;
|
||||
}
|
||||
}
|
||||
|
||||
// Page wrapper
|
||||
.page-wrapper {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// Inner content
|
||||
.inner-content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Footer styles - Modern vibrant design
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
.global-footer {
|
||||
background: $text-dark;
|
||||
color: $white;
|
||||
padding: $spacing-5xl 0 $spacing-2xl;
|
||||
|
||||
@include respond-to('sm') {
|
||||
padding: $spacing-3xl 0 $spacing-xl;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-top {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 3fr;
|
||||
gap: $spacing-5xl;
|
||||
margin-bottom: $spacing-4xl;
|
||||
max-width: $container-max-width;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 0 $spacing-lg;
|
||||
|
||||
@include respond-to('md') {
|
||||
grid-template-columns: 1fr;
|
||||
gap: $spacing-2xl;
|
||||
}
|
||||
}
|
||||
|
||||
// Footer brand section
|
||||
.footer-brand {
|
||||
max-width: 360px;
|
||||
|
||||
.footer-logo {
|
||||
height: 48px;
|
||||
margin-bottom: $spacing-lg;
|
||||
}
|
||||
|
||||
.footer-desc {
|
||||
font-size: $font-size-sm;
|
||||
line-height: $line-height-loose;
|
||||
color: rgba($white, 0.7);
|
||||
margin-bottom: $spacing-lg;
|
||||
}
|
||||
|
||||
.footer-newsletter {
|
||||
margin-bottom: $spacing-xl;
|
||||
|
||||
h4 {
|
||||
font-size: $font-size-md;
|
||||
font-weight: $font-weight-semibold;
|
||||
margin-bottom: $spacing-md;
|
||||
}
|
||||
|
||||
.newsletter-form {
|
||||
display: flex;
|
||||
gap: $spacing-sm;
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
padding: $spacing-sm $spacing-md;
|
||||
background: rgba($white, 0.1);
|
||||
border: 1px solid rgba($white, 0.2);
|
||||
border-radius: $border-radius-md;
|
||||
color: $white;
|
||||
font-size: $font-size-sm;
|
||||
|
||||
&::placeholder {
|
||||
color: rgba($white, 0.5);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
background: rgba($white, 0.15);
|
||||
border-color: $primary-blue;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
padding: $spacing-sm $spacing-lg;
|
||||
background: $gradient-primary;
|
||||
color: $white;
|
||||
border-radius: $border-radius-md;
|
||||
font-weight: $font-weight-semibold;
|
||||
font-size: $font-size-sm;
|
||||
transition: $transition-base;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: $shadow-md;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Social links
|
||||
.social-links {
|
||||
display: flex;
|
||||
gap: $spacing-md;
|
||||
|
||||
a {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
background: rgba($white, 0.1);
|
||||
border-radius: $border-radius-lg;
|
||||
@include flex-center;
|
||||
color: $white;
|
||||
transition: $transition-base;
|
||||
font-size: $font-size-lg;
|
||||
|
||||
&:hover {
|
||||
background: $primary-blue;
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
|
||||
&.facebook:hover {
|
||||
background: #1877f2;
|
||||
}
|
||||
|
||||
&.twitter:hover {
|
||||
background: #1da1f2;
|
||||
}
|
||||
|
||||
&.linkedin:hover {
|
||||
background: #0077b5;
|
||||
}
|
||||
|
||||
&.github:hover {
|
||||
background: #333;
|
||||
}
|
||||
|
||||
&.youtube:hover {
|
||||
background: #ff0000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Footer links
|
||||
.footer-links {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: $spacing-2xl;
|
||||
|
||||
@include respond-to('md') {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
grid-template-columns: 1fr;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-column {
|
||||
h4 {
|
||||
font-size: $font-size-base;
|
||||
font-weight: $font-weight-bold;
|
||||
margin-bottom: $spacing-lg;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
|
||||
li {
|
||||
margin-bottom: $spacing-md;
|
||||
|
||||
a {
|
||||
color: rgba($white, 0.7);
|
||||
font-size: $font-size-sm;
|
||||
transition: $transition-base;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -2px;
|
||||
left: 0;
|
||||
width: 0;
|
||||
height: 1px;
|
||||
background: $accent-cyan;
|
||||
transition: $transition-base;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: $accent-cyan;
|
||||
|
||||
&::after {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Special badges
|
||||
.footer-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: $spacing-xs;
|
||||
padding: $spacing-xs $spacing-sm;
|
||||
background: rgba($accent-green, 0.2);
|
||||
color: $accent-green;
|
||||
border-radius: $border-radius-full;
|
||||
font-size: $font-size-xs;
|
||||
font-weight: $font-weight-semibold;
|
||||
margin-left: $spacing-sm;
|
||||
}
|
||||
}
|
||||
|
||||
// Footer bottom
|
||||
.footer-bottom {
|
||||
padding-top: $spacing-2xl;
|
||||
border-top: 1px solid rgba($white, 0.1);
|
||||
max-width: $container-max-width;
|
||||
margin: 0 auto;
|
||||
padding-left: $spacing-lg;
|
||||
padding-right: $spacing-lg;
|
||||
}
|
||||
|
||||
.footer-legal {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
@include respond-to('sm') {
|
||||
flex-direction: column;
|
||||
gap: $spacing-lg;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
p {
|
||||
color: rgba($white, 0.5);
|
||||
font-size: $font-size-sm;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.legal-links {
|
||||
display: flex;
|
||||
gap: $spacing-lg;
|
||||
|
||||
a {
|
||||
color: rgba($white, 0.7);
|
||||
font-size: $font-size-sm;
|
||||
transition: $transition-base;
|
||||
|
||||
&:hover {
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Footer decoration
|
||||
.footer-decoration {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -100px;
|
||||
right: -100px;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
background: radial-gradient(circle, rgba($primary-blue, 0.1) 0%, transparent 70%);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -150px;
|
||||
left: -150px;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
background: radial-gradient(circle, rgba($accent-cyan, 0.05) 0%, transparent 70%);
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,298 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Grid system - Modern responsive layout
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Grid container
|
||||
.grid {
|
||||
display: grid;
|
||||
gap: $spacing-lg;
|
||||
|
||||
// Column templates
|
||||
&-cols-1 {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
&-cols-2 {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
&-cols-3 {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
|
||||
&-cols-4 {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
|
||||
&-cols-5 {
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
}
|
||||
|
||||
&-cols-6 {
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
}
|
||||
|
||||
&-cols-12 {
|
||||
grid-template-columns: repeat(12, 1fr);
|
||||
}
|
||||
|
||||
// Auto-fit grid
|
||||
&-auto {
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
}
|
||||
|
||||
&-auto-sm {
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
}
|
||||
|
||||
&-auto-lg {
|
||||
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
||||
}
|
||||
|
||||
// Gap variations
|
||||
&.gap-0 {
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
&.gap-sm {
|
||||
gap: $spacing-sm;
|
||||
}
|
||||
|
||||
&.gap-md {
|
||||
gap: $spacing-md;
|
||||
}
|
||||
|
||||
&.gap-lg {
|
||||
gap: $spacing-lg;
|
||||
}
|
||||
|
||||
&.gap-xl {
|
||||
gap: $spacing-xl;
|
||||
}
|
||||
|
||||
// Responsive grids
|
||||
@include respond-to('md') {
|
||||
&-md-cols-1 {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
&-md-cols-2 {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
&-sm-cols-1 {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
&-sm-cols-2 {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Grid item spans
|
||||
.col-span-1 {
|
||||
grid-column: span 1;
|
||||
}
|
||||
|
||||
.col-span-2 {
|
||||
grid-column: span 2;
|
||||
}
|
||||
|
||||
.col-span-3 {
|
||||
grid-column: span 3;
|
||||
}
|
||||
|
||||
.col-span-4 {
|
||||
grid-column: span 4;
|
||||
}
|
||||
|
||||
.col-span-5 {
|
||||
grid-column: span 5;
|
||||
}
|
||||
|
||||
.col-span-6 {
|
||||
grid-column: span 6;
|
||||
}
|
||||
|
||||
.col-span-full {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.row-span-1 {
|
||||
grid-row: span 1;
|
||||
}
|
||||
|
||||
.row-span-2 {
|
||||
grid-row: span 2;
|
||||
}
|
||||
|
||||
.row-span-3 {
|
||||
grid-row: span 3;
|
||||
}
|
||||
|
||||
// API Grid
|
||||
.api-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: $spacing-lg;
|
||||
|
||||
@include respond-to('md') {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
// Experience Grid
|
||||
.experience-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: $spacing-lg;
|
||||
|
||||
@include respond-to('sm') {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
// Partners Grid
|
||||
.partners-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: $spacing-2xl;
|
||||
align-items: center;
|
||||
|
||||
@include respond-to('sm') {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
// Feature Grid
|
||||
.feature-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: $spacing-xl;
|
||||
|
||||
@include respond-to('sm') {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
// Demo Grid
|
||||
.demo-wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: $spacing-2xl;
|
||||
align-items: start;
|
||||
|
||||
@include respond-to('md') {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
// Footer Grid
|
||||
.footer-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 3fr;
|
||||
gap: $spacing-5xl;
|
||||
|
||||
@include respond-to('md') {
|
||||
grid-template-columns: 1fr;
|
||||
gap: $spacing-2xl;
|
||||
}
|
||||
|
||||
.footer-links {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: $spacing-2xl;
|
||||
|
||||
@include respond-to('md') {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
grid-template-columns: 1fr;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pricing Grid
|
||||
.pricing-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: $spacing-lg;
|
||||
align-items: center;
|
||||
|
||||
@include respond-to('md') {
|
||||
grid-template-columns: 1fr;
|
||||
gap: $spacing-xl;
|
||||
}
|
||||
}
|
||||
|
||||
// Testimonial Grid
|
||||
.testimonial-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
||||
gap: $spacing-lg;
|
||||
|
||||
@include respond-to('sm') {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
// Stats Grid
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: $spacing-xl;
|
||||
text-align: center;
|
||||
|
||||
@include respond-to('md') {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
@include respond-to('sm') {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
// Two Column Layout
|
||||
.two-column {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: $spacing-3xl;
|
||||
align-items: center;
|
||||
|
||||
@include respond-to('md') {
|
||||
grid-template-columns: 1fr;
|
||||
gap: $spacing-xl;
|
||||
}
|
||||
|
||||
&.reverse {
|
||||
direction: rtl;
|
||||
|
||||
> * {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
@include respond-to('md') {
|
||||
direction: ltr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Three Column Layout
|
||||
.three-column {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: $spacing-xl;
|
||||
|
||||
@include respond-to('md') {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,805 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Header styles - Modern & Responsive Design
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// CSS Variables for modern header styling
|
||||
:root {
|
||||
// Enhanced color palette from design
|
||||
--primary-blue: #4B9BFF;
|
||||
--secondary-blue: #2E7FF7;
|
||||
--accent-cyan: #00D4FF;
|
||||
--accent-yellow: #FFD93D;
|
||||
--accent-orange: #FF6B6B;
|
||||
--accent-green: #6BCF7F;
|
||||
--accent-purple: #A78BFA;
|
||||
|
||||
// Base colors
|
||||
--text-dark: #1A1A2E;
|
||||
--text-gray: #64748B;
|
||||
--text-light: #94A3B8;
|
||||
--white: #FFFFFF;
|
||||
--gray-bg: #F8FAFC;
|
||||
--light-bg: #EFF6FF;
|
||||
--border-gray: #E2E8F0;
|
||||
|
||||
// Gradients
|
||||
--gradient-primary: linear-gradient(135deg, #4B9BFF 0%, #2E7FF7 100%);
|
||||
--gradient-accent: linear-gradient(135deg, #00D4FF 0%, #4B9BFF 100%);
|
||||
--gradient-warm: linear-gradient(135deg, #FFD93D 0%, #FF6B6B 100%);
|
||||
|
||||
// Shadows
|
||||
--shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||
--shadow-md: 0 4px 12px rgba(75, 155, 255, 0.1);
|
||||
--shadow-lg: 0 8px 24px rgba(75, 155, 255, 0.15);
|
||||
--shadow-xl: 0 16px 40px rgba(75, 155, 255, 0.2);
|
||||
}
|
||||
|
||||
// Blind text for screen readers
|
||||
.blind {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Modern Header Structure
|
||||
// ===========================
|
||||
.global-header {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
box-shadow: var(--shadow-sm);
|
||||
z-index: 1000;
|
||||
height: 80px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 80px;
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Header Layout Components
|
||||
// ===========================
|
||||
|
||||
// Header Left Section
|
||||
.header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.logo {
|
||||
height: 45px;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
// Logo Wrapper
|
||||
.logo-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
// Logo with modern styling
|
||||
.logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
height: 45px;
|
||||
z-index: 10;
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
height: 100%;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
img {
|
||||
height: 45px;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: var(--primary-blue);
|
||||
padding: 4px 12px;
|
||||
background: var(--light-bg);
|
||||
border-radius: 20px;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
// When logo-text is a link
|
||||
&:hover {
|
||||
background: var(--primary-blue);
|
||||
color: var(--white);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
&:visited {
|
||||
color: var(--primary-blue);
|
||||
}
|
||||
}
|
||||
|
||||
// Logo link styles
|
||||
.logo-link,
|
||||
.mobile-logo-link,
|
||||
.drawer-logo-link {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
transition: transform 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
// Header Right Section
|
||||
.header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
// Search Button
|
||||
.search-btn {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: var(--gray-bg);
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
color: var(--text-gray);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background: var(--light-bg);
|
||||
color: var(--primary-blue);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Desktop/Mobile Layout Control
|
||||
// ===========================
|
||||
.desktop-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-header {
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Mobile Header Components
|
||||
// ===========================
|
||||
.mobile-left {
|
||||
.mobile-logo {
|
||||
height: 32px;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-center {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
|
||||
.mobile-title {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: var(--text-dark);
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-right {
|
||||
.mobile-menu-btn {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 8px;
|
||||
border-radius: 8px;
|
||||
transition: background-color 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background: var(--gray-bg);
|
||||
}
|
||||
|
||||
.hamburger-line {
|
||||
width: 24px;
|
||||
height: 2px;
|
||||
background: var(--text-dark);
|
||||
transition: all 0.3s ease;
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
&.active {
|
||||
.hamburger-line {
|
||||
&:nth-child(1) {
|
||||
transform: rotate(45deg) translateY(6px);
|
||||
}
|
||||
&:nth-child(2) {
|
||||
opacity: 0;
|
||||
}
|
||||
&:nth-child(3) {
|
||||
transform: rotate(-45deg) translateY(-6px);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Mobile Drawer/Modal
|
||||
// ===========================
|
||||
.mobile-drawer {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 9999;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&.active {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
|
||||
.drawer-content {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.drawer-overlay {
|
||||
display: none; // Not needed for full-screen drawer
|
||||
}
|
||||
|
||||
.drawer-content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--white);
|
||||
transform: translateY(100%);
|
||||
transition: transform 0.3s ease;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.drawer-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 20px;
|
||||
border-bottom: 2px solid var(--border-gray);
|
||||
background: var(--white);
|
||||
box-shadow: var(--shadow-sm);
|
||||
min-height: 60px;
|
||||
|
||||
.drawer-logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
|
||||
.logo {
|
||||
height: 32px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: var(--primary-blue);
|
||||
}
|
||||
}
|
||||
|
||||
.drawer-close {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 8px;
|
||||
font-size: 18px;
|
||||
color: var(--text-gray);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background: var(--white);
|
||||
color: var(--text-dark);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.drawer-nav {
|
||||
flex: 1;
|
||||
padding: 0;
|
||||
overflow-y: auto;
|
||||
background: var(--white);
|
||||
|
||||
.drawer-menu {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 20px 0;
|
||||
|
||||
li {
|
||||
margin-bottom: 8px;
|
||||
|
||||
.drawer-link {
|
||||
display: block;
|
||||
padding: 16px 24px;
|
||||
margin: 0 20px;
|
||||
color: var(--text-dark);
|
||||
text-decoration: none;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
border-radius: 12px;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover, &:active {
|
||||
background: var(--light-bg);
|
||||
color: var(--primary-blue);
|
||||
transform: translateX(4px);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.drawer-actions {
|
||||
padding: 24px;
|
||||
border-top: 2px solid var(--border-gray);
|
||||
background: var(--white);
|
||||
box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.05);
|
||||
|
||||
.drawer-login-btn {
|
||||
display: block;
|
||||
text-align: center;
|
||||
padding: 14px 20px;
|
||||
color: var(--text-dark);
|
||||
text-decoration: none;
|
||||
border: 2px solid var(--primary-blue);
|
||||
border-radius: 12px;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
margin-bottom: 12px;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background: var(--light-bg);
|
||||
color: var(--primary-blue);
|
||||
}
|
||||
}
|
||||
|
||||
.drawer-signup-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
padding: 14px 20px;
|
||||
background: var(--gradient-primary);
|
||||
color: var(--white);
|
||||
text-decoration: none;
|
||||
border-radius: 12px;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
margin-bottom: 12px;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: var(--shadow-md);
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
}
|
||||
|
||||
.drawer-search-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
padding: 14px 20px;
|
||||
background: var(--gray-bg);
|
||||
color: var(--text-dark);
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background: var(--light-bg);
|
||||
color: var(--primary-blue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-mobilemenu {
|
||||
position: absolute;
|
||||
right: $spacing-md;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 8px;
|
||||
z-index: $z-index-modal + 1; // Above the nav
|
||||
|
||||
span {
|
||||
display: block;
|
||||
width: 24px;
|
||||
height: 2px;
|
||||
background: $text-dark;
|
||||
position: relative;
|
||||
transition: all $transition-fast;
|
||||
text-indent: -9999px;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 24px;
|
||||
height: 2px;
|
||||
background: $text-dark;
|
||||
transition: all $transition-fast;
|
||||
}
|
||||
|
||||
&::before { top: -8px; }
|
||||
&::after { top: 8px; }
|
||||
}
|
||||
|
||||
&.on span {
|
||||
background: transparent;
|
||||
&::before { top: 0; transform: rotate(45deg); }
|
||||
&::after { top: 0; transform: rotate(-45deg); }
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Unified Navigation (Mobile-First)
|
||||
// ===========================
|
||||
.main-nav.m-nav {
|
||||
// Mobile: Off-canvas menu
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: $white;
|
||||
z-index: $z-index-modal;
|
||||
right: -100%; // Initial state for JS animation
|
||||
transition: none; // JS handles animation
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
// The JS will directly manipulate the 'right' property, not toggle a class for this element.
|
||||
// So, no .active or .on state here for the main nav panel.
|
||||
|
||||
.nav-header {
|
||||
padding: $spacing-lg;
|
||||
background: $gray-bg;
|
||||
border-bottom: 1px solid $border-gray;
|
||||
}
|
||||
|
||||
.nav-list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
flex-grow: 1;
|
||||
|
||||
.nav-item {
|
||||
border-bottom: 1px solid $border-gray;
|
||||
|
||||
> a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: $spacing-lg;
|
||||
color: $text-dark;
|
||||
font-size: $font-size-md;
|
||||
font-weight: $font-weight-medium;
|
||||
text-decoration: none;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&.has-submenu > a::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: $spacing-lg;
|
||||
top: 50%;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-right: 2px solid $text-gray;
|
||||
border-bottom: 2px solid $text-gray;
|
||||
transform: translateY(-50%) rotate(45deg);
|
||||
transition: transform $transition-fast;
|
||||
}
|
||||
|
||||
&.expanded > a::after {
|
||||
transform: translateY(-25%) rotate(-135deg);
|
||||
}
|
||||
|
||||
.sub-menu {
|
||||
display: none;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background: $gray-bg;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
padding: $spacing-md $spacing-lg $spacing-md ($spacing-lg * 2);
|
||||
color: $text-gray;
|
||||
font-size: $font-size-sm;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
background: $white;
|
||||
color: $primary-blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.expanded .sub-menu {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.info_wrap {
|
||||
padding: $spacing-xl $spacing-lg;
|
||||
background: $white;
|
||||
border-top: 1px solid $border-gray;
|
||||
margin-top: auto;
|
||||
// styles for tit1, tit2...
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Modern Navigation Menu
|
||||
// ===========================
|
||||
.nav-menu {
|
||||
display: flex;
|
||||
list-style: none;
|
||||
gap: 8px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
text-decoration: none;
|
||||
color: var(--text-dark);
|
||||
font-weight: 500;
|
||||
font-size: 15px;
|
||||
padding: 8px 16px;
|
||||
border-radius: 8px;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background: var(--light-bg);
|
||||
color: var(--primary-blue);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
}
|
||||
|
||||
.nav-icon {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.signup-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
text-decoration: none;
|
||||
background: var(--gradient-primary);
|
||||
color: var(--white);
|
||||
padding: 12px 24px;
|
||||
border-radius: 50px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: var(--shadow-md);
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Desktop Navigation Styles
|
||||
// ===========================
|
||||
@include respond-to('desktop') {
|
||||
.m-only { display: none !important; }
|
||||
.pc-only { display: block !important; }
|
||||
|
||||
.btn-mobilemenu { display: none; }
|
||||
|
||||
.main-nav.m-nav {
|
||||
position: static;
|
||||
right: auto;
|
||||
transition: none;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
overflow: visible;
|
||||
background: transparent;
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
|
||||
.nav-header { display: none; }
|
||||
.info_wrap { display: none; }
|
||||
|
||||
.nav-list {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
flex-grow: 1;
|
||||
|
||||
.nav-item {
|
||||
border-bottom: none;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
|
||||
> a {
|
||||
height: 100%;
|
||||
padding: 0 24px;
|
||||
color: var(--text-dark);
|
||||
font-weight: 500;
|
||||
font-size: 15px;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
color: var(--primary-blue);
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 24px;
|
||||
right: 24px;
|
||||
height: 3px;
|
||||
background: var(--primary-blue);
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.has-submenu > a::after { display: none; }
|
||||
|
||||
.sub-menu {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
background: var(--white);
|
||||
border: 1px solid var(--border-gray);
|
||||
border-radius: 8px;
|
||||
box-shadow: var(--shadow-lg);
|
||||
min-width: 200px;
|
||||
padding: 8px 0;
|
||||
display: none;
|
||||
z-index: 1001;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
padding: 8px 16px;
|
||||
color: var(--text-dark);
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background: var(--light-bg);
|
||||
color: var(--primary-blue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .sub-menu {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Body Layout Compensation
|
||||
// ===========================
|
||||
body {
|
||||
padding-top: 80px; // Compensate for fixed header
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Mobile Responsive Design
|
||||
// ===========================
|
||||
@media (max-width: 768px) {
|
||||
.global-header {
|
||||
height: 60px;
|
||||
|
||||
.container .header-content {
|
||||
padding: 0 16px;
|
||||
height: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
padding-top: 60px; // Smaller header on mobile
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.global-header {
|
||||
.header-content {
|
||||
padding: 0 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.logo {
|
||||
.logo-text {
|
||||
display: none; // Hide logo text on very small screens
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Main SASS Entry Point - Version 2 (Modern Vibrant Design)
|
||||
// Based on design/styles-v2.css
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@charset "utf-8";
|
||||
|
||||
// 1. Configuration and helpers (no CSS output)
|
||||
@import 'abstracts/variables';
|
||||
@import 'abstracts/mixins';
|
||||
|
||||
// 2. Base styles
|
||||
@import 'base/reset';
|
||||
@import 'base/typography';
|
||||
@import 'base/animations';
|
||||
|
||||
// 3. Layout
|
||||
@import 'layout/header';
|
||||
@import 'layout/footer';
|
||||
@import 'layout/grid';
|
||||
@import 'layout/container';
|
||||
|
||||
// 4. Components
|
||||
@import 'components/buttons';
|
||||
@import 'components/cards';
|
||||
@import 'components/forms';
|
||||
@import 'components/modals';
|
||||
@import 'components/navigation';
|
||||
@import 'components/partners';
|
||||
@import 'components/cta';
|
||||
|
||||
// 5. Page-specific styles
|
||||
@import 'pages/index';
|
||||
@import 'pages/home';
|
||||
@import 'pages/api-portal';
|
||||
@import 'pages/documentation';
|
||||
@import 'pages/login';
|
||||
|
||||
// 6. Themes
|
||||
@import 'themes/dark';
|
||||
|
||||
// 7. Utilities (should be last)
|
||||
@import 'base/utilities';
|
||||
|
||||
// 8. Vendor overrides
|
||||
@import 'vendors/overrides';
|
||||
@@ -0,0 +1,7 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// API Portal page specific styles
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
.api-portal-page {
|
||||
// Any API portal-specific styles go here
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Documentation page specific styles
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
.documentation-page {
|
||||
// Any documentation-specific styles go here
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Home page specific styles
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
.home-page {
|
||||
// Any home-specific styles go here
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,308 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Login Page Styles - Modern Design
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
.login-page {
|
||||
min-height: calc(100vh - 140px); // Account for header and footer
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, var(--light-bg) 0%, var(--gray-bg) 100%);
|
||||
padding: 40px 20px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
// Decorative background elements
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
right: -20%;
|
||||
width: 600px;
|
||||
height: 600px;
|
||||
background: radial-gradient(circle, var(--accent-cyan) 0%, transparent 70%);
|
||||
opacity: 0.1;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -30%;
|
||||
left: -10%;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
background: radial-gradient(circle, var(--primary-blue) 0%, transparent 70%);
|
||||
opacity: 0.1;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.login-container {
|
||||
width: 100%;
|
||||
max-width: 480px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.login-card {
|
||||
background: var(--white);
|
||||
border-radius: 24px;
|
||||
box-shadow: var(--shadow-xl);
|
||||
padding: 48px 40px;
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.8);
|
||||
|
||||
@media (max-width: 480px) {
|
||||
padding: 32px 24px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.login-header {
|
||||
text-align: center;
|
||||
margin-bottom: 40px;
|
||||
|
||||
.login-logo {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 24px;
|
||||
|
||||
img {
|
||||
height: 48px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: var(--primary-blue);
|
||||
padding: 6px 16px;
|
||||
background: var(--light-bg);
|
||||
border-radius: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.login-title {
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
color: var(--text-dark);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.login-subtitle {
|
||||
font-size: 15px;
|
||||
color: var(--text-gray);
|
||||
}
|
||||
}
|
||||
|
||||
.login-form {
|
||||
margin-bottom: 24px;
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 20px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--text-dark);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
width: 100%;
|
||||
padding: 14px 16px;
|
||||
font-size: 15px;
|
||||
border: 2px solid var(--border-gray);
|
||||
border-radius: 12px;
|
||||
background: var(--white);
|
||||
transition: all 0.3s ease;
|
||||
outline: none;
|
||||
|
||||
&::placeholder {
|
||||
color: var(--text-light);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-color: var(--primary-blue);
|
||||
box-shadow: 0 0 0 4px rgba(75, 155, 255, 0.1);
|
||||
}
|
||||
|
||||
&.error {
|
||||
border-color: var(--accent-orange);
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 4px rgba(255, 107, 107, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-top: 16px;
|
||||
|
||||
input[type="checkbox"] {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
accent-color: var(--primary-blue);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: 14px;
|
||||
color: var(--text-gray);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.login-button {
|
||||
width: 100%;
|
||||
padding: 16px 24px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--white);
|
||||
background: var(--gradient-primary);
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: var(--shadow-md);
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
.login-links {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
margin-top: 32px;
|
||||
padding-top: 32px;
|
||||
border-top: 1px solid var(--border-gray);
|
||||
flex-wrap: wrap;
|
||||
|
||||
@media (max-width: 480px) {
|
||||
gap: 12px;
|
||||
margin-top: 24px;
|
||||
padding-top: 24px;
|
||||
}
|
||||
|
||||
a {
|
||||
font-size: 14px;
|
||||
color: var(--text-gray);
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
|
||||
&:hover {
|
||||
color: var(--primary-blue);
|
||||
}
|
||||
|
||||
i {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.link-separator {
|
||||
color: var(--border-gray);
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
// Alert messages
|
||||
.login-alert {
|
||||
margin-bottom: 20px;
|
||||
padding: 12px 16px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
&.alert-error {
|
||||
background: rgba(255, 107, 107, 0.1);
|
||||
color: var(--accent-orange);
|
||||
border: 1px solid rgba(255, 107, 107, 0.2);
|
||||
}
|
||||
|
||||
&.alert-success {
|
||||
background: rgba(107, 207, 127, 0.1);
|
||||
color: var(--accent-green);
|
||||
border: 1px solid rgba(107, 207, 127, 0.2);
|
||||
}
|
||||
|
||||
&.alert-info {
|
||||
background: rgba(75, 155, 255, 0.1);
|
||||
color: var(--primary-blue);
|
||||
border: 1px solid rgba(75, 155, 255, 0.2);
|
||||
}
|
||||
|
||||
i {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
// Loading state
|
||||
.login-loading {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 24px;
|
||||
z-index: 10;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: opacity 0.3s ease;
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 3px solid var(--border-gray);
|
||||
border-top-color: var(--primary-blue);
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Dark theme styles (optional)
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Dark theme variables can be defined here
|
||||
// This file can be left empty if dark theme is not needed yet
|
||||
@@ -0,0 +1,6 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Vendor library overrides
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Place any third-party library style overrides here
|
||||
// This file can be left empty if no vendor libraries are used
|
||||
@@ -1,104 +1,90 @@
|
||||
<!doctype html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/kbank_base_layout}">
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/kjbank_base_layout}">
|
||||
<body>
|
||||
<section layout:fragment="contentFragment" class="content">
|
||||
<div class="content_wrap">
|
||||
<div class="sub_title2">
|
||||
<h2 class="title add7">로그인</h2>
|
||||
</div>
|
||||
<div class="inner i_cs9 h_inner9">
|
||||
<div class="form_type">
|
||||
<form id="loginForm" role="form" name="loginForm" th:action="@{/actionLogin.do}" method="post">
|
||||
<th:block layout:fragment="contentFragment">
|
||||
<div class="login-page">
|
||||
<div class="login-container">
|
||||
<div class="login-card">
|
||||
<!-- Login Header with Logo -->
|
||||
<div class="login-header">
|
||||
<h1 class="login-title">로그인</h1>
|
||||
<p class="login-subtitle">광주은행 개발자 포털에 오신 것을 환영합니다</p>
|
||||
</div>
|
||||
|
||||
<!-- Alert Messages -->
|
||||
<div th:if="${param.logout}" class="login-alert alert-info">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
<span>로그아웃되었습니다.</span>
|
||||
</div>
|
||||
|
||||
<!-- Login Form -->
|
||||
<form id="loginForm" role="form" name="loginForm" th:action="@{/actionLogin.do}" method="post" class="login-form">
|
||||
<input type="hidden" id="message" name="message" th:value="${loginMessage}">
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
|
||||
<div class="form_type_box">
|
||||
<div class="info1 form_top">
|
||||
<p class="title">
|
||||
<span>아이디</span>
|
||||
</p>
|
||||
<div class="info_line info_add">
|
||||
<div class="info_box1 add add2">
|
||||
<input type="text" id="id" name="id" th:value="${loginId}"
|
||||
class="common_input_type_1 h_inp"
|
||||
placeholder="이메일 아이디를 입력해 주세요." required>
|
||||
<input type="hidden" id="loginId" th:value="${loginId}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" id="loginId" th:value="${loginId}">
|
||||
|
||||
<div class="info1">
|
||||
<p class="title">
|
||||
<span>비밀번호</span>
|
||||
</p>
|
||||
<div class="info_line info_add">
|
||||
<div class="info_box1 add add2">
|
||||
<input type="password" id="password" name="password"
|
||||
class="common_input_type_1 h_inp"
|
||||
placeholder="비밀번호를 입력해 주세요." required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Email Field -->
|
||||
<div class="form-group">
|
||||
<label for="id" class="form-label">이메일</label>
|
||||
<input type="text"
|
||||
id="id"
|
||||
name="id"
|
||||
th:value="${loginId}"
|
||||
class="form-input"
|
||||
placeholder="이메일 아이디를 입력해 주세요"
|
||||
required>
|
||||
</div>
|
||||
<div class="box_inp">
|
||||
<span class="inp_check f_size">
|
||||
<input id="checkId" name="checkId" type="checkbox">
|
||||
<label for="checkId">아이디 저장</label>
|
||||
</span>
|
||||
|
||||
<!-- Password Field -->
|
||||
<div class="form-group">
|
||||
<label for="password" class="form-label">비밀번호</label>
|
||||
<input type="password"
|
||||
id="password"
|
||||
name="password"
|
||||
class="form-input"
|
||||
placeholder="비밀번호를 입력해 주세요"
|
||||
required>
|
||||
</div>
|
||||
|
||||
<!-- Remember Me Checkbox -->
|
||||
<div class="form-checkbox">
|
||||
<input id="checkId" name="checkId" type="checkbox">
|
||||
<label for="checkId">아이디 저장</label>
|
||||
</div>
|
||||
</form>
|
||||
<div class="btn_login">
|
||||
<a href="#" class="common_btn_type_1 h_btn" id="actionLogin"><span>로그인</span></a>
|
||||
|
||||
<!-- Login Button -->
|
||||
<button type="button" class="login-button" id="actionLogin">
|
||||
로그인
|
||||
</button>
|
||||
|
||||
<!-- Additional Links -->
|
||||
<div class="login-links">
|
||||
<a th:href="@{/account_recovery(tab='findId')}">
|
||||
<i class="fas fa-search"></i>
|
||||
<span>아이디 찾기</span>
|
||||
</a>
|
||||
<span class="link-separator">|</span>
|
||||
<a th:href="@{/account_recovery(tab='resetPassword')}">
|
||||
<i class="fas fa-lock"></i>
|
||||
<span>비밀번호 초기화</span>
|
||||
</a>
|
||||
<span class="link-separator">|</span>
|
||||
<a th:href="@{/signup}">
|
||||
<i class="fas fa-user-plus"></i>
|
||||
<span>회원가입</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="login_list pc-only">
|
||||
<ul>
|
||||
<li class="icon_search">
|
||||
<img th:src="@{/img/icon/icon_login_search.png}" alt="">
|
||||
<a th:href="@{/account_recovery(tab='findId')}">아이디 찾기</a>
|
||||
</li>
|
||||
<li>
|
||||
<span>|</span>
|
||||
</li>
|
||||
<li class="icon_lock">
|
||||
<img th:src="@{/img/icon/icon_login_lock.png}" alt="">
|
||||
<a th:href="@{/account_recovery(tab='resetPassword')}">비밀번호 초기화</a>
|
||||
</li>
|
||||
<li>
|
||||
<span>|</span>
|
||||
</li>
|
||||
<li class="icon_join">
|
||||
<img th:src="@{/img/icon/icon_login_join.png}" alt="">
|
||||
<a th:href="@{/signup}">회원가입</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="login_list m-only">
|
||||
<ul>
|
||||
<li class="icon_search">
|
||||
<a th:href="@{/account_recovery(tab='findId')}">아이디 찾기</a>
|
||||
</li>
|
||||
<li>
|
||||
<span>|</span>
|
||||
</li>
|
||||
<li class="icon_lock">
|
||||
<a th:href="@{/account_recovery(tab='resetPassword')}">비밀번호 초기화</a>
|
||||
</li>
|
||||
<li>
|
||||
<span>|</span>
|
||||
</li>
|
||||
<li class="icon_join">
|
||||
<a th:href="@{/signup}">회원가입</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div th:if="${param.logout}" class="alert alert-info mt-3">
|
||||
<p>로그아웃되었습니다.</p>
|
||||
|
||||
<!-- Loading State -->
|
||||
<div class="login-loading" id="loginLoading">
|
||||
<div class="spinner"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
</th:block>
|
||||
</body>
|
||||
<th:block layout:fragment="contentScript">
|
||||
<script th:inline="javascript">
|
||||
@@ -179,6 +165,10 @@
|
||||
|
||||
let actionLogin = function (event) {
|
||||
let form = document.loginForm;
|
||||
|
||||
// Show loading state
|
||||
$('#loginLoading').addClass('active');
|
||||
|
||||
if ($('#checkId').is(':checked')) {
|
||||
setCookie('saveid', $('#id').val(), new Date(new Date().getTime() + 1000 * 3600 * 24 * 30));
|
||||
} else {
|
||||
@@ -188,9 +178,11 @@
|
||||
if (!form.checkValidity()) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
$('#loginLoading').removeClass('active');
|
||||
customPopups.showAlert('입력 정보 확인');
|
||||
} else {
|
||||
if (form.password.value.length < 8) {
|
||||
$('#loginLoading').removeClass('active');
|
||||
customPopups.showAlert('[[#{login.passLengthShort}]]');
|
||||
} else {
|
||||
const originalPassword = form.password.value;
|
||||
@@ -201,7 +193,10 @@
|
||||
form.classList.add('was-validated');
|
||||
};
|
||||
|
||||
$('#actionLogin').on('click', actionLogin);
|
||||
$('#actionLogin').on('click', function(event) {
|
||||
event.preventDefault();
|
||||
actionLogin(event);
|
||||
});
|
||||
$('#password').on('keydown', function (event) {
|
||||
if (event.key === 'Enter' || event.keyCode === 13 || event.code === 'Enter') {
|
||||
event.preventDefault();
|
||||
|
||||
@@ -1,459 +1,372 @@
|
||||
<!doctype html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/kbank_index_layout}">
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/kjbank_index_layout}">
|
||||
|
||||
|
||||
<body>
|
||||
<section layout:fragment="contentFragment" class="content main">
|
||||
<script th:src="@{/js/htmx.min.js}"></script>
|
||||
<!-- main slick -->
|
||||
<div class="slider-container">
|
||||
<div class="slider m-only">
|
||||
<div class="slider_box">
|
||||
|
||||
<img th:src="@{/img/img_mainslick_m.png}" alt="슬라이드 1">
|
||||
<div class="slick_txt">
|
||||
<p>디지털 금융 리더 <span>케이뱅크</span>가<br/>새로운 비즈니스 기회를<br/>제공합니다.</p>
|
||||
<th:block layout:fragment="contentFragment">
|
||||
<section class="hero-section">
|
||||
<div class="hero-patterns">
|
||||
<div class="pattern-circle pattern-1"></div>
|
||||
<div class="pattern-circle pattern-2"></div>
|
||||
<div class="pattern-dots"></div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="hero-content">
|
||||
<div class="hero-badge">
|
||||
<span class="badge-icon">🚀</span>
|
||||
<span>Wa bank 생태계에 오신 것을 환영합니다!</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="slider_box">
|
||||
<img th:src="@{/img/img_mainslick2_m.png}" alt="슬라이드 2">
|
||||
<div class="slick_txt">
|
||||
<p>차별화된 <span>API와<br> 편리한 테스트 환경</span>을<br> 지원합니다</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="slider_box">
|
||||
<img th:src="@{/img/img_mainslick3_m.png}" alt="슬라이드 3">
|
||||
<div class="slick_txt">
|
||||
<p><span>디지털 금융 혁신</span>을<br> 케이뱅크가<br> 함께합니다</p>
|
||||
<h1 class="main-headline">
|
||||
<span class="headline-wa">Wa한</span> 금융 혁신,<br>
|
||||
여러분의 아이디어로 시작됩니다
|
||||
</h1>
|
||||
<h2 class="sub-headline">
|
||||
광주은행 오픈 API로 새로운 금융 서비스를 만들어보세요.<br>
|
||||
안전하고 빠르게, 그리고 쉽게 연동할 수 있습니다.
|
||||
</h2>
|
||||
<div class="hero-buttons">
|
||||
<a href="/apis" class="btn btn-primary">
|
||||
<i class="fas fa-code"></i> API 둘러보기
|
||||
</a>
|
||||
<a href="#get-started" class="btn btn-secondary">
|
||||
<i class="fas fa-play"></i> 5분 만에 시작하기
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="slider pc-only">
|
||||
<div class="slider_box">
|
||||
<img th:src="@{/img/img_mainslick_pc.png}" alt="슬라이드 1">
|
||||
<div class="slick_txt">
|
||||
<p><span>케이뱅크</span>가 새로운 비즈니스<br> 기회를 제공합니다</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="slider_box">
|
||||
<img th:src="@{/img/img_mainslick2_pc.png}" alt="슬라이드 2">
|
||||
<div class="slick_txt">
|
||||
<p>차별화된 <span>API와</span><br/>
|
||||
<span>편리한 테스트 환경</span>을<br/>지원합니다</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="slider_box">
|
||||
<img th:src="@{/img/img_mainslick3_pc.png}" alt="슬라이드 3">
|
||||
<div class="slick_txt">
|
||||
<p><span>디지털 금융 혁신</span>을<br>케이뱅크가<br>함께합니다</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="slick-prev" aria-label="Previous" type="button">이전</button>
|
||||
<button class="slick-next" aria-label="Next" type="button">다음</button>
|
||||
<ul class="slick-dots">
|
||||
<li>
|
||||
<button type="button">1</button>
|
||||
</li>
|
||||
<li>
|
||||
<button type="button">2</button>
|
||||
</li>
|
||||
<li>
|
||||
<button type="button">3</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- // main slick -->
|
||||
</section>
|
||||
|
||||
<div class="main-container">
|
||||
<div class="search_type">
|
||||
<form th:action="@{/apis}" id="searchForm" method="get">
|
||||
<div class="search-container">
|
||||
<input type="text" name="keyword" class="search-box" id="search-box" placeholder="어떤 API를 찾고 계신가요?">
|
||||
<button class="search-button" type="submit"></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="hashtag">
|
||||
<ul>
|
||||
<li th:each="tag: ${hashtags}"><a href="#" th:text="${tag}">#인증</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="main_keyword">
|
||||
<div class="api_tit">
|
||||
<h2>가장 많이 찾는 API</h2>
|
||||
<p class="total_view">
|
||||
<a href="/apis">전체보기</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="api_keyword">
|
||||
<ul class="keyword_list tab_list">
|
||||
<li>
|
||||
<a href="#"
|
||||
hx-get="/api_fragments"
|
||||
hx-target="#api_spec_list"
|
||||
hx-trigger="click"
|
||||
onclick="setActive(this)">전체<span class="number" th:text="${totalApiCount}"></span></a>
|
||||
</li>
|
||||
<li th:each="item : ${services}">
|
||||
<a href="#"
|
||||
th:hx-get="@{/api_fragments(id=${item.id})}"
|
||||
hx-target="#api_spec_list"
|
||||
hx-trigger="click"
|
||||
onclick="setActive(this)">
|
||||
[[${item.groupName}]]<span class="number" th:text="${item.apiGroupApiList.size()}"></span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="more_type m-only">
|
||||
<button class="showmore" type="button">
|
||||
<img th:src="@{/img/icon/icon_more_btn.png}" alt="더보기 버튼">
|
||||
</button>
|
||||
</div>
|
||||
<div class="more_type pc-only">
|
||||
<button class="showmore" type="button">
|
||||
<img th:src="@{/img/icon/icon_more_btn2.png}" alt="더보기 버튼">
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="api_info_container box_list" id="api_spec_list">
|
||||
<div class="api_info_box" th:each="api : ${apis}" th:data-href="@{/apis/detail(id=${api.apiId})}">
|
||||
<div class="api_list" th:data-href="@{/apis/detail(id=${api.apiId})}">
|
||||
<p class="txt1" th:text="${api.apiName}"></p>
|
||||
<p class="txt2" th:text="${api.apiSimpleDescription}"></p>
|
||||
<!-- API 검색 섹션 -->
|
||||
<section class="api-search-section">
|
||||
<div class="container">
|
||||
<div class="search-container">
|
||||
<form th:action="@{/apis}" method="get" class="search-form">
|
||||
<div class="search-wrapper">
|
||||
<input type="text" class="search-input" placeholder="원하는 API를 검색해보세요" id="apiSearchInput" name="keyword">
|
||||
<button class="search-button" type="submit">
|
||||
<i class="fas fa-search"></i>
|
||||
<span>검색하기</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="api_img" style="height: 48px;">
|
||||
<a th:href="@{/apis/detail(id=${api.apiId})}" class="btn btn-primary">
|
||||
<img th:if="${#strings.isEmpty(api.mainIcon) == false}" th:src="${api.mainIcon}" alt="">
|
||||
</a>
|
||||
</form>
|
||||
<div class="hashtag-suggestions" th:if="${hashtags != null and not #lists.isEmpty(hashtags)}">
|
||||
<span class="hashtag-label">추천 검색어:</span>
|
||||
<a href="#" class="hashtag" th:each="tag : ${hashtags}"
|
||||
th:data-search="${tag}"
|
||||
th:text="${'#' + tag}">
|
||||
</a>
|
||||
</div>
|
||||
<!-- Fallback hashtags if no hashtags from controller -->
|
||||
<div class="hashtag-suggestions" th:unless="${hashtags != null and not #lists.isEmpty(hashtags)}">
|
||||
<span class="hashtag-label">추천 검색어:</span>
|
||||
<a href="#" class="hashtag" data-search="계좌조회">#계좌조회</a>
|
||||
<a href="#" class="hashtag" data-search="송금API">#송금API</a>
|
||||
<a href="#" class="hashtag" data-search="실시간결제">#실시간결제</a>
|
||||
<a href="#" class="hashtag" data-search="오픈뱅킹">#오픈뱅킹</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="api-showcase">
|
||||
<div class="container">
|
||||
<div class="section-header">
|
||||
<h2 class="section-title">
|
||||
<span class="title-highlight">인기 API</span>로 바로 시작하세요
|
||||
</h2>
|
||||
<p class="section-subtitle">가장 많이 사용되는 API를 확인하고 바로 테스트해보세요</p>
|
||||
</div>
|
||||
<div class="api-grid">
|
||||
<!-- Dynamic API Cards from Controller (max 4) -->
|
||||
<div th:each="api, iterStat : ${apis}"
|
||||
th:if="${iterStat.index < 4}"
|
||||
class="api-card"
|
||||
th:classappend="${iterStat.index == 0} ? 'api-card-popular' : (${iterStat.index == 3} ? 'api-card-new' : '')">
|
||||
|
||||
<!-- Show badge for first (인기) and last (NEW) items -->
|
||||
<div th:if="${iterStat.index == 0}" class="api-badge">인기</div>
|
||||
<div th:if="${iterStat.index == 3}" class="api-badge new">NEW</div>
|
||||
|
||||
<!-- API Icon - using different icons based on index or API type -->
|
||||
<div class="api-icon">
|
||||
<!-- Icon selection based on API name or service type -->
|
||||
<i th:if="${api.apiName != null}"
|
||||
th:class="${#strings.containsIgnoreCase(api.apiName, '계좌') or #strings.containsIgnoreCase(api.apiName, '조회')} ? 'fas fa-wallet' :
|
||||
(${#strings.containsIgnoreCase(api.apiName, '송금') or #strings.containsIgnoreCase(api.apiName, '이체')} ? 'fas fa-exchange-alt' :
|
||||
(${#strings.containsIgnoreCase(api.apiName, '카드') or #strings.containsIgnoreCase(api.apiName, '결제')} ? 'fas fa-credit-card' :
|
||||
(${#strings.containsIgnoreCase(api.apiName, 'AI') or #strings.containsIgnoreCase(api.apiName, '분석')} ? 'fas fa-chart-line' :
|
||||
(${iterStat.index == 0} ? 'fas fa-wallet' :
|
||||
(${iterStat.index == 1} ? 'fas fa-exchange-alt' :
|
||||
(${iterStat.index == 2} ? 'fas fa-credit-card' : 'fas fa-chart-line'))))))"></i>
|
||||
</div>
|
||||
|
||||
<!-- API Name -->
|
||||
<h3 class="api-name" th:text="${api.apiName}">API 이름</h3>
|
||||
|
||||
<!-- API Description -->
|
||||
<p class="api-description" th:text="${api.apiSimpleDescription != null ? api.apiSimpleDescription : api.description}">API 설명</p>
|
||||
|
||||
<!-- API Features/Method Info -->
|
||||
<div class="api-features">
|
||||
<span class="feature-tag" th:if="${api.apiMethod != null}" th:text="${api.apiMethod}">GET</span>
|
||||
<span class="feature-tag" th:if="${api.service != null}" th:text="${api.service}">서비스</span>
|
||||
</div>
|
||||
|
||||
<!-- Test Link -->
|
||||
<a th:href="@{/apis/detail(id=${api.apiId})}" class="api-link">
|
||||
테스트하기 <i class="fas fa-arrow-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Fallback: Show static cards if no APIs from controller -->
|
||||
<div th:if="${apis == null or #lists.isEmpty(apis)}" class="api-card api-card-popular">
|
||||
<div class="api-badge">인기</div>
|
||||
<div class="api-icon">
|
||||
<i class="fas fa-wallet"></i>
|
||||
</div>
|
||||
<h3 class="api-name">계좌 조회 API</h3>
|
||||
<p class="api-description">실시간 잔액 조회와 거래내역을 안전하게 확인</p>
|
||||
<div class="api-features">
|
||||
<span class="feature-tag">실시간</span>
|
||||
<span class="feature-tag">OAuth 2.0</span>
|
||||
</div>
|
||||
<a href="#" class="api-link">
|
||||
테스트하기 <i class="fas fa-arrow-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div th:if="${apis == null or #lists.isEmpty(apis)}" class="api-card">
|
||||
<div class="api-icon">
|
||||
<i class="fas fa-exchange-alt"></i>
|
||||
</div>
|
||||
<h3 class="api-name">송금 API</h3>
|
||||
<p class="api-description">간편하고 안전한 송금 서비스 구현</p>
|
||||
<div class="api-features">
|
||||
<span class="feature-tag">간편송금</span>
|
||||
<span class="feature-tag">실명확인</span>
|
||||
</div>
|
||||
<a href="#" class="api-link">
|
||||
테스트하기 <i class="fas fa-arrow-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div th:if="${apis == null or #lists.isEmpty(apis)}" class="api-card">
|
||||
<div class="api-icon">
|
||||
<i class="fas fa-credit-card"></i>
|
||||
</div>
|
||||
<h3 class="api-name">카드 결제 API</h3>
|
||||
<p class="api-description">온/오프라인 결제 솔루션 통합</p>
|
||||
<div class="api-features">
|
||||
<span class="feature-tag">PG연동</span>
|
||||
<span class="feature-tag">간편결제</span>
|
||||
</div>
|
||||
<a href="#" class="api-link">
|
||||
테스트하기 <i class="fas fa-arrow-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div th:if="${apis == null or #lists.isEmpty(apis)}" class="api-card api-card-new">
|
||||
<div class="api-badge new">NEW</div>
|
||||
<div class="api-icon">
|
||||
<i class="fas fa-chart-line"></i>
|
||||
</div>
|
||||
<h3 class="api-name">AI 신용평가 API</h3>
|
||||
<p class="api-description">머신러닝 기반 실시간 신용 분석</p>
|
||||
<div class="api-features">
|
||||
<span class="feature-tag">AI/ML</span>
|
||||
<span class="feature-tag">실시간</span>
|
||||
</div>
|
||||
<a href="#" class="api-link">
|
||||
테스트하기 <i class="fas fa-arrow-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 정보 섹션 -->
|
||||
<section class="info-section">
|
||||
<div class="container">
|
||||
<div class="info-wrapper">
|
||||
<div class="image-container">
|
||||
<div class="image-placeholder">
|
||||
<i class="fas fa-chart-line"></i>
|
||||
<span>금융 혁신</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="main_con">
|
||||
<p class="con_tit m-only"><img th:src="@{/img/img_con_tit.png}" alt="Kbank API PORTAL"></p>
|
||||
<p class="con_tit pc-only"><img th:src="@{/img/img_con_tit2.png}" alt="Kbank API PORTAL"></p>
|
||||
<p class="con_img m-only"><img th:src="@{/img/img_mask_group.png}" alt="Kbank API PORTAL"></p>
|
||||
<p class="con_img pc-only"><img th:src="@{/img/img_mask_group2.png}" alt="Kbank API PORTAL"></p>
|
||||
<p class="con_txt m-only">
|
||||
<span>Kbank API Portal</span>은 기업이 금융서비스를<br>
|
||||
편리하게 개발할 수 있도록 차별화된<br>
|
||||
API와 테스트환경을 제공합니다.<br>
|
||||
</p>
|
||||
<p class="con_txt pc-only">
|
||||
<span>Kbank API Portal</span>은 기업이 금융서비스를 편리하게 개발할 수 있도록 차별화된 API와 테스트환경을 제공합니다.
|
||||
</p>
|
||||
<div class="main_btn">
|
||||
<a th:href="@{/intro}" class="common_btn_type_5"><span>처음 만나는 케이뱅크 API</span></a>
|
||||
<a th:href="@{/partnership}" class="common_btn_type_5 m_btn"><span>사업 제휴 문의</span></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tiding_box">
|
||||
<div class="api_type">
|
||||
<div class="api_tiding">
|
||||
<div class="api_tit">
|
||||
<h2>새로운 케이뱅크 API 소식을<br> 만나보세요</h2>
|
||||
<p class="total_view">
|
||||
<a href="/portalnotice">전체보기</a>
|
||||
<div class="info-content">
|
||||
<p class="highlight-text">
|
||||
광주은행 <span class="text-accent">API Portal</span>은 기업이 금융서비스를 편리하게 개발할 수 있도록<br>
|
||||
차별화된 API와 테스트환경을 제공합니다.
|
||||
</p>
|
||||
</div>
|
||||
<div class="api_tiding_list">
|
||||
<ul>
|
||||
<li th:each="notice : ${portalNotices}">
|
||||
<a th:href="@{/portalnotice/detail(id=${notice.id})}">
|
||||
<p th:text="${notice.noticeSubject}"></p>
|
||||
</a>
|
||||
<span th:text="${#temporals.format(notice.createdDate, 'yyyy.MM.dd')}"></span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="action-buttons">
|
||||
<a href="#" class="action-btn">
|
||||
<span class="btn-number">1</span>
|
||||
<span class="btn-text">처음 만나는 광주뱅크 API</span>
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
</a>
|
||||
<a href="#" class="action-btn">
|
||||
<span class="btn-number">2</span>
|
||||
<span class="btn-text">사업 제휴 문의</span>
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="api_info">
|
||||
<ul>
|
||||
<li class="img1">
|
||||
<a th:href="@{/faq_list}">
|
||||
<p>FAQ</p>
|
||||
<span>자주 묻는 질문과 답변을<br> 확인해보세요</span>
|
||||
<img th:src="@{/img/icon/icon_petals01.png}" alt="faq 이미지">
|
||||
</a>
|
||||
</li>
|
||||
<li class="img2">
|
||||
<a th:href="@{/inquiry}">
|
||||
<p>Q&A</p>
|
||||
<span>문의사항에<br> 친절하게 답변 드리겠습니다</span>
|
||||
<img th:src="@{/img/icon/icon_petals02.png}" alt="Q&A 이미지">
|
||||
</a>
|
||||
</li>
|
||||
<li class="img3">
|
||||
<a th:href="@{/partnership}">
|
||||
<p>사업제휴</p>
|
||||
<span>온라인 비즈니스 혁신을 위한<br> 사업 제안을 환영합니다</span>
|
||||
<img th:src="@{/img/icon/icon_petals03.png}" alt="사업제휴 이미지">
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 지원 센터 섹션 -->
|
||||
<section class="support-center">
|
||||
<div class="container">
|
||||
<div class="section-header">
|
||||
<h2 class="section-title">
|
||||
도움이 <span class="title-highlight">필요하신가요?</span>
|
||||
</h2>
|
||||
<p class="section-subtitle">다양한 방법으로 필요한 정보를 찾아보세요</p>
|
||||
</div>
|
||||
<div class="support-grid">
|
||||
<a th:href="@{/portalnotice}" class="support-card">
|
||||
<div class="card-icon">
|
||||
<i class="fas fa-bullhorn"></i>
|
||||
</div>
|
||||
<h3>공지사항</h3>
|
||||
<p>최신 업데이트와 중요한 소식을 확인하세요</p>
|
||||
<div class="card-arrow">
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
</div>
|
||||
</a>
|
||||
<a th:href="@{/faq_list}" class="support-card">
|
||||
<div class="card-icon">
|
||||
<i class="fas fa-question-circle"></i>
|
||||
</div>
|
||||
<h3>자주 묻는 질문</h3>
|
||||
<p>자주 묻는 질문과 답변을 빠르게 찾아보세요</p>
|
||||
<div class="card-arrow">
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
</div>
|
||||
</a>
|
||||
<a th:href="@{/inquiry}" class="support-card">
|
||||
<div class="card-icon">
|
||||
<i class="fas fa-comments"></i>
|
||||
</div>
|
||||
<h3>문의하기</h3>
|
||||
<p>추가 도움이 필요하시면 직접 문의해주세요</p>
|
||||
<div class="card-arrow">
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="api_count">
|
||||
<div class="api_total_box">
|
||||
<p class="txt m-only">우리곁의 수많은 서비스들이<br> <em>케이뱅크API</em>와<br> 함께하고 있습니다</p>
|
||||
<p class="txt pc-only">우리곁의 수많은 서비스들이<br> <em>케이뱅크API와 함께</em>하고 있습니다</p>
|
||||
<div class="api_total">
|
||||
<ul>
|
||||
<li>
|
||||
<img th:src="@{/img/icon/icon_api01.png}" alt="서비스 이용 수">
|
||||
<div class="api_num">
|
||||
<p th:text="${serviceCount}"></p>
|
||||
<span>서비스 이용</span>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<img th:src="@{/img/icon/icon_api02.png}" alt="API 이용건수">
|
||||
<div class="api_num">
|
||||
<p th:text="${selectedApiCount}"></p>
|
||||
<span>API 이용</span>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<img th:src="@{/img/icon/icon_api03.png}" alt="API 활용기업">
|
||||
<div class="api_num">
|
||||
<p th:text="${approvedOrgCount}"></p>
|
||||
<span>API 활용 기업</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- API 활용 현황 섹션 -->
|
||||
<section class="api-stats-section">
|
||||
<div class="container">
|
||||
<div class="section-header">
|
||||
<h2 class="section-title">
|
||||
우리곁의 수많은 서비스들이<br>
|
||||
<span class="title-highlight">광주은행 API</span>와 함께하고 있습니다
|
||||
</h2>
|
||||
</div>
|
||||
<div class="stats-cards">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon">
|
||||
<i class="fas fa-store"></i>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-number" th:attr="data-target=${serviceCount != null ? serviceCount : 0}" th:text="${serviceCount != null ? serviceCount : 0}">0</div>
|
||||
<div class="stat-label">서비스 이용 수</div>
|
||||
<div class="stat-description">다양한 분야의 서비스가 활용중</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon">
|
||||
<i class="fas fa-exchange-alt"></i>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-number" th:attr="data-target=${totalApiCount != null ? totalApiCount : 0}" th:text="${totalApiCount != null ? totalApiCount : 0}">0</div>
|
||||
<div class="stat-label">API 이용 건수</div>
|
||||
<div class="stat-description">일일 평균 API 호출 수</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon">
|
||||
<i class="fas fa-building"></i>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-number" th:attr="data-target=${approvedOrgCount != null ? approvedOrgCount : 0}" th:text="${approvedOrgCount != null ? approvedOrgCount : 0}">0</div>
|
||||
<div class="stat-label">API 활용 기업</div>
|
||||
<div class="stat-description">혁신적인 파트너사와 함께</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main_bg"></div>
|
||||
</section>
|
||||
</section>
|
||||
</th:block>
|
||||
</body>
|
||||
<th:block layout:fragment="contentScript">
|
||||
<script th:inline="javascript">
|
||||
$(document).ready(function() {
|
||||
// 기존 success 메시지 처리
|
||||
var successMsg = [[${success}]];
|
||||
console.log("Success message:", successMsg);
|
||||
if (successMsg) {
|
||||
console.log("Showing alert");
|
||||
customPopups.showAlert(successMsg);
|
||||
}
|
||||
|
||||
// 장기미사용 계정 체크
|
||||
const dormantAccount = [[${session.dormantAccount}]];
|
||||
if (dormantAccount) {
|
||||
const dormantMsg = /*[[${session.success}]]*/ '';
|
||||
const redirectUrl = /*[[${session.redirectUrl}]]*/ '';
|
||||
|
||||
console.log('dormantMsg:', dormantMsg);
|
||||
console.log('redirectUrl:', redirectUrl);
|
||||
|
||||
customPopups.showAlert(dormantMsg);
|
||||
$('#customAlertOkButton').off('click.custom').on('click.custom', function () {
|
||||
customPopups.hideAlert('#customAlert');
|
||||
window.location.href = redirectUrl;
|
||||
});
|
||||
return; // 다른 체크 중단
|
||||
}
|
||||
|
||||
// 비밀번호 만료 체크 추가
|
||||
const passwordExpired = [[${session.passwordExpired}]];
|
||||
if (passwordExpired) {
|
||||
const pwdExpiredMsg = /*[[${session.success}]]*/ '';
|
||||
const formattedMsg = pwdExpiredMsg.replace(/\n/g, '<br>');
|
||||
const redirectUrl = /*[[${session.redirectUrl}]]*/ '';
|
||||
|
||||
console.log('pwdExpiredMsg:', pwdExpiredMsg);
|
||||
console.log('redirectUrl:', redirectUrl);
|
||||
|
||||
$('#customAlertMessage').html(formattedMsg);
|
||||
$('#customAlert').css('display','flex');
|
||||
|
||||
$('#customAlertOkButton').off('click.custom').on('click.custom', function () {
|
||||
customPopups.hideAlert('#customAlert');
|
||||
window.location.href = redirectUrl;
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
function setActive(element) {
|
||||
// Remove 'active' class from all links
|
||||
document.querySelectorAll('.keyword_list a').forEach(el => {
|
||||
el.classList.remove('active');
|
||||
});
|
||||
// Add 'active' class to clicked link
|
||||
element.classList.add('active');
|
||||
}
|
||||
// 숫자 카운트업 애니메이션
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const observerOptions = {
|
||||
threshold: 0.5,
|
||||
rootMargin: '0px 0px -100px 0px'
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', (event) => {
|
||||
const ITEMS_PER_PAGE = 4;
|
||||
let isExpanded = false;
|
||||
const animateNumbers = (entries, observer) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
const numbers = entry.target.querySelectorAll('.stat-number');
|
||||
|
||||
// 더보기 버튼 초기화
|
||||
function initMoreButton() {
|
||||
const mobileMoreBtn = document.querySelector('.more_type.m-only .showmore');
|
||||
const pcMoreBtn = document.querySelector('.more_type.pc-only .showmore');
|
||||
const apiInfoBoxes = document.querySelectorAll('.api_info_box');
|
||||
numbers.forEach(number => {
|
||||
const target = parseInt(number.getAttribute('data-target'));
|
||||
const duration = 2000; // 2초
|
||||
const increment = target / (duration / 16);
|
||||
let current = 0;
|
||||
|
||||
// 5개 미만이면 더보기 버튼 숨기기
|
||||
const mobileMoreContainer = document.querySelector('.more_type.m-only');
|
||||
const pcMoreContainer = document.querySelector('.more_type.pc-only');
|
||||
const updateNumber = () => {
|
||||
current += increment;
|
||||
if (current < target) {
|
||||
number.textContent = Math.floor(current).toLocaleString('ko-KR');
|
||||
requestAnimationFrame(updateNumber);
|
||||
} else {
|
||||
number.textContent = target.toLocaleString('ko-KR');
|
||||
}
|
||||
};
|
||||
|
||||
console.log('더보기 버튼 초기화:', {
|
||||
항목개수: apiInfoBoxes.length,
|
||||
보여질상태: apiInfoBoxes.length >= 5 ? 'block' : 'none'
|
||||
});
|
||||
updateNumber();
|
||||
});
|
||||
|
||||
// 더보기 버튼 표시 여부 설정
|
||||
if (apiInfoBoxes.length < 5) {
|
||||
mobileMoreContainer.style.setProperty('display', 'none', 'important');
|
||||
pcMoreContainer.style.setProperty('display', 'none', 'important');
|
||||
} else {
|
||||
mobileMoreContainer.style.setProperty('display', 'block', 'important');
|
||||
pcMoreContainer.style.setProperty('display', 'block', 'important');
|
||||
}
|
||||
|
||||
// 초기 상태 설정
|
||||
updateApiListVisibility();
|
||||
|
||||
// 더보기 버튼 이벤트 리스너 설정
|
||||
[mobileMoreBtn, pcMoreBtn].forEach(btn => {
|
||||
if (btn) {
|
||||
btn.removeEventListener('click', handleMoreClick);
|
||||
btn.addEventListener('click', handleMoreClick);
|
||||
observer.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const observer = new IntersectionObserver(animateNumbers, observerOptions);
|
||||
const statsSection = document.querySelector('.api-stats-section');
|
||||
|
||||
if (statsSection) {
|
||||
observer.observe(statsSection);
|
||||
}
|
||||
|
||||
function handleMoreClick(e) {
|
||||
e.preventDefault();
|
||||
console.log('더보기 버튼 클릭');
|
||||
isExpanded = !isExpanded; // 상태 토글
|
||||
// API 검색 기능
|
||||
const searchInput = document.getElementById('apiSearchInput');
|
||||
const searchForm = document.querySelector('.search-form');
|
||||
const hashtags = document.querySelectorAll('.hashtag');
|
||||
|
||||
// 버튼 이미지/텍스트 변경
|
||||
const mobileMoreBtn = document.querySelector('.more_type.m-only .showmore img');
|
||||
const pcMoreBtn = document.querySelector('.more_type.pc-only .showmore img');
|
||||
if (mobileMoreBtn) {
|
||||
mobileMoreBtn.alt = isExpanded ? "접기 버튼" : "더보기 버튼";
|
||||
}
|
||||
if (pcMoreBtn) {
|
||||
pcMoreBtn.alt = isExpanded ? "접기 버튼" : "더보기 버튼";
|
||||
}
|
||||
|
||||
updateApiListVisibility();
|
||||
}
|
||||
|
||||
// API 리스트 표시 상태 업데이트
|
||||
function updateApiListVisibility() {
|
||||
const apiInfoBoxes = document.querySelectorAll('.api_info_box');
|
||||
const endIndex = isExpanded ? apiInfoBoxes.length : ITEMS_PER_PAGE;
|
||||
|
||||
console.log('업데이트 - API 목록:', {
|
||||
총개수: apiInfoBoxes.length,
|
||||
표시상태: isExpanded ? '전체표시' : '일부표시',
|
||||
표시할개수: endIndex
|
||||
});
|
||||
|
||||
apiInfoBoxes.forEach((box, index) => {
|
||||
box.style.display = index < endIndex ? 'block' : 'none';
|
||||
});
|
||||
}
|
||||
|
||||
// HTMX 로드 완료 이벤트 리스너
|
||||
document.body.addEventListener('htmx:afterSwap', function(evt) {
|
||||
if (evt.detail.target.id === 'api_spec_list') {
|
||||
console.log('HTMX 컨텐츠 로드됨 - 페이지 초기화');
|
||||
isExpanded = false;
|
||||
initMoreButton();
|
||||
}
|
||||
});
|
||||
|
||||
document.body.addEventListener('htmx:afterSettle', function(evt) {
|
||||
const apiListItems = document.querySelectorAll('.api_list');
|
||||
apiListItems.forEach(function(item) {
|
||||
item.removeEventListener('click',null);
|
||||
item.addEventListener('click', function() {
|
||||
const href = this.getAttribute('data-href');
|
||||
if (href) {
|
||||
window.location.href = href;
|
||||
}
|
||||
});
|
||||
});
|
||||
const apiItems = document.querySelectorAll('.api_info_box');
|
||||
apiItems.forEach(function(item) {
|
||||
item.removeEventListener('click',null);
|
||||
item.addEventListener('click', function() {
|
||||
const href = this.getAttribute('data-href');
|
||||
if (href) {
|
||||
window.location.href = href;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// 초기 실행
|
||||
console.log('초기 실행');
|
||||
initMoreButton();
|
||||
|
||||
// All 카테고리를 기본으로 active 설정
|
||||
document.querySelector('.keyword_list li:first-child a').classList.add('active');
|
||||
|
||||
const apiListItems = document.querySelectorAll('.api_list');
|
||||
apiListItems.forEach(function(item) {
|
||||
item.addEventListener('click', function() {
|
||||
const href = this.getAttribute('data-href');
|
||||
if (href) {
|
||||
window.location.href = href;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const apiItems = document.querySelectorAll('.api_info_box');
|
||||
apiItems.forEach(function(item) {
|
||||
item.removeEventListener('click',null);
|
||||
item.addEventListener('click', function() {
|
||||
const href = this.getAttribute('data-href');
|
||||
if (href) {
|
||||
window.location.href = href;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const hashtagItems = document.querySelectorAll('.hashtag ul li a');
|
||||
const searchBox = document.getElementById('search-box');
|
||||
|
||||
hashtagItems.forEach(function(item) {
|
||||
item.addEventListener('click', function(e) {
|
||||
// 해시태그 클릭 이벤트
|
||||
hashtags.forEach(tag => {
|
||||
tag.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
// Remove the # symbol if present and set the text in search box
|
||||
const searchText = this.textContent.replace('#', '').trim();
|
||||
searchBox.value = searchText;
|
||||
|
||||
document.getElementById("searchForm").submit();
|
||||
});
|
||||
});
|
||||
|
||||
const infoItems = document.querySelectorAll('.api_info ul li');
|
||||
infoItems.forEach(function (item) {
|
||||
item.style.cursor = 'pointer';
|
||||
item.addEventListener('click', function() {
|
||||
const link = this.querySelector('a');
|
||||
if (link) {
|
||||
location.href = link.getAttribute('href');
|
||||
const searchTerm = this.getAttribute('data-search');
|
||||
searchInput.value = searchTerm;
|
||||
// 폼 제출
|
||||
if (searchForm) {
|
||||
searchForm.submit();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
</th:block>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<!doctype html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
|
||||
|
||||
<aside layout:fragment="apiAside" class="lnb">
|
||||
<nav th:with="services=${@apiServiceService.searchApiGroupsForLnb()}">
|
||||
<ul class="lnb_list_type">
|
||||
<li>
|
||||
<a href="#none">공통안내</a>
|
||||
<ul class="lnb_list_nav">
|
||||
<li> <a th:href="@{/apis/common}">API 개발 공통</a></li>
|
||||
<li> <a th:href="@{/apis/KAPAP004U3}">가상계좌 응답 코드</a></li>
|
||||
<li> <a th:href="@{/apis/KAPAP004U4}">가상계좌 배치 설계</a></li>
|
||||
<li> <a th:href="@{/apis/KAPAP004U5}">가상계좌 VAN사 코드</a></li>
|
||||
<li> <a th:href="@{/apis/KAPAP004U6}">펌뱅킹 응답코드</a></li>
|
||||
<li> <a th:href="@{/apis/KAPAP004U7}">펌뱅킹 배치 설계</a></li>
|
||||
<li> <a th:href="@{/apis/KAPAP004U8}">대출금리 응답코드</a></li>
|
||||
<li> <a th:href="@{/apis/KAPAP004U9}">케이뱅크 페이 응답코드</a></li>
|
||||
<li> <a th:href="@{/apis/KAPAP004U10}">케이뱅크 페이 복합과세 예제</a></li>
|
||||
<li> <a th:href="@{/apis/token-spec}">케이뱅크 OAuth 2.0 토큰 발급</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li th:each="apiService : ${services}">
|
||||
<a href="#none" th:text="${apiService.groupName}">API Group Name</a>
|
||||
<ul class="lnb_list_nav">
|
||||
<li th:each="api : ${apiService.apiGroupApiList}">
|
||||
<a th:href="@{/apis/detail(id=${api.apiId})}" th:text="${api.apiDesc}">API Description</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</aside>
|
||||
@@ -0,0 +1,69 @@
|
||||
<!doctype html>
|
||||
<html xmlns:th="http://www.thymeleaf.org"
|
||||
>
|
||||
|
||||
<body>
|
||||
<footer th:fragment="footerFragment" class="global-footer">
|
||||
<div class="container">
|
||||
<div class="footer-top">
|
||||
<div class="footer-brand">
|
||||
<img src="/img/logo/logo.png" alt="광주은행" class="footer-logo">
|
||||
<p class="footer-desc">
|
||||
Wa bank와 함께 만드는 새로운 금융의 미래<br>
|
||||
개발자 여러분과 함께 성장합니다.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
<div class="footer-links">
|
||||
<div class="footer-column">
|
||||
<h4>제품</h4>
|
||||
<ul>
|
||||
<li><a href="#">API 카탈로그</a></li>
|
||||
<li><a href="#">SDK 다운로드</a></li>
|
||||
<li><a href="#">Playground</a></li>
|
||||
<li><a href="#">요금제</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer-column">
|
||||
<h4>개발자</h4>
|
||||
<ul>
|
||||
<li><a href="#">시작 가이드</a></li>
|
||||
<li><a href="#">API 문서</a></li>
|
||||
<li><a href="#">튜토리얼</a></li>
|
||||
<li><a href="#">샘플 코드</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer-column">
|
||||
<h4>지원</h4>
|
||||
<ul>
|
||||
<li><a href="#">도움말 센터</a></li>
|
||||
<li><a href="#">커뮤니티</a></li>
|
||||
<li><a href="#">기술 지원</a></li>
|
||||
<li><a href="#">시스템 상태</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer-column">
|
||||
<h4>회사</h4>
|
||||
<ul>
|
||||
<li><a href="#">광주은행 소개</a></li>
|
||||
<li><a href="#">뉴스룸</a></li>
|
||||
<li><a href="#">채용</a></li>
|
||||
<li><a href="#">제휴 문의</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-bottom">
|
||||
<div class="footer-legal">
|
||||
<p>© 2025 광주은행. All rights reserved.</p>
|
||||
<div class="legal-links">
|
||||
<a href="#">이용약관</a>
|
||||
<a href="#">개인정보처리방침</a>
|
||||
<a href="#">쿠키 정책</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,52 @@
|
||||
<!doctype html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
|
||||
|
||||
<head th:fragment="headFragment">
|
||||
<title th:text="#{title.html}">개발자 포털</title>
|
||||
|
||||
<meta content="https://www.eactive.co.kr/" property="og:url"/>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta content="max-age=0, public" http-equiv="Cache-Control"/>
|
||||
<meta content="index, follow" name="robots"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
|
||||
<meta http-equiv="Cache-Control" content="no-cache">
|
||||
<meta http-equiv="Pragma" content="no-cache">
|
||||
|
||||
<meta http-equiv="Expires" content="0">
|
||||
<link rel="stylesheet" type="text/css" th:href="@{/css/all.min.css}">
|
||||
<link rel="stylesheet" type="text/css" th:href="@{/css/main.css}">
|
||||
<link rel="stylesheet" type="text/css" th:href="@{/css/slick.css}">
|
||||
<link rel="stylesheet" type="text/css" th:href="@{/css/daterangepicker.css}">
|
||||
|
||||
<link rel="stylesheet" th:href="@{/plugins/codemirror/codemirror.css}" type="text/css"/>
|
||||
<link rel="stylesheet" th:href="@{/plugins/codemirror/theme/monokai.css}" type="text/css"/>
|
||||
<link rel="stylesheet" th:href="@{/plugins/summernote/summernote-lite.css}" type="text/css" />
|
||||
<link rel="stylesheet" th:href="@{/plugins/jquery-ui/jquery-ui.min.css}" />
|
||||
<link rel="icon" type="image/ico" th:href="@{/favicon_16px.png}">
|
||||
|
||||
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<script th:src="@{/plugins/jquery/jquery-3.7.1.min.js}"></script>
|
||||
<script th:src="@{/js/lodash.js}"></script>
|
||||
<script th:src="@{/js/common.js}"></script>
|
||||
<script th:src="@{/js/moment.min.js}"></script>
|
||||
<script th:src="@{/js/daterangepicker.js}"></script>
|
||||
<script th:src="@{/plugins/codemirror/codemirror.js}"></script>
|
||||
<script th:src="@{/plugins/codemirror/mode/clike.js}"></script>
|
||||
<script th:src="@{/plugins/codemirror/mode/javascript.js}"></script>
|
||||
<script th:src="@{/plugins/codemirror/addon/display/fullscreen.js}"></script>
|
||||
<script th:src="@{/plugins/codemirror/addon/display/placeholder.js}"></script>
|
||||
<script th:src="@{/plugins/summernote/summernote-lite.min.js}"></script>
|
||||
<script th:src="@{/plugins/summernote/summernote-cleaner.js}"></script>
|
||||
<script th:src="@{/plugins/jquery-ui/jquery-ui.min.js}"></script>
|
||||
<script th:src="@{/js/htmx.min.js}"></script>
|
||||
</head>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,135 @@
|
||||
<!doctype html>
|
||||
<html xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||
<body>
|
||||
<th:block th:fragment="headerFragment">
|
||||
<!-- Global Header Container -->
|
||||
<header class="global-header">
|
||||
<div class="container">
|
||||
<div class="header-content">
|
||||
|
||||
<!-- Desktop Header Layout -->
|
||||
<div class="desktop-header">
|
||||
<div class="header-left">
|
||||
<div class="logo-wrapper">
|
||||
<a th:href="@{/}" class="logo-link">
|
||||
<img src="/img/logo/logo.png" alt="광주은행" class="logo">
|
||||
</a>
|
||||
<a th:href="@{/}" class="logo-text">개발자 포털</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="header-center">
|
||||
<ul class="nav-menu">
|
||||
<li><a href="#docs" class="nav-link">서비스 소개</a></li>
|
||||
<li><a href="#api-market" class="nav-link">오픈 API</a></li>
|
||||
<li><a href="#playground" class="nav-link">고객지원</a></li>
|
||||
<li><a href="#community" class="nav-link">MY</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<div class="header-right">
|
||||
<button class="search-btn"><i class="fas fa-search"></i></button>
|
||||
<a th:href="@{/login}" class="login-btn">로그인</a>
|
||||
<a href="#signup" class="signup-btn">
|
||||
<span>회원 가입</span>
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Header Layout -->
|
||||
<div class="mobile-header">
|
||||
<div class="mobile-left">
|
||||
<a th:href="@{/}" class="mobile-logo-link">
|
||||
<img src="/img/logo/logo.png" alt="광주은행" class="mobile-logo">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="mobile-center">
|
||||
<h1 class="mobile-title">개발자 포털</h1>
|
||||
</div>
|
||||
|
||||
<div class="mobile-right">
|
||||
<button class="mobile-menu-btn" id="mobileMenuToggle">
|
||||
<span class="hamburger-line"></span>
|
||||
<span class="hamburger-line"></span>
|
||||
<span class="hamburger-line"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Mobile Drawer/Modal -->
|
||||
<div class="mobile-drawer" id="mobileDrawer">
|
||||
<div class="drawer-overlay" id="drawerOverlay"></div>
|
||||
<div class="drawer-content">
|
||||
<div class="drawer-header">
|
||||
<div class="drawer-logo">
|
||||
<a th:href="@{/}" class="drawer-logo-link">
|
||||
<img src="/img/logo/logo.png" alt="광주은행" class="logo">
|
||||
</a>
|
||||
<a th:href="@{/}" class="logo-text">개발자 포털</a>
|
||||
</div>
|
||||
<button class="drawer-close" id="drawerClose">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<nav class="drawer-nav">
|
||||
<ul class="drawer-menu">
|
||||
<li><a href="#docs" class="drawer-link">서비스 소개</a></li>
|
||||
<li><a href="#api-market" class="drawer-link">오픈 API</a></li>
|
||||
<li><a href="#playground" class="drawer-link">고객지원</a></li>
|
||||
<li><a href="#community" class="drawer-link">MY</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<div class="drawer-actions">
|
||||
<a th:href="@{/login}" class="drawer-login-btn">로그인</a>
|
||||
<a href="#signup" class="drawer-signup-btn">
|
||||
<span>회원 가입</span>
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
|
||||
<!-- Mobile Menu JavaScript -->
|
||||
<th:block th:fragment="headerScript">
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const menuToggle = document.getElementById('mobileMenuToggle');
|
||||
const drawer = document.getElementById('mobileDrawer');
|
||||
const drawerClose = document.getElementById('drawerClose');
|
||||
const drawerOverlay = document.getElementById('drawerOverlay');
|
||||
|
||||
function openDrawer() {
|
||||
drawer.classList.add('active');
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
|
||||
function closeDrawer() {
|
||||
drawer.classList.remove('active');
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
|
||||
menuToggle?.addEventListener('click', openDrawer);
|
||||
drawerClose?.addEventListener('click', closeDrawer);
|
||||
drawerOverlay?.addEventListener('click', closeDrawer);
|
||||
|
||||
// Close drawer when clicking on nav links
|
||||
document.querySelectorAll('.drawer-link').forEach(link => {
|
||||
link.addEventListener('click', closeDrawer);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</th:block>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,19 @@
|
||||
<!doctype html>
|
||||
<html xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div th:fragment="headerFragment" class="navigation" id="navigation">
|
||||
<ul class="navigation-area">
|
||||
<li th:each="crumb : ${breadcrumb}">
|
||||
<a th:href="${crumb.path}" class="navigation-button" th:text="${crumb.name}">Unknown Page</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,24 @@
|
||||
<!doctype html>
|
||||
<html xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<aside class="sidebar" th:fragment="menuFragment">
|
||||
|
||||
</aside>
|
||||
|
||||
<!-- menu script -->
|
||||
<th:block th:fragment="menuScript">
|
||||
<script th:inline="javascript">
|
||||
|
||||
$(function () {
|
||||
});
|
||||
</script>
|
||||
</th:block>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,74 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{layout/kjbank_base_layout}">
|
||||
<body>
|
||||
<section layout:fragment="contentFragment" class="content">
|
||||
<div class="content_wrap">
|
||||
<div class="sub_title2">
|
||||
<h2 class="title" th:classappend="${isTermsOfUse ? 'add3' : 'add4'}"
|
||||
th:text="${agreementTitle}">이용약관</h2>
|
||||
</div>
|
||||
<div class="inner cs2">
|
||||
<div class="tab-wrap">
|
||||
<div class="tabs">
|
||||
<ul class="tab_nav tab_bt">
|
||||
<li th:class="${isTermsOfUse ? 'active' : ''}">
|
||||
<a th:href="@{/agreements/terms(tab='terms')}">이용약관</a>
|
||||
</li>
|
||||
<li th:class="${isPrivacyPolicy ? 'active' : ''}">
|
||||
<a th:href="@{/agreements/terms(tab='privacy')}">개인정보처리방침</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab active" th:id="${isTermsOfUse ? 'tab1' : 'tab2'}">
|
||||
<div class="form_type">
|
||||
<div class="info1 ts_top">
|
||||
<div class="info_line ts_left">
|
||||
<div class="info_box1 info_add3 info_top">
|
||||
<span class="input">
|
||||
<form id="agreementForm" th:action="@{/agreements/terms}" method="get">
|
||||
<input type="hidden" name="tab"
|
||||
th:value="${currentTab}">
|
||||
<div class="custom_select" id="agreement_select">
|
||||
<div class="select_selected">
|
||||
시행일자 : <span th:text="${#temporals.format(selectedAgreement.publishedOn, 'yyyy.MM.dd')}"></span>
|
||||
</div>
|
||||
<ul class="common_selecttype select_items select_hide">
|
||||
<li th:each="agreement : ${agreementsList}"
|
||||
th:data-id="${#temporals.format(agreement.publishedOn, 'yyyy-MM-dd')}"
|
||||
th:text="'시행일자 : ' + ${#temporals.format(agreement.publishedOn, 'yyyy.MM.dd')}"
|
||||
th:class="${#temporals.format(agreement.publishedOn, 'yyyy-MM-dd') == selectedDate ? 'selected' : ''}">
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<input type="hidden" name="publishedOn" id="publishedOnInput">
|
||||
</form>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="terms_contents m_termst" th:utext="${selectedAgreement.contents}"
|
||||
style="white-space: pre-wrap; word-wrap: break-word;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<script layout:fragment="contentScript">
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const selects = document.getElementById('agreement_select');
|
||||
const form = document.getElementById('agreementForm');
|
||||
const publishedOnInput = document.getElementById('publishedOnInput');
|
||||
|
||||
createCustomSelect(selects, {
|
||||
onSelect: (item) => {
|
||||
publishedOnInput.value = item;
|
||||
form.submit();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,26 @@
|
||||
<!doctype html>
|
||||
<html xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
|
||||
|
||||
<head th:replace="fragment/kbank/head :: headFragment">
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<th:block th:replace="fragment/kjbank/header_container :: headerFragment"></th:block>
|
||||
<th:block th:replace="fragment/kjbank/header_container :: headerScript"></th:block>
|
||||
<div class="loading-overlay" style="display: none;">
|
||||
<div class="loading-spinner"></div>
|
||||
</div>
|
||||
<th:block layout:fragment="contentFragment">
|
||||
</th:block>
|
||||
|
||||
<th:block layout:fragment="contentScript">
|
||||
</th:block>
|
||||
|
||||
<footer th:replace="fragment/kjbank/footer :: footerFragment"></footer>
|
||||
<section th:replace="fragment/popup/customPopups :: customPopups"></section>
|
||||
<section layout:fragment="pagePopups"></section>
|
||||
<script th:src="@{/js/popup/custom-popups.js}"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,26 @@
|
||||
<!doctype html>
|
||||
<html xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
|
||||
|
||||
|
||||
<head th:replace="fragment/kjbank/head :: headFragment">
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- header -->
|
||||
<th:block th:replace="fragment/kjbank/header_container :: headerFragment"></th:block>
|
||||
<th:block th:replace="fragment/kjbank/header_container :: headerScript"></th:block>
|
||||
|
||||
<th:block layout:fragment="contentFragment">
|
||||
</th:block>
|
||||
|
||||
<th:block layout:fragment="contentScript">
|
||||
</th:block>
|
||||
|
||||
<footer th:replace="fragment/kjbank/footer :: footerFragment"></footer>
|
||||
|
||||
<section th:replace="fragment/popup/customPopups :: customPopups"></section>
|
||||
<script th:src="@{/js/popup/custom-popups.js}"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user