summaryrefslogtreecommitdiffci
diff refs
from: back
to: back
| flip
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build-and-deploy-prod.yml102
-rw-r--r--.github/workflows/build-and-deploy-stage.yml104
-rw-r--r--Dockerfile9
-rw-r--r--Jenkinsfile313
-rw-r--r--config/config.go6
-rw-r--r--config/config.prod.yaml8
-rw-r--r--deploy/playbook.yml9
-rw-r--r--internal/glightbox/html_renderer.go4
-rw-r--r--internal/router/handlers/api-v1-like-get.go2
-rw-r--r--internal/router/handlers/lang-blog-title.go6
-rw-r--r--internal/router/handlers/root.go7
-rw-r--r--internal/router/router.go2
-rw-r--r--internal/tailwind/transformer.go2
-rw-r--r--static/input.css92
-rw-r--r--views/layouts/general-page.html54
-rw-r--r--views/pages/blog-catalogue.html37
-rw-r--r--views/pages/blog-page.html26
-rw-r--r--views/pages/home-page.html19
-rw-r--r--views/pages/language-pick.html4
-rw-r--r--views/pages/user-page.html22
-rw-r--r--views/partials/blog-page-like-button.html6
-rw-r--r--views/partials/catalogue-blog-cards.html8
-rw-r--r--views/partials/general-page-header.html4
-rw-r--r--views/partials/personal-page-status.html2
24 files changed, 481 insertions, 367 deletions
diff --git a/.github/workflows/build-and-deploy-prod.yml b/.github/workflows/build-and-deploy-prod.yml
deleted file mode 100644
index 060ae32..0000000
--- a/.github/workflows/build-and-deploy-prod.yml
+++ /dev/null
@@ -1,102 +0,0 @@
-name: Docker image building and publishing onto Production
-on:
- push:
- tags:
- - "*"
-jobs:
- build-and-push:
- if: github.repository == 'SayaAndy/saya-today-web'
- runs-on: ubuntu-latest
- environment: Production
- permissions:
- packages: write
- steps:
- - name: Checkout
- uses: actions/checkout@v6
-
- - name: Generate output.css with tailwindcss
- uses: ZoeyVid/tailwindcss-update@main
- with:
- input: static/input.css
- output: static/output.css
- params: "--minify"
-
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v4
-
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v4
-
- - name: Login to GitHub Container Registry
- uses: docker/login-action@v4
- with:
- registry: ghcr.io
- username: ${{ github.repository_owner }}
- password: ${{ secrets.GHCR_TOKEN }}
-
- - name: Build and push
- uses: docker/build-push-action@v7
- with:
- context: .
- file: ./Dockerfile
- push: true
- cache-from: type=gha
- cache-to: type=gha,mode=max
- tags: |
- ghcr.io/sayaandy/saya-today-web:latest
- ghcr.io/sayaandy/saya-today-web:stable
- ghcr.io/sayaandy/saya-today-web:${{ github.ref_name }}
-
- deploy:
- if: github.repository == 'SayaAndy/saya-today-web'
- runs-on: ubuntu-latest
- environment: Production
- needs: [build-and-push]
- container:
- image: ghcr.io/ansible/community-ansible-dev-tools:v26.4.6
- options: --user root
- steps:
- - name: Checkout
- uses: actions/checkout@v6
-
- - name: Install community.docker collection
- run: ansible-galaxy collection install community.docker
-
- - name: Set up SSH connection for uz.saya.casa
- run: |
- mkdir -p ~/.ssh
- (cat <<EOF
- ${{ secrets.SVC_GITHUB_PK }}
- EOF
- ) > ~/.ssh/id_ed25519
- chmod 600 ~/.ssh/id_ed25519
- sed -i 's/\r$//' ~/.ssh/id_ed25519
- ssh-keyscan -H uz.saya.casa >> ~/.ssh/known_hosts
-
- - name: Test SSH connection
- run: |
- ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 svc_github@uz.saya.casa "echo 'SSH connection successful'"
-
- - name: Run Ansible playbook
- env:
- ANSIBLE_HOST_KEY_CHECKING: "False"
- working-directory: ./deploy
- run: |
- ansible-playbook \
- playbook.yml \
- -i inventory.yml \
- -l prod \
- --private-key ~/.ssh/id_ed25519 \
- -u svc_github \
- -e saya_today_web_auth_salt="${{ secrets.AUTH_SALT }}" \
- -e saya_today_web_s3_access_key_id="${{ secrets.S3_ACCESS_KEY_ID }}" \
- -e saya_today_web_s3_secret_access_key="${{ secrets.S3_SECRET_ACCESS_KEY }}" \
- -e saya_today_web_environment=prod \
- -e saya_today_web_tag=${{ github.ref_name }} \
- -e saya_today_web_mail_salt="${{ secrets.MAIL_SALT }}" \
- -e saya_today_web_mail_host="${{ secrets.MAIL_HOST }}" \
- -e saya_today_web_mail_address="${{ secrets.MAIL_ADDRESS }}" \
- -e saya_today_web_mail_username="${{ secrets.MAIL_USERNAME }}" \
- -e saya_today_web_mail_password="${{ secrets.MAIL_PASSWORD }}" \
- -e saya_today_google_site_verification="${{ secrets.GOOGLE_SITE_VERIFICATION }}" \
- -e saya_today_yandex_verification="${{ secrets.YANDEX_VERIFICATION }}"
diff --git a/.github/workflows/build-and-deploy-stage.yml b/.github/workflows/build-and-deploy-stage.yml
deleted file mode 100644
index ce4a1fb..0000000
--- a/.github/workflows/build-and-deploy-stage.yml
+++ /dev/null
@@ -1,104 +0,0 @@
-name: Docker image building and publishing onto Stage
-on:
- push:
- branches: [stage]
-jobs:
- build-and-push:
- if: github.repository == 'SayaAndy/saya-today-web'
- runs-on: ubuntu-latest
- environment: Stage
- permissions:
- packages: write
- outputs:
- sha_short: ${{ steps.ghss_vars.outputs.sha_short }}
- steps:
- - name: Checkout
- uses: actions/checkout@v6
-
- - name: Generate output.css with tailwindcss
- uses: ZoeyVid/tailwindcss-update@main
- with:
- input: static/input.css
- output: static/output.css
- params: "--minify"
-
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v4
-
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v4
-
- - name: Login to GitHub Container Registry
- uses: docker/login-action@v4
- with:
- registry: ghcr.io
- username: ${{ github.repository_owner }}
- password: ${{ secrets.GHCR_TOKEN }}
-
- - name: Set github short sha
- id: ghss_vars
- run: echo "sha_short=${GITHUB_SHA::7}" >> $GITHUB_OUTPUT
-
- - name: Build and push
- uses: docker/build-push-action@v7
- with:
- context: .
- file: ./Dockerfile
- push: true
- cache-from: type=gha
- cache-to: type=gha,mode=max
- tags: |
- ghcr.io/sayaandy/saya-today-web:latest
- ghcr.io/sayaandy/saya-today-web:commit-${{ steps.ghss_vars.outputs.sha_short }}
-
- deploy:
- if: github.repository == 'SayaAndy/saya-today-web'
- runs-on: ubuntu-latest
- environment: Stage
- needs: [build-and-push]
- container:
- image: ghcr.io/ansible/community-ansible-dev-tools:v26.4.6
- options: --user root
- steps:
- - name: Checkout
- uses: actions/checkout@v6
-
- - name: Install community.docker collection
- run: ansible-galaxy collection install community.docker
-
- - name: Set up SSH connection for uz.saya.casa
- run: |
- mkdir -p ~/.ssh
- (cat <<EOF
- ${{ secrets.SVC_GITHUB_PK }}
- EOF
- ) > ~/.ssh/id_ed25519
- chmod 600 ~/.ssh/id_ed25519
- sed -i 's/\r$//' ~/.ssh/id_ed25519
- ssh-keyscan -H uz.saya.casa >> ~/.ssh/known_hosts
-
- - name: Test SSH connection
- run: |
- ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_ed25519 svc_github@uz.saya.casa "echo 'SSH connection successful'"
-
- - name: Run Ansible playbook
- env:
- ANSIBLE_HOST_KEY_CHECKING: "False"
- working-directory: ./deploy
- run: |
- ansible-playbook \
- playbook.yml \
- -i inventory.yml \
- -l stage \
- --private-key ~/.ssh/id_ed25519 \
- -u svc_github \
- -e saya_today_web_auth_salt="${{ secrets.AUTH_SALT }}" \
- -e saya_today_web_s3_access_key_id="${{ secrets.S3_ACCESS_KEY_ID }}" \
- -e saya_today_web_s3_secret_access_key="${{ secrets.S3_SECRET_ACCESS_KEY }}" \
- -e saya_today_web_environment=stage \
- -e saya_today_web_tag=commit-${{ needs.build-and-push.outputs.sha_short }} \
- -e saya_today_web_mail_salt="${{ secrets.MAIL_SALT }}" \
- -e saya_today_web_mail_host="${{ secrets.MAIL_HOST }}" \
- -e saya_today_web_mail_address="${{ secrets.MAIL_ADDRESS }}" \
- -e saya_today_web_mail_username="${{ secrets.MAIL_USERNAME }}" \
- -e saya_today_web_mail_password="${{ secrets.MAIL_PASSWORD }}"
diff --git a/Dockerfile b/Dockerfile
index 44d1ea2..d0b6621 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,9 @@
-FROM golang:1.26-alpine3.23 AS build-stage
+FROM golang:1.26.4-alpine3.24 AS build-stage
+
+ARG TARGETOS=linux
+ARG TARGETARCH=amd64
+ENV GOOS=${TARGETOS}
+ENV GOARCH=${TARGETARCH}
RUN apk add --no-cache sqlite-dev musl-dev gcc
@@ -7,7 +12,7 @@ COPY . .
RUN go mod download
RUN CGO_ENABLED=1 go build -o sayana-web .
-FROM alpine:3.23 AS runtime-stage
+FROM alpine:3.24 AS runtime-stage
ENV ENVIRONMENT=""
ENV AUTH_SALT=""
diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 0000000..8633145
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,313 @@
+pipeline {
+ agent none
+
+ stages {
+ stage('Compile Tailwind CSS') {
+ agent {
+ docker {
+ image 'node:26.3.1-alpine3.24'
+ args '-v /tmp:/tmp -v /.npm:/.npm'
+ }
+ }
+ steps {
+ checkout scm
+ sh '''
+ npm install tailwindcss @tailwindcss/cli @tailwindcss/forms
+ npx tailwindcss -i static/input.css -o static/output.css --minify
+ '''
+ stash name: 'tailwindcss-output', includes: 'static/output.css'
+ }
+ }
+
+ stage('Matrix Build') {
+ matrix {
+ axes {
+ axis {
+ name 'GOOS'
+ values 'linux'
+ }
+ axis {
+ name 'GOARCH'
+ values 'arm64', 'amd64'
+ }
+ }
+ stages {
+ stage('Build') {
+ agent {
+ kubernetes {
+ defaultContainer 'kaniko'
+ yaml """
+apiVersion: v1
+kind: Pod
+metadata:
+ namespace: jenkins
+spec:
+ nodeSelector:
+ kubernetes.io/arch: ${GOARCH}
+ containers:
+ - name: kaniko
+ image: gcr.io/kaniko-project/executor:v1.24.0-debug
+ imagePullPolicy: Always
+ command: [ /busybox/cat ]
+ tty: true
+ resources:
+ requests:
+ cpu: "1"
+ memory: 2Gi
+ ephemeral-storage: 4Gi
+ limits:
+ memory: 4Gi
+ ephemeral-storage: 8Gi
+"""
+ }
+ }
+ environment {
+ IMAGE_PUSH_DESTINATION="registry.sayag.it/sayauz/web"
+ }
+ steps {
+ checkout scm
+ unstash 'tailwindcss-output'
+ container(name: 'kaniko', shell: '/busybox/sh') {
+ withCredentials([string(credentialsId: 'registry-sayagit-jenkins-password', variable: 'REGISTRY_SAYAGIT_JENKINS_PASSWORD')]) {
+ withEnv(['PATH+EXTRA=/busybox']) {
+ script {
+ env.GIT_COMMIT_SHORT = env.GIT_COMMIT ? env.GIT_COMMIT.take(7) : "unknown"
+ try {
+ sh '''#!/busybox/sh
+ mkdir -p /kaniko/.docker
+ printf '{"auths":{"registry.sayag.it":{"username":"jenkins","password":"%s"}}}' "$REGISTRY_SAYAGIT_JENKINS_PASSWORD" > /kaniko/.docker/config.json
+ /kaniko/executor --context `pwd` \
+ --custom-platform=linux/${GOARCH} \
+ --build-arg TARGETOS=linux \
+ --build-arg TARGETARCH=${GOARCH} \
+ --destination $IMAGE_PUSH_DESTINATION:commit-$GIT_COMMIT_SHORT-$GOARCH
+ '''
+ } catch (Exception e) {
+ echo "Caught exception: ${e.getMessage()}"
+ currentBuild.result = 'FAILURE'
+ throw e
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ stage('Stitch Manifest') {
+ agent {
+ kubernetes {
+ defaultContainer 'manifest-tool'
+ yaml """
+apiVersion: v1
+kind: Pod
+metadata:
+ namespace: jenkins
+spec:
+ containers:
+ - name: manifest-tool
+ image: mplatform/manifest-tool:alpine-v2.2.2
+ imagePullPolicy: Always
+ command: [ 'cat' ]
+ tty: true
+ resources:
+ requests:
+ cpu: "1"
+ memory: 2Gi
+ ephemeral-storage: 4Gi
+"""
+ }
+ }
+ environment {
+ IMAGE_PUSH_DESTINATION="registry.sayag.it/sayauz/web"
+ }
+ steps {
+ script {
+ env.GIT_COMMIT_SHORT = env.GIT_COMMIT ? env.GIT_COMMIT.take(7) : "unknown"
+ }
+ withCredentials([string(credentialsId: 'registry-sayagit-jenkins-password', variable: 'REGISTRY_SAYAGIT_JENKINS_PASSWORD')]) {
+ sh '''mkdir -p /root/.docker
+ printf '{"auths":{"registry.sayag.it":{"username":"jenkins","password":"%s"}}}' "$REGISTRY_SAYAGIT_JENKINS_PASSWORD" > /root/.docker/config.json
+
+ manifest-tool push from-args \
+ --platforms linux/amd64,linux/arm64 \
+ --template $IMAGE_PUSH_DESTINATION:commit-$GIT_COMMIT_SHORT-ARCH \
+ --target $IMAGE_PUSH_DESTINATION:commit-$GIT_COMMIT_SHORT
+ manifest-tool push from-args \
+ --platforms linux/amd64,linux/arm64 \
+ --template $IMAGE_PUSH_DESTINATION:commit-$GIT_COMMIT_SHORT-ARCH \
+ --target $IMAGE_PUSH_DESTINATION:latest
+ if [ "$TAG_NAME" != "" ]; then
+ manifest-tool push from-args \
+ --platforms linux/amd64,linux/arm64 \
+ --template $IMAGE_PUSH_DESTINATION:commit-$GIT_COMMIT_SHORT-ARCH \
+ --target $IMAGE_PUSH_DESTINATION:stable
+ manifest-tool push from-args \
+ --platforms linux/amd64,linux/arm64 \
+ --template $IMAGE_PUSH_DESTINATION:commit-$GIT_COMMIT_SHORT-ARCH \
+ --target $IMAGE_PUSH_DESTINATION:$TAG_NAME
+ fi
+ '''
+ }
+ }
+ }
+ stage('Deploy (Stage)') {
+ when { branch 'stage' }
+ agent {
+ kubernetes {
+ defaultContainer 'ansible'
+ yaml """
+apiVersion: v1
+kind: Pod
+metadata:
+ namespace: jenkins
+spec:
+ containers:
+ - name: ansible
+ image: ghcr.io/ansible/community-ansible-dev-tools:v26.7.2
+ command: [ 'cat' ]
+ tty: true
+ resources:
+ requests:
+ cpu: "500m"
+ memory: 1Gi
+"""
+ }
+ }
+ steps {
+ checkout scm
+ container('ansible') {
+ script {
+ env.GIT_COMMIT_SHORT = env.GIT_COMMIT ? env.GIT_COMMIT.take(7) : "unknown"
+
+ def secretVars = [
+ 'sayauz-web-stage-auth-salt' : 'AUTH_SALT',
+ 'sayauz-web-stage-s3-access-key-id' : 'S3_ACCESS_KEY_ID',
+ 'sayauz-web-stage-s3-secret-access-key' : 'S3_SECRET_ACCESS_KEY',
+ 'sayauz-web-stage-mail-salt' : 'MAIL_SALT',
+ 'sayauz-web-stage-mail-host' : 'MAIL_HOST',
+ 'sayauz-web-stage-mail-address' : 'MAIL_ADDRESS',
+ 'sayauz-web-stage-mail-username' : 'MAIL_USERNAME',
+ 'sayauz-web-stage-mail-password' : 'MAIL_PASSWORD'
+ ]
+ def bindings = secretVars.collect { id, varName -> string(credentialsId: id, variable: varName) }
+ bindings << sshUserPrivateKey(credentialsId: 'sayauz-svc-github', keyFileVariable: 'SSH_KEY_FILE', usernameVariable: 'SSH_USER')
+
+ withCredentials(bindings) {
+ sh '''
+ ansible-galaxy collection install community.docker
+
+ mkdir -p ~/.ssh
+ cp "$SSH_KEY_FILE" ~/.ssh/id_ed25519
+ chmod 600 ~/.ssh/id_ed25519
+ ssh-keyscan -H uz.saya.casa >> ~/.ssh/known_hosts
+
+ ssh -o ConnectTimeout=10 -i ~/.ssh/id_ed25519 "$SSH_USER@uz.saya.casa" "echo 'SSH connection successful'"
+
+ cd deploy
+ ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook \
+ playbook.yml \
+ -i inventory.yml \
+ -l stage \
+ --private-key ~/.ssh/id_ed25519 \
+ -u "$SSH_USER" \
+ -e saya_today_web_auth_salt="$AUTH_SALT" \
+ -e saya_today_web_s3_access_key_id="$S3_ACCESS_KEY_ID" \
+ -e saya_today_web_s3_secret_access_key="$S3_SECRET_ACCESS_KEY" \
+ -e saya_today_web_environment=stage \
+ -e saya_today_web_tag=commit-$GIT_COMMIT_SHORT \
+ -e saya_today_web_mail_salt="$MAIL_SALT" \
+ -e saya_today_web_mail_host="$MAIL_HOST" \
+ -e saya_today_web_mail_address="$MAIL_ADDRESS" \
+ -e saya_today_web_mail_username="$MAIL_USERNAME" \
+ -e saya_today_web_mail_password="$MAIL_PASSWORD"
+ '''
+ }
+ }
+ }
+ }
+ }
+ stage('Deploy (Prod)') {
+ when { buildingTag() }
+ agent {
+ kubernetes {
+ defaultContainer 'ansible'
+ yaml """
+apiVersion: v1
+kind: Pod
+metadata:
+ namespace: jenkins
+spec:
+ containers:
+ - name: ansible
+ image: ghcr.io/ansible/community-ansible-dev-tools:v26.7.2
+ command: [ 'cat' ]
+ tty: true
+ resources:
+ requests:
+ cpu: "500m"
+ memory: 1Gi
+"""
+ }
+ }
+ steps {
+ checkout scm
+ container('ansible') {
+ script {
+ def secretVars = [
+ 'sayauz-web-prod-auth-salt' : 'AUTH_SALT',
+ 'sayauz-web-prod-s3-access-key-id' : 'S3_ACCESS_KEY_ID',
+ 'sayauz-web-prod-s3-secret-access-key' : 'S3_SECRET_ACCESS_KEY',
+ 'sayauz-web-prod-mail-salt' : 'MAIL_SALT',
+ 'sayauz-web-prod-mail-host' : 'MAIL_HOST',
+ 'sayauz-web-prod-mail-address' : 'MAIL_ADDRESS',
+ 'sayauz-web-prod-mail-username' : 'MAIL_USERNAME',
+ 'sayauz-web-prod-mail-password' : 'MAIL_PASSWORD',
+ 'sayauz-web-prod-verification-google' : 'GOOGLE_VERIFICATION',
+ 'sayauz-web-prod-verification-yandex' : 'YANDEX_VERIFICATION',
+ 'sayauz-web-prod-verification-bing' : 'BING_VERIFICATION'
+ ]
+ def bindings = secretVars.collect { id, varName -> string(credentialsId: id, variable: varName) }
+ bindings << sshUserPrivateKey(credentialsId: 'sayauz-svc-github', keyFileVariable: 'SSH_KEY_FILE', usernameVariable: 'SSH_USER')
+
+ withCredentials(bindings) {
+ sh '''
+ ansible-galaxy collection install community.docker
+
+ mkdir -p ~/.ssh
+ cp "$SSH_KEY_FILE" ~/.ssh/id_ed25519
+ chmod 600 ~/.ssh/id_ed25519
+ ssh-keyscan -H uz.saya.casa >> ~/.ssh/known_hosts
+
+ ssh -o ConnectTimeout=10 -i ~/.ssh/id_ed25519 "$SSH_USER@uz.saya.casa" "echo 'SSH connection successful'"
+
+ cd deploy
+ ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook \
+ playbook.yml \
+ -i inventory.yml \
+ -l prod \
+ --private-key ~/.ssh/id_ed25519 \
+ -u "$SSH_USER" \
+ -e saya_today_web_auth_salt="$AUTH_SALT" \
+ -e saya_today_web_s3_access_key_id="$S3_ACCESS_KEY_ID" \
+ -e saya_today_web_s3_secret_access_key="$S3_SECRET_ACCESS_KEY" \
+ -e saya_today_web_environment=prod \
+ -e saya_today_web_tag=$TAG_NAME \
+ -e saya_today_web_mail_salt="$MAIL_SALT" \
+ -e saya_today_web_mail_host="$MAIL_HOST" \
+ -e saya_today_web_mail_address="$MAIL_ADDRESS" \
+ -e saya_today_web_mail_username="$MAIL_USERNAME" \
+ -e saya_today_web_mail_password="$MAIL_PASSWORD" \
+ -e saya_today_google_verification="$GOOGLE_VERIFICATION" \
+ -e saya_today_yandex_verification="$YANDEX_VERIFICATION" \
+ -e saya_today_bing_verification="$BING_VERIFICATION"
+ '''
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/config/config.go b/config/config.go
index 8ab1bfc..9185e6a 100644
--- a/config/config.go
+++ b/config/config.go
@@ -20,7 +20,7 @@ type Config struct {
Auth AuthConfig `json:"Auth" yaml:"auth" validate:"required"`
Mail MailConfig `json:"Mail" yaml:"mail" validate:"required"`
CanonicalEndpoint string `json:"CanonicalEndpoint" yaml:"canonicalEndpoint" validate:"required"`
- Meta MetaConfig `json:"Meta" yaml:"meta"`
+ Meta []MetaConfig `json:"Meta" yaml:"meta"`
PhotoStorage PhotoStorageConfig `json:"PhotoStorage" yaml:"photoStorage"`
StaticStorage StaticStorageConfig `json:"StaticStorage" yaml:"staticStorage" validate:"required"`
AllowOrigins []string `json:"AllowOrigins" yaml:"allowOrigins"`
@@ -237,8 +237,8 @@ type TriggerConfig struct {
}
type MetaConfig struct {
- GoogleSiteVerification string `json:"GoogleSiteVerification" yaml:"googleSiteVerification"`
- YandexVerification string `json:"YandexVerification" yaml:"yandexVerification"`
+ Name string `json:"Name" yaml:"name"`
+ Value string `json:"Value" yaml:"value"`
}
type PhotoStorageConfig struct {
diff --git a/config/config.prod.yaml b/config/config.prod.yaml
index ce0941d..6ec00d8 100644
--- a/config/config.prod.yaml
+++ b/config/config.prod.yaml
@@ -55,8 +55,12 @@ mail:
onNewPost: "0/5 * * * *"
canonicalEndpoint: "https://${FQDN}"
meta:
- googleSiteVerification: "${GOOGLE_SITE_VERIFICATION}"
- yandexVerification: "${YANDEX_VERIFICATION}"
+ - name: google-site-verification
+ value: "${GOOGLE_SITE_VERIFICATION}"
+ - name: yandex-verification
+ value: "${YANDEX_VERIFICATION}"
+ - name: msvalidate.01
+ value: "${BING_VERIFICATION}"
photoStorage:
full:
baseUrl: https://cdn.saya.uz/photos/jpeg-full/%s
diff --git a/deploy/playbook.yml b/deploy/playbook.yml
index ae3e936..057cc19 100644
--- a/deploy/playbook.yml
+++ b/deploy/playbook.yml
@@ -6,7 +6,7 @@
vars:
docker_volumes:
- "{{ saya_today_web_name }}-volume:/data:rw"
-
+
tasks:
- name: Initialize Unix socket volume
when: >-
@@ -26,11 +26,11 @@
community.docker.docker_volume:
name: "{{ saya_today_web_name }}-volume"
- - name: Deploy saya-today-web Docker Container
+ - name: Deploy sayauz/web Docker Container
community.docker.docker_container:
name: "{{ saya_today_web_name }}"
hostname: "{{ saya_today_web_hostname }}"
- image: "ghcr.io/sayaandy/saya-today-web:{{ saya_today_web_tag }}"
+ image: "registry.sayag.it/sayauz/web:{{ saya_today_web_tag }}"
env:
S3_ACCESS_KEY_ID: "{{ saya_today_web_s3_access_key_id }}"
S3_SECRET_ACCESS_KEY: "{{ saya_today_web_s3_secret_access_key }}"
@@ -42,8 +42,9 @@
MAIL_PASSWORD: "{{ saya_today_web_mail_password }}"
MAIL_SALT: "{{ saya_today_web_mail_salt }}"
FQDN: "{{ saya_today_web_listen_address }}"
- GOOGLE_SITE_VERIFICATION: "{{ saya_today_google_site_verification | default('') }}"
+ GOOGLE_VERIFICATION: "{{ saya_today_google_verification | default('') }}"
YANDEX_VERIFICATION: "{{ saya_today_yandex_verification | default('') }}"
+ BING_VERIFICATION: "{{ saya_today_bing_verification | default('') }}"
network_mode: caddy
networks:
- name: caddy
diff --git a/internal/glightbox/html_renderer.go b/internal/glightbox/html_renderer.go
index b2cd855..1bb606b 100644
--- a/internal/glightbox/html_renderer.go
+++ b/internal/glightbox/html_renderer.go
@@ -151,12 +151,12 @@ func (r *GLightboxHTMLRenderer) renderGLightbox(w util.BufWriter, source []byte,
w.WriteString(strings.ReplaceAll(`
<div class="items-center flex flex-col">
- <hr class="border-t-3 border-dotted border-main-hard mt-1 mb-2 w-[80%] ml-auto mr-auto">
+ <hr class="border-t-[0.375rem] border-dotted border-main-hard my-2 w-24 ml-auto mr-auto">
<div class="grid masonry-grid-{id}">
<div class="grid-sizer grid-sizer-{id}"></div>
`+strings.Join(elements, "\n")+`
</div>
- <hr class="border-t-3 border-dotted border-main-hard mt-1 mb-2 w-[80%] ml-auto mr-auto">
+ <hr class="border-t-[0.375rem] border-dotted border-main-hard my-2 w-24 ml-auto mr-auto">
</div>
<script>
diff --git a/internal/router/handlers/api-v1-like-get.go b/internal/router/handlers/api-v1-like-get.go
index 0eaf5f6..9e2c856 100644
--- a/internal/router/handlers/api-v1-like-get.go
+++ b/internal/router/handlers/api-v1-like-get.go
@@ -42,7 +42,7 @@ func (r *GetLikeHandler) Render(c *fiber.Ctx, supplements *router.Supplements, l
return fiber.StatusBadRequest, fmt.Errorf("error getting path from referer: %w", err)
}
- if len(pathParts) != 3 && pathParts[1] != "blog" {
+ if len(pathParts) != 3 || pathParts[1] != "blog" {
return fiber.StatusBadRequest, fmt.Errorf("invalid path format: expected '/:lang/blog/:page', got '%s'", path)
}
diff --git a/internal/router/handlers/lang-blog-title.go b/internal/router/handlers/lang-blog-title.go
index 5a1155d..76dc335 100644
--- a/internal/router/handlers/lang-blog-title.go
+++ b/internal/router/handlers/lang-blog-title.go
@@ -156,7 +156,13 @@ func (r *BlogPageHandler) RenderHeader(c *fiber.Ctx, supplements *router.Supplem
return fiber.StatusNotFound, fmt.Errorf("could not read '%s' for metadata: %w", path, err)
}
+ pageTitle := metadata.Title
+ if metadata.Medley != "" {
+ pageTitle += " // " + l10n.T.GetPath(lang, "Medleys", metadata.Medley).(string)
+ }
+
templateMap["Title"] = metadata.Title
+ templateMap["PageTitle"] = pageTitle
return fiber.StatusOK, nil
}
diff --git a/internal/router/handlers/root.go b/internal/router/handlers/root.go
index 6a011e4..4fc4e31 100644
--- a/internal/router/handlers/root.go
+++ b/internal/router/handlers/root.go
@@ -47,11 +47,8 @@ func (r *RootHandler) AddMeta(c *fiber.Ctx, supplements *router.Supplements, lan
{Property: "og:url", Content: fmt.Sprint(templateMap["CanonicalEndpoint"]) + "/"},
{Property: "og:type", Content: "website"},
}
- if supplements.Meta.GoogleSiteVerification != "" {
- meta = append(meta, router.MetaField{Name: "google-site-verification", Content: supplements.Meta.GoogleSiteVerification})
- }
- if supplements.Meta.YandexVerification != "" {
- meta = append(meta, router.MetaField{Name: "yandex-verification", Content: supplements.Meta.YandexVerification})
+ for _, field := range supplements.Meta {
+ meta = append(meta, router.MetaField{Name: field.Name, Content: field.Value})
}
return meta, nil
}
diff --git a/internal/router/router.go b/internal/router/router.go
index c8b5686..a11a934 100644
--- a/internal/router/router.go
+++ b/internal/router/router.go
@@ -102,7 +102,7 @@ type Supplements struct {
BlogTrigger *blogtrigger.BlogTriggerScheduler
TemplateManager *templatemanager.TemplateManager
MarkdownRenderer goldmark.Markdown
- Meta config.MetaConfig
+ Meta []config.MetaConfig
PhotoStorage config.PhotoStorageConfig
StaticStorage config.StaticStorageConfig
}
diff --git a/internal/tailwind/transformer.go b/internal/tailwind/transformer.go
index c9da9df..f90489f 100644
--- a/internal/tailwind/transformer.go
+++ b/internal/tailwind/transformer.go
@@ -45,7 +45,7 @@ func (t *TailwindTransformer) Transform(node *ast.Document, reader text.Reader,
node.SetAttribute([]byte("class"), []byte("text-base/[2] font-gentium tracking-[.0125rem]"))
case *ast.Blockquote:
- node.SetAttribute([]byte("class"), []byte("border-l-2 border-main-medium bg-paper bg-background-dark p-1 mb-2 italic font-thin"))
+ node.SetAttribute([]byte("class"), []byte("border-l-[0.125rem] border-main-medium bg-paper bg-background-dark p-1 mb-2 italic font-thin"))
case *ast.CodeSpan:
node.SetAttribute([]byte("class"), []byte("bg-paper bg-background-dark"))
diff --git a/static/input.css b/static/input.css
index 7ccf7af..e0c5c81 100644
--- a/static/input.css
+++ b/static/input.css
@@ -22,24 +22,38 @@
--color-main-dark-hard: var(--color-main-dark-hard);
--color-main-dark-medium: var(--color-main-dark-medium);
--color-main-dark-soft: var(--color-main-dark-soft);
- --shadow-elevation-flat: 0px 1px 1px 0px rgba(0, 0, 0, 0.2);
+ --shadow-elevation-flat: 0px 0.0625rem 0.0625rem 0px rgba(0, 0, 0, 0.2);
+ --inset-shadow-elevation-flat: inset 0px 0.0625rem 0.125rem 0px rgba(0, 0, 0, 0.15);
--shadow-elevation-0: 0px 0px 0px 0px rgba(0, 0, 0, 0.2), 0px 0px 0px 0px rgba(0, 0, 0, 0.14), 0px 0px 0px 0px rgba(0, 0, 0, 0.12);
- --shadow-elevation-1: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12);
- --shadow-elevation-2: 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12);
- --shadow-elevation-3: 0px 3px 3px -2px rgba(0, 0, 0, 0.2), 0px 3px 4px 0px rgba(0, 0, 0, 0.14), 0px 1px 8px 0px rgba(0, 0, 0, 0.12);
- --shadow-elevation-4: 0px 2px 4px -1px rgba(0, 0, 0, 0.2), 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 1px 10px 0px rgba(0, 0, 0, 0.12);
- --shadow-elevation-5: 0px 3px 5px -1px rgba(0, 0, 0, 0.2), 0px 5px 8px 0px rgba(0, 0, 0, 0.14), 0px 1px 14px 0px rgba(0, 0, 0, 0.12);
- --shadow-elevation-6: 0px 3px 5px -1px rgba(0, 0, 0, 0.2), 0px 6px 10px 0px rgba(0, 0, 0, 0.14), 0px 1px 18px 0px rgba(0, 0, 0, 0.12);
- --shadow-elevation-7: 0px 4px 5px -2px rgba(0, 0, 0, 0.2), 0px 7px 10px 1px rgba(0, 0, 0, 0.14), 0px 2px 16px 1px rgba(0, 0, 0, 0.12);
- --shadow-elevation-8: 0px 5px 5px -3px rgba(0, 0, 0, 0.2), 0px 8px 10px 1px rgba(0, 0, 0, 0.14), 0px 3px 14px 2px rgba(0, 0, 0, 0.12);
- --shadow-elevation-9: 0px 5px 6px -3px rgba(0, 0, 0, 0.2), 0px 9px 12px 1px rgba(0, 0, 0, 0.14), 0px 3px 16px 2px rgba(0, 0, 0, 0.12);
- --shadow-elevation-10: 0px 6px 6px -3px rgba(0, 0, 0, 0.2), 0px 10px 14px 1px rgba(0, 0, 0, 0.14), 0px 4px 18px 3px rgba(0, 0, 0, 0.12);
- --shadow-elevation-11: 0px 6px 7px -4px rgba(0, 0, 0, 0.2), 0px 11px 15px 1px rgba(0, 0, 0, 0.14), 0px 4px 20px 3px rgba(0, 0, 0, 0.12);
- --shadow-elevation-12: 0px 7px 8px -4px rgba(0, 0, 0, 0.2), 0px 12px 17px 2px rgba(0, 0, 0, 0.14), 0px 5px 22px 4px rgba(0, 0, 0, 0.12);
+ --inset-shadow-elevation-0: inset 0px 0px 0px 0px rgba(0, 0, 0, 0);
+ --shadow-elevation-1: 0px 0.125rem 0.0625rem -0.0625rem rgba(0, 0, 0, 0.2), 0px 0.0625rem 0.0625rem 0px rgba(0, 0, 0, 0.14), 0px 0.0625rem 0.1875rem 0px rgba(0, 0, 0, 0.12);
+ --inset-shadow-elevation-1: inset 0px 0.125rem 0.25rem 0px rgba(0, 0, 0, 0.2);
+ --shadow-elevation-2: 0px 0.1875rem 0.0625rem -0.125rem rgba(0, 0, 0, 0.2), 0px 0.125rem 0.125rem 0px rgba(0, 0, 0, 0.14), 0px 0.0625rem 0.3125rem 0px rgba(0, 0, 0, 0.12);
+ --inset-shadow-elevation-2: inset 0px 0.1875rem 0.375rem 0px rgba(0, 0, 0, 0.22);
+ --shadow-elevation-3: 0px 0.1875rem 0.1875rem -0.125rem rgba(0, 0, 0, 0.2), 0px 0.1875rem 0.25rem 0px rgba(0, 0, 0, 0.14), 0px 0.0625rem 0.5rem 0px rgba(0, 0, 0, 0.12);
+ --inset-shadow-elevation-3: inset 0px 0.25rem 0.5rem 0px rgba(0, 0, 0, 0.25);
+ --shadow-elevation-4: 0px 0.125rem 0.25rem -0.0625rem rgba(0, 0, 0, 0.2), 0px 0.25rem 0.3125rem 0px rgba(0, 0, 0, 0.14), 0px 0.0625rem 0.625rem 0px rgba(0, 0, 0, 0.12);
+ --inset-shadow-elevation-4: inset 0px 0.3125rem 0.625rem 0px rgba(0, 0, 0, 0.27);
+ --shadow-elevation-5: 0px 0.1875rem 0.3125rem -0.0625rem rgba(0, 0, 0, 0.2), 0px 0.3125rem 0.5rem 0px rgba(0, 0, 0, 0.14), 0px 0.0625rem 0.875rem 0px rgba(0, 0, 0, 0.12);
+ --inset-shadow-elevation-5: inset 0px 0.375rem 0.75rem 0px rgba(0, 0, 0, 0.3);
+ --shadow-elevation-6: 0px 0.1875rem 0.3125rem -0.0625rem rgba(0, 0, 0, 0.2), 0px 0.375rem 0.625rem 0px rgba(0, 0, 0, 0.14), 0px 0.0625rem 1.125rem 0px rgba(0, 0, 0, 0.12);
+ --inset-shadow-elevation-6: inset 0px 0.4375rem 0.875rem 0px rgba(0, 0, 0, 0.32);
+ --shadow-elevation-7: 0px 0.25rem 0.3125rem -0.125rem rgba(0, 0, 0, 0.2), 0px 0.4375rem 0.625rem 0.0625rem rgba(0, 0, 0, 0.14), 0px 0.125rem 1rem 0.0625rem rgba(0, 0, 0, 0.12);
+ --inset-shadow-elevation-7: inset 0px 0.5rem 1rem 0px rgba(0, 0, 0, 0.35);
+ --shadow-elevation-8: 0px 0.3125rem 0.3125rem -0.1875rem rgba(0, 0, 0, 0.2), 0px 0.5rem 0.625rem 0.0625rem rgba(0, 0, 0, 0.14), 0px 0.1875rem 0.875rem 0.125rem rgba(0, 0, 0, 0.12);
+ --inset-shadow-elevation-8: inset 0px 0.5625rem 1.125rem 0px rgba(0, 0, 0, 0.37);
+ --shadow-elevation-9: 0px 0.3125rem 0.375rem -0.1875rem rgba(0, 0, 0, 0.2), 0px 0.5625rem 0.75rem 0.0625rem rgba(0, 0, 0, 0.14), 0px 0.1875rem 1rem 0.125rem rgba(0, 0, 0, 0.12);
+ --inset-shadow-elevation-9: inset 0px 0.625rem 1.25rem 0px rgba(0, 0, 0, 0.4);
+ --shadow-elevation-10: 0px 0.375rem 0.375rem -0.1875rem rgba(0, 0, 0, 0.2), 0px 0.625rem 0.875rem 0.0625rem rgba(0, 0, 0, 0.14), 0px 0.25rem 1.125rem 0.1875rem rgba(0, 0, 0, 0.12);
+ --inset-shadow-elevation-10: inset 0px 0.6875rem 1.375rem 0px rgba(0, 0, 0, 0.42);
+ --shadow-elevation-11: 0px 0.375rem 0.4375rem -0.25rem rgba(0, 0, 0, 0.2), 0px 0.6875rem 0.9375rem 0.0625rem rgba(0, 0, 0, 0.14), 0px 0.25rem 1.25rem 0.1875rem rgba(0, 0, 0, 0.12);
+ --inset-shadow-elevation-11: inset 0px 0.75rem 1.5rem 0px rgba(0, 0, 0, 0.45);
+ --shadow-elevation-12: 0px 0.4375rem 0.5rem -0.25rem rgba(0, 0, 0, 0.2), 0px 0.75rem 1.0625rem 0.125rem rgba(0, 0, 0, 0.14), 0px 0.3125rem 1.375rem 0.25rem rgba(0, 0, 0, 0.12);
+ --inset-shadow-elevation-12: inset 0px 0.8125rem 1.625rem 0px rgba(0, 0, 0, 0.47);
}
html {
- font-size: 12px;
+ font-size: clamp(11px, min(1dvw, 1dvh) + 7.6px, 16px);
--crossed-out: url("data:image/svg+xml,<svg id='patternId' width='100%' height='100%' xmlns='http://www.w3.org/2000/svg'><defs><pattern id='a' patternUnits='userSpaceOnUse' width='30' height='30' patternTransform='scale(1) rotate(65)'><rect x='0' y='0' width='100%' height='100%' fill='%232b2b3100' /><path d='M30 15L22.5 30 15 15 22.5 0zm-15 0L7.5 30 0 15 7.5 0z' stroke-width='0.6' stroke='%23ffffffff' fill='none' /></pattern></defs><rect width='800%' height='800%' transform='translate(0,0)' fill='url(%23a)' /></svg>");
--bg-paper: url(data:image/webp;base64,UklGRi4BAABXRUJQVlA4ICIBAABQCQCdASqAAIAAPm02lUmkIqIkIImIgA2JaW3rMFmGDAOKLAoJtP591ByFR74Tun2DP+Lygpfsz5FH7+cKgxi2Islfd03i5AJdXUfU0SDc8SXYAAD++hlzeYAJWQEF8ZdkJdlcA+5btZg0FMGaso8SHoBph0qAOQysElJ5C5SJFNoKIV1J550UyL7Y9Gh0/c/uzLnBmr8lvz7k1WeA81H4S5ViU/wBqa7aM1m8D9rDtrk8cSTqx+xWF6MS8UfZGSsks6CT/igtgv6syFN9uNA3LjnjiCJKYOvFcMkX+jB2578GWVo3nyLaM1QNPYCxn3TiUbnf7U0MdD2NsBpg1+Jd1wu6yW/U+goN+IQS6Nt4RMWltVcZHlxrneKJi0SobO0AAA==);
--split-right-background: unset;
@@ -73,27 +87,25 @@ body {
scrollbar-color: var(--color-background-light) var(--color-main-soft);
}
-@media screen and (min-width: 640px) and (min-height: 640px) {
- html {
- font-size: 14px;
- }
+body.glightbox-open {
+ height: 100dvh;
}
@media screen and (min-width: 900px) and (min-height: 900px) {
html {
- font-size: 16px;
+ font-size: clamp(16px, min(1dvw, 1dvh) + 7px, 20px);
}
}
@media screen and (min-width: 1400px) and (min-height: 1400px) {
html {
- font-size: 20px;
+ font-size: clamp(20px, min(1dvw, 1dvh) + 6px, 24px);
}
}
@media screen and (min-width: 1920px) and (min-height: 1920px) {
html {
- font-size: 24px;
+ font-size: calc(min(1dvw, 1dvh) + 4.8px);
}
}
@@ -527,14 +539,6 @@ form.crossable.htmx-request input {
calc(var(--squares-and-triangles-background-height-coef) * 1rem);
}
-.inset-shadow {
- box-shadow:
- inset 0dvh 1dvh 1dvh -1dvh rgba(75, 81, 58, 0.5),
- inset 1dvh 0dvh 1dvh -1dvh rgba(75, 81, 58, 0.5),
- inset -1dvh 0dvh 1dvh -1dvh rgba(75, 81, 58, 0.5),
- inset 0dvh -0.5dvh rgba(75, 81, 58, 0.5);
-}
-
.text-stroke-\(--color-sidebar-stroke\) {
-webkit-text-stroke-color: var(--color-sidebar-stroke);
}
@@ -547,7 +551,7 @@ form.crossable.htmx-request input {
position: fixed;
width: 12rem;
height: 12rem;
- box-shadow: 0.25rem 0.25rem 0.25rem var(--color-main-soft);
+ box-shadow: 0px 0.3125rem 0.3125rem -0.1875rem rgba(0, 0, 0, 0.2), 0px 0.5rem 0.625rem 0.0625rem rgba(0, 0, 0, 0.14), 0px 0.1875rem 0.875rem 0.125rem rgba(0, 0, 0, 0.12);
border-radius: 50%;
opacity: 0;
visibility: hidden;
@@ -582,7 +586,7 @@ form.crossable.htmx-request input {
.theme-icon i {
position: absolute;
- filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3));
+ filter: drop-shadow(0 0.125rem 0.25rem rgba(0, 0, 0, 0.3));
z-index: 1;
}
@@ -608,7 +612,7 @@ form.crossable.htmx-request input {
box-shadow: 0rem 0rem 1rem var(--color-main-hard);
border: 0.5rem solid
color-mix(in srgb, var(--color-main-soft) 90%, transparent);
- backdrop-filter: blur(2px);
+ backdrop-filter: blur(0.125rem);
top: 35%;
left: 35%;
width: 30%;
@@ -633,6 +637,10 @@ form.crossable.htmx-request input {
transition-timing-function: var(--ease-in-out);
}
+.accent-button {
+ box-shadow: 0px 0.1875rem 0.1875rem -0.125rem rgba(0, 0, 0, 0.2), 0px 0.1875rem 0.25rem 0px rgba(0, 0, 0, 0.14), 0px 0.0625rem 0.5rem 0px rgba(0, 0, 0, 0.12);
+}
+
.accent-button:hover,
.accent-button.active:active:hover {
cursor: pointer;
@@ -646,6 +654,7 @@ form.crossable.htmx-request input {
--tw-gradient-position: from 45deg in oklab;
--tw-gradient-to: color-mix(in oklab, var(--color-accent-dark) 30%, transparent);
--tw-gradient-via: color-mix(in oklab, var(--color-accent-light) 50%, transparent);
+ box-shadow: inset 0px 0.25rem 0.5rem 0px rgba(0, 0, 0, 0.25);
}
.accent-button.active:hover,
@@ -661,7 +670,7 @@ form.crossable.htmx-request input {
}
.custom-svg-marker svg {
- filter: drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.3));
+ filter: drop-shadow(0.125rem 0.125rem 0.125rem rgba(0, 0, 0, 0.3));
transition: transform 0.2s;
}
@@ -717,6 +726,15 @@ form.crossable.htmx-request input {
width: 10rem;
}
+.grid-item picture {
+ mask-image:
+ linear-gradient(to right, #FFFFFF calc(100% - 0.5rem), transparent 100%),
+ linear-gradient(to left, #FFFFFF calc(100% - 0.5rem), transparent 100%),
+ linear-gradient(to top, #FFFFFF calc(100% - 0.5rem), transparent 100%),
+ linear-gradient(to bottom, #FFFFFF calc(100% - 0.5rem), transparent 100%);
+ mask-composite: intersect;
+}
+
.grid-sizer {
width: 10.5rem;
}
@@ -740,6 +758,10 @@ form.crossable.htmx-request input {
opacity: 0;
}
+.grid-item:hover picture {
+ mask-image: none;
+}
+
.grid-item-2x {
width: 20rem;
}
@@ -882,8 +904,8 @@ form.crossable.htmx-request input {
}
.ram-frame {
- width: 20vmin;
- height: 20vmin;
+ width: 8rem;
+ height: 8rem;
user-select: none;
-webkit-user-select: none;
}
diff --git a/views/layouts/general-page.html b/views/layouts/general-page.html
index 9220b7f..06ef625 100644
--- a/views/layouts/general-page.html
+++ b/views/layouts/general-page.html
@@ -213,18 +213,8 @@
var seed = cyrb128("{{ .Title }}");
var rand = sfc32(seed[0], seed[1], seed[2], seed[3]);
- function calculateVmin(percent) {
- const viewportWidth = window.innerWidth;
- const viewportHeight = window.innerHeight;
-
- const smallerDimension = Math.min(
- viewportWidth,
- viewportHeight,
- );
-
- const vminValue = (smallerDimension / 100) * percent;
-
- return vminValue;
+ function calculateRem(remNum) {
+ return remNum * parseFloat(getComputedStyle(document.documentElement).fontSize);
}
const _probe = document.createElement('div');
@@ -319,7 +309,7 @@
theme = document.body.getAttribute("data-theme");
}
- vmin = calculateVmin(1);
+ rem = calculateRem(1);
var clWidth = document.documentElement.clientWidth;
var clHeight = document.documentElement.clientHeight;
@@ -338,11 +328,11 @@
"z-0",
"absolute",
);
- const x = Math.floor(rand() * clWidth);
- const y = Math.floor(rand() * clHeight * 0.8);
const rot = rand() * 90;
const animDuration = rand() * 10 + 3;
const sz = Math.floor(rand() * 8) + 12;
+ const x = Math.floor(rand() * clWidth - 1.42 * sz); // 1.42 ~ sqrt(2)
+ const y = Math.floor(rand() * clHeight * 0.8);
star.style.transform = `translateX(${x}px) translateY(${y}px) rotate(${rot}deg)`;
star.style.animationDuration = `${animDuration}s`;
star.style.fontSize = `${sz}px`;
@@ -362,14 +352,14 @@
);
let x, y;
outerLoop: while (true) {
- x = Math.floor(rand() * clWidth - 20 * vmin);
- y = Math.floor(rand() * clHeight - 20 * vmin);
+ x = Math.floor(rand() * clWidth - 22.64 * rem) + 11.32 * rem; // 11.32 ~ 8 * sqrt(2)
+ y = Math.floor(rand() * clHeight - 22.64 * rem) + 11.32 * rem;
for (j = 0; j < i - 1; j++) {
const xd = frameCenters[j].x - x;
const yd = frameCenters[j].y - y;
if (
Math.sqrt(xd * xd + yd * yd) <
- 30 * vmin
+ 23 * rem
) {
continue outerLoop;
}
@@ -412,6 +402,7 @@
localStorage.setItem("theme", theme);
document.body.setAttribute("data-theme", theme);
switchThemeDecor(theme);
+ switchColorScheme(matchMedia('(prefers-color-scheme: dark)').matches);
}
const savedTheme = localStorage.getItem("theme") || "lilac";
@@ -637,15 +628,15 @@
class="flex flex-1 min-h-0 z-1 bg-paper bg-background shadow-elevation-3 @container/body"
>
<div
- class="bg-paper bg-background-dark border-r-2 border-dashed border-main-hard"
+ class="bg-paper bg-background-dark border-r-[0.25rem] border-dashed border-main-hard"
></div>
<div
- class="max-h-full max-w-full flex flex-col grow bg-paper bg-background-dark relative pt-4 md:pr-4"
+ class="max-h-full max-w-full flex flex-col grow bg-paper bg-background-dark relative md:pr-4"
>
<header
id="general-page-header"
- class="max-xs:hidden [@media(max-height:32rem)]:hidden flex flex-col ml-8 basis-8"
+ class="max-xs:hidden [@media(max-height:32rem)]:hidden pt-4 flex flex-col ml-8 basis-8"
>{{ .RenderedHeader }}</header>
<div
id="general-page-header-trigger"
@@ -656,12 +647,12 @@
></div>
<hr
- class="max-xs:hidden [@media(max-height:32rem)]:hidden border-t-4 border-dotted border-main-hard mb-2"
+ class="max-xs:hidden [@media(max-height:32rem)]:hidden border-t-[0.5rem] border-dotted border-main-hard mb-2"
/>
<main
id="general-page-body"
- class="relative flex-1 overflow-y-auto @container-size"
+ class="relative flex-1 overflow-y-auto @container-size inset-shadow-elevation-8"
>{{ .RenderedBody }}</main>
<div
id="general-page-body-trigger"
@@ -683,14 +674,10 @@
hx-target="#general-page-footer"
hx-swap="innerHTML"
></div>
-
- <hr
- class="border-t-4 border-dotted border-main-hard mb-2"
- />
</div>
<div
- class="bg-paper bg-background-dark shadow-2xl border-l-2 border-dotted border-main-hard"
+ class="bg-paper bg-background-dark shadow-2xl border-l-[0.25rem] border-dotted border-main-hard"
></div>
</div>
</div>
@@ -717,17 +704,6 @@
}
});
- function calculateVmax(percent) {
- const viewportWidth = window.innerWidth;
- const viewportHeight = window.innerHeight;
-
- const largerDimension = Math.max(viewportWidth, viewportHeight);
-
- const vmaxValue = (largerDimension / 100) * percent;
-
- return vmaxValue;
- }
-
function positionThemeIcons() {
const sliceAngle = 360 / themeIcons.length;
diff --git a/views/pages/blog-catalogue.html b/views/pages/blog-catalogue.html
index b2bb0a3..ca8f578 100644
--- a/views/pages/blog-catalogue.html
+++ b/views/pages/blog-catalogue.html
@@ -45,50 +45,50 @@
</symbol>
</svg>
<div class="flex md:flex-row flex-col text-base h-full">
- <div class="relative flex shrink-0 w-full max-h-[30%] md:min-w-1/10 md:max-w-1/4 md:max-h-full md:h-full md:w-fit">
- <div class="absolute w-full h-full inset-shadow-[0_0_0.4rem_black] pointer-events-none z-20"></div>
+ <div class="relative flex shrink-0 w-full max-h-[30%] md:min-w-1/10 md:max-w-1/4 md:max-h-full md:h-full md:w-fit shadow-elevation-6">
+ <div class="absolute w-full h-full pointer-events-none z-20"></div>
<form hx-get="/api/v1/blog-search" hx-vals='{"lang": "{{ .Lang }}"}' hx-target=".blog-cards" hx-swap="innerHTML"
- class="tags-list relative flex flex-col w-full bg-paper bg-background-light">
- <div class="flex flex-col overflow-y-auto">
+ class="tags-list relative flex flex-col w-full">
+ <div class="flex flex-col bg-paper bg-background-light overflow-y-auto inset-shadow-elevation-6">
<fieldset>
<legend class="font-bold w-full text-center">{{ l $.Lang "BlogSearch" "OrderByHeader" }}</legend>
<div class="md:flex flex-col grid grid-cols-3 grid-rows-2 grid-flow-col">
- <div>
+ <div class="m-1">
<label class="flex justify-start gap-1 items-center">
<input type="radio" id="sortTitleAsc" name="sort" value="titleAsc" class="bg-accent-light border-transparent text-accent-deep focus:border-transparent focus:bg-accent-light focus:ring-1 focus:ring-offset-2 focus:ring-accent-deep" {{ if eq .QuerySort "titleAsc" }}checked{{ end }}>
{{ l $.Lang "BlogSearch" "TitleOrdered" }}
<svg viewBox="0 0 24 24" class="h-8"><use href="#icon-arrange-letter-asc"/></svg>
</label>
</div>
- <div>
+ <div class="m-1">
<label class="flex justify-start gap-1 items-center">
<input type="radio" id="sortTitleDesc" name="sort" value="titleDesc" class="bg-accent-light border-transparent text-accent-deep focus:border-transparent focus:bg-accent-light focus:ring-1 focus:ring-offset-2 focus:ring-accent-deep" {{ if eq .QuerySort "titleDesc" }}checked{{ end }}>
{{ l $.Lang "BlogSearch" "TitleOrdered" }}
<svg viewBox="0 0 24 24" class="h-8"><use href="#icon-arrange-letter-desc"/></svg>
</label>
</div>
- <div>
+ <div class="m-1">
<label class="flex justify-start gap-1 items-center">
<input type="radio" id="sortActionDateAsc" name="sort" value="actionDateAsc" class="bg-accent-light border-transparent text-accent-deep focus:border-transparent focus:bg-accent-light focus:ring-1 focus:ring-offset-2 focus:ring-accent-deep" {{ if eq .QuerySort "actionDateAsc" }}checked{{ end }}>
{{ l $.Lang "BlogSearch" "ActionDateOrdered" }}
<svg viewBox="0 0 24 24" class="h-8"><use href="#icon-arrange-number-asc"/></svg>
</label>
</div>
- <div>
+ <div class="m-1">
<label class="flex justify-start gap-1 items-center">
<input type="radio" id="sortActionDateDesc" name="sort" value="actionDateDesc" class="bg-accent-light border-transparent text-accent-deep focus:border-transparent focus:bg-accent-light focus:ring-1 focus:ring-offset-2 focus:ring-accent-deep" {{ if eq .QuerySort "actionDateDesc" }}checked{{ end }}>
{{ l $.Lang "BlogSearch" "ActionDateOrdered" }}
<svg viewBox="0 0 24 24" class="h-8"><use href="#icon-arrange-number-desc"/></svg>
</label>
</div>
- <div>
+ <div class="m-1">
<label class="flex justify-start gap-1 items-center">
<input type="radio" id="sortPublicationDateAsc" name="sort" value="publicationDateAsc" class="bg-accent-light border-transparent text-accent-deep focus:border-transparent focus:bg-accent-light focus:ring-1 focus:ring-offset-2 focus:ring-accent-deep" {{ if eq .QuerySort "publicationDateAsc" }}checked{{ end }}>
{{ l $.Lang "BlogSearch" "PublicationDateOrdered" }}
<svg viewBox="0 0 24 24" class="h-8"><use href="#icon-arrange-number-asc"/></svg>
</label>
</div>
- <div>
+ <div class="m-1">
<label class="flex justify-start gap-1 items-center">
<input type="radio" id="sortPublicationDateDesc" name="sort" value="publicationDateDesc" class="bg-accent-light border-transparent text-accent-deep focus:border-transparent focus:bg-accent-light focus:ring-1 focus:ring-offset-2 focus:ring-accent-deep" {{ if eq .QuerySort "publicationDateDesc" }}checked{{ end }}>
{{ l $.Lang "BlogSearch" "PublicationDateOrdered" }}
@@ -111,23 +111,20 @@
</div>
</fieldset>
</div>
- <hr class="border-t-2 border-dotted border-main-hard my-0.5">
- <div class="flex flex-row bg-paper bg-background-dark p-0.5 rounded-1 h-12">
- <button type="button" onclick="defaultSearchParams(); cleanHrefParams();" class="flex flex-1 justify-center text-main-hard bg-paper bg-accent-light cursor-pointer hover:bg-accent-deep active:text-background-dark transition-colors duration-500">
- <svg viewBox="0 0 24 24"><use href="#icon-camera-settings-flip"/></svg>
+ <hr class="border-t-[0.375rem] border-dotted border-main-hard my-2 mx-auto w-24">
+ <div class="flex flex-row p-0.5 rounded-1 h-12">
+ <button type="button" onclick="defaultSearchParams(); cleanHrefParams();" class="accent-button grow h-full">
+ <svg class="h-full mx-auto" viewBox="0 0 24 24"><use href="#icon-camera-settings-flip"/></svg>
</button>
- <div class="w-1 bg-paper bg-background-light grow-0"></div>
- <button type="submit" onclick="setHrefParams();" class="flex flex-1 justify-center text-main-hard bg-paper bg-accent-light cursor-pointer hover:bg-accent-deep active:text-background-dark transition-colors duration-500">
- <svg viewBox="0 0 24 24"><use href="#icon-search-magnifier"/></svg>
+ <button type="submit" onclick="setHrefParams();" class="accent-button grow h-full">
+ <svg class="h-full mx-auto" viewBox="0 0 24 24"><use href="#icon-search-magnifier"/></svg>
</button>
</div>
</form>
</div>
- <div class="w-[0.5dvh] border-r-2 border-dotted border-main-hard bg-paper bg-background-dark"></div>
-
<div class="relative flex grow h-full">
- <div class="absolute w-full h-full inset-0 inset-shadow-[0_0_0.4rem_black] pointer-events-none z-20"></div>
+ <div class="absolute w-full h-full inset-0 inset-shadow-elevation-6 pointer-events-none z-20"></div>
<div hx-get="/api/v1/blog-search" hx-vals='js:{lang: "{{ .Lang }}", tz: clientTimeZone, highlight: "{{ .PreviousBlogPage }}"}' hx-target="this" hx-swap="innerHTML" hx-trigger="load" hx-include=".tags-list"
class="blog-cards relative grow flex flex-col overflow-y-auto bg-paper bg-background-light pr-2">
Loading...
diff --git a/views/pages/blog-page.html b/views/pages/blog-page.html
index c02c3f5..3d3c623 100644
--- a/views/pages/blog-page.html
+++ b/views/pages/blog-page.html
@@ -1,9 +1,8 @@
{{ define "body" }}
<input class="htmx-exit-trigger" type="hidden" name="codename" value="{{ .Codename }}">
-<div class="sticky top-0 left-0 w-full h-[100cqb] -mb-[100cqb] inset-shadow-[0_0_0.4rem_black] pointer-events-none z-20"></div>
-<article class="relative bg-paper bg-background-light flex flex-col px-8 py-4 overflow-y-auto">
- <div class="flex flex-col sm:flex-row h-[30cqb] sm:h-[15cqb]">
- <div class="grow shrink-2 flex-1 overflow-y-auto -ml-8 -mt-4 {{if .Medley}}max-sm:-mr-8{{else}}-mr-8{{end}} z-1 shadow-elevation-2">
+<div class="relative bg-paper bg-background-light flex flex-col py-4 overflow-y-auto">
+ <div class="flex flex-col sm:flex-row h-[30cqb] sm:h-[15cqb] shadow-elevation-6">
+ <div class="grow shrink-2 flex-1 overflow-y-auto -mt-4 z-1 shadow-elevation-3">
<div class="multitone min-h-full" style="--multitone-bg: url({{ printf $.PhotoStorage.Thumbnail560p.BaseUrl .Thumbnail }});">
<div class="ml-8 py-4">
<h1 class="max-xs:flex flex-row content-center [@media(max-height:32rem)]:block hidden font-gentium text-2xl font-bold italic text-main-hard tracking-[.0125rem] mb-1">
@@ -21,13 +20,12 @@
</div>
</div>
</div>
- <hr class="block sm:hidden border-t-3 bg-paper bg-background-dark border-dotted border-main-hard w-full">
+ <hr class="block sm:hidden border-t-[0.1875rem] bg-paper bg-background-dark border-dotted border-main-hard w-full">
{{- if .Medley }}
- <div class="overflow-y-auto grow-2 shrink-0 flex-1 bg-paper bg-background-dark shadow-elevation-2 -mr-8 sm:-mt-4 max-sm:-ml-8 z-2">
- <h2 class="text-2xl font-gentium font-extrabold text-main-hard tracking-[.0125rem] ml-2">
+ <div class="overflow-y-auto grow-2 shrink-0 flex-1 bg-paper bg-background-dark shadow-elevation-3 sm:-mt-4 z-2">
+ <h2 class="text-2xl font-gentium font-extrabold text-main-hard tracking-[.0125rem] ml-2 mb-2 border-b-[0.25rem] border-dotted w-fit">
{{ l .Lang "Medleys" .Medley }}
</h2>
- <hr class="block border-t-2 my-1 border-dotted border-main-hard w-full">
<div hx-get="/api/v1/blog-search" hx-vals='js:{lang: "{{ .Lang }}", tz: clientTimeZone, medley: "{{ .Medley }}", sort: "medley", hideTags: true, hidePublishedTime: true, highlight: "{{ .Codename }}"}' hx-target="this" hx-swap="innerHTML" hx-trigger="load"
class="grow flex flex-col pr-2">
Loading...
@@ -35,14 +33,16 @@
</div>
{{- end }}
</div>
- <hr class="block border-t-3 mb-2 border-dotted border-main-hard w-full ml-auto mr-auto">
- {{ .ParsedMarkdown }}
+ <hr class="block border-t-[0.375rem] w-24 mx-auto my-4 border-dotted border-main-hard">
+ <article class="px-8 flex flex-col">
+ {{ .ParsedMarkdown }}
+ </article>
{{- if .MapLocationX }}
- <hr class="border-t-3 border-dotted border-main-hard mt-1 mb-2 w-[80%] ml-auto mr-auto">
- <div id="map-outer-container" class="relative p-1 flex-none ml-auto mr-auto w-[80%] lg:w-[60%] h-[30dvh] md:h-[40dvh]"
+ <hr class="border-t-[0.375rem] border-dotted border-main-hard my-2 w-24 mx-auto">
+ <div id="map-outer-container" class="relative p-1 flex-none mx-auto w-[80%] lg:w-[60%] h-[30dvh] md:h-[40dvh]"
hx-get="/api/v1/map" hx-vals='{"lang": "{{ .Lang }}", "codename": "{{ .Codename }}", "zoom": 8}' hx-target="this" hx-swap="innerHTML" hx-trigger="load">
</div>
- <hr class="border-t-3 border-dotted border-main-hard mt-1 mb-2 w-[80%] ml-auto mr-auto">
+ <hr class="border-t-[0.375rem] border-dotted border-main-hard my-2 w-24 mx-auto">
<script>
var lightbox = GLightbox({
diff --git a/views/pages/home-page.html b/views/pages/home-page.html
index e89be39..d494a08 100644
--- a/views/pages/home-page.html
+++ b/views/pages/home-page.html
@@ -17,14 +17,13 @@
<path d="M4.59 15.35a39.94 39.94 0 0 0 -2.94 3.25 0.35 0.35 0 1 0 0.53 0.46c0.59 -0.6 1.69 -1.51 2.89 -2.58 0.63 -0.57 1.29 -1.17 1.9 -1.79s1.42 -1.52 2 -2.21 -0.14 -1 -0.82 -0.39c-0.52 0.46 -1.08 0.94 -1.67 1.47s-1.28 1.19 -1.89 1.79Z" fill="var(--color-accent-deep)" stroke-width="1"></path>
</g></symbol>
</svg>
-<div class="absolute w-full h-full inset-0 inset-shadow-[0_0_0.4rem_black] pointer-events-none z-20"></div>
<div class="relative bg-paper bg-background-light font-gentium flex flex-col sm:flex-row w-full h-full overflow-y-auto text-base/loose tracking-wide z-10">
<div class="sm:flex-3/5 justify-center content-start p-8">
<div class="flex flex-col justify-start items-start bg-paper bg-background-dark mb-8 shadow-[0.4rem_0.4rem_0.4rem_black]">
<p class="text-3xl/loose sm:text-4xl/loose lg:text-5xl/loose tracking-widest uppercase w-full font-m-plus font-thin italic text-left
- border-l-4 border-solid border-background-dark
+ border-l-[0.25rem] border-solid border-background-dark
bg-linear-to-r from-background-dark to-background-light">{{ l $.Lang "HomePage" "Hymn1" }}</p>
- <hr class="w-full border-t-2 border-dotted border-main-hard mb-1">
+ <hr class="w-full border-t-[0.125rem] border-dotted border-main-hard mb-1">
<p class="text-xl/loose sm:text-2xl/loose lg:text-3xl/loose -indent-8 ml-12 p-1">{{ l $.Lang "HomePage" "Hymn2" }}</p>
<p class="text-xl/loose sm:text-2xl/loose lg:text-3xl/loose -indent-8 ml-12 p-1">{{ l $.Lang "HomePage" "Hymn3" }}</p>
<p class="text-xl/loose sm:text-2xl/loose lg:text-3xl/loose -indent-8 ml-12 p-1">{{ l $.Lang "HomePage" "Hymn4" }}</p>
@@ -32,9 +31,9 @@
<div class="flex flex-col justify-center items-center">
<p class="text-xl sm:text-2xl lg:text-3xl p-1 w-full font-m-plus font-thin italic text-left
- border-l-1.5 border-solid border-background-dark
+ border-l-[0.125rem] border-solid border-background-dark
bg-linear-to-r from-background-dark to-background-light">{{ l $.Lang "HomePage" "DidYouKnowThat" }}</p>
- <hr class="w-full border-t-2 border-dotted border-main-hard mb-1">
+ <hr class="w-full border-t-[0.125rem] border-dotted border-main-hard mb-1">
<ul class="w-full text-left list-[circle]">
<li class="ml-4 mb-1">{{ index .FunFacts 0 }}</li>
<li class="ml-4 mb-1">{{ index .FunFacts 1 }}</li>
@@ -46,9 +45,9 @@
<div class="sm:flex-2/5 justify-center content-start p-8">
<div class="flex flex-col justify-center items-start mb-4">
<p class="text-xl sm:text-2xl lg:text-3xl p-1 w-full font-m-plus font-thin italic text-left
- border-l-1.5 border-solid border-background-dark
+ border-l-[0.125rem] border-solid border-background-dark
bg-linear-to-r from-background-dark to-background-light">{{ l $.Lang "HomePage" "Contacts" }}</p>
- <hr class="w-full border-t-2 border-dotted border-main-hard mb-1">
+ <hr class="w-full border-t-[0.125rem] border-dotted border-main-hard mb-1">
<a href="https://t.me/EarlInisMona">
<svg class="w-4 h-4 mr-1 inline" viewBox="0 0 24 24"><use href="#icon-telegram"/></svg>
<span class="font-bold">Telegram:</span>
@@ -74,7 +73,7 @@
<div class="home-page-heart z-50">♡</div>
{{- end }}
<img src="{{ .GifUrl }}"
- class="home-page-gif z-49 -rotate-12 max-w-[70%] max-h-[70%] border-4 border-background-dark border-inset">
+ class="home-page-gif z-49 -rotate-12 max-w-[70%] max-h-[70%] border-[0.25rem] border-background-dark border-inset">
</div>
<script>
@@ -121,9 +120,9 @@
<div class="flex flex-col justify-center items-center">
<p class="text-xl sm:text-2xl lg:text-3xl p-1 w-full font-m-plus font-thin italic text-left
- border-l-1.5 border-solid border-color-background-dark
+ border-l-[0.125rem] border-solid border-color-background-dark
bg-linear-to-r from-background-dark to-background-light">{{ l $.Lang "HomePage" "SidebarDescription" }}</p>
- <hr class="w-full border-t-2 border-dotted border-main-hard mb-1">
+ <hr class="w-full border-t-[0.125rem] border-dotted border-main-hard mb-1">
<div class="w-full grid grid-cols-[1fr_4fr] content-center items-center
[&>*:nth-child(4n+2)]:bg-background-medium/50 [&>*:nth-child(4n+3)]:bg-background-medium/50" style="container-type: inline-size;">
<svg viewBox="0 0 24 24" class="h-full w-[15cqi] context-center text-main-hard"><use href="#icon-back"/></svg>
diff --git a/views/pages/language-pick.html b/views/pages/language-pick.html
index f4119e4..9576a65 100644
--- a/views/pages/language-pick.html
+++ b/views/pages/language-pick.html
@@ -1,7 +1,7 @@
{{ define "body" }}
<div class="flex flex-col justify-center text-3xl h-full">
{{- range .AvailableLanguages }}
- <hr class="border-t-2 border-dotted border-main-hard">
+ <hr class="border-t-[0.125rem] border-dotted border-main-hard">
<div class="nth-[2n+1_of_div]:bg-background-medium/50 nth-[2n_of_div]:bg-background-light/50 p-2.5 flex flex-row justify-center justify-items-center">
<a href="/{{ .Name }}" class="w-12 h-12 basis-12 shrink-0 mr-4">
<img onclick="return changeUrl('{{ .Name }}');" class="w-full h-full aspect-square cursor-pointer object-cover rounded-md select-none" src="{{ .Flag }}">
@@ -11,6 +11,6 @@
</a>
</div>
{{- end }}
- <hr class="border-t-2 border-dotted border-main-hard">
+ <hr class="border-t-[0.125rem] border-dotted border-main-hard">
</div>
{{ end }}
diff --git a/views/pages/user-page.html b/views/pages/user-page.html
index dc4966b..a94dcb3 100644
--- a/views/pages/user-page.html
+++ b/views/pages/user-page.html
@@ -1,5 +1,5 @@
{{ define "body" }}
-<div class="absolute w-full h-full inset-0 inset-shadow-[0_0_0.4rem_black] pointer-events-none z-20"></div>
+<div class="absolute w-full h-full inset-0 inset-shadow-elevation-6 pointer-events-none z-20"></div>
<div class="relative bg-paper bg-background-light flex flex-col px-8 py-4">
<form id="email-form" class="w-full mb-2 flex flex-col relative crossable"
hx-get="/api/v1/email/is-in-verification" hx-target="#email-message" hx-swap="outerHTML" hx-trigger="load" hx-indicator="this">
@@ -8,7 +8,7 @@
<label class="block text-main-medium font-bold mb-1 z-22">
{{ l $.Lang "UserProfile" "EmailHeader" }}
</label>
- <input class="bg-background-medium appearance-none border-background-medium rounded ml-6 mr-4 py-2 px-4 text-main-medium leading-tight inset-shadow-[0_0_0.4rem_black] focus:outline-none focus:bg-background-light focus:text-main-hard z-22"
+ <input class="bg-background-medium appearance-none border-background-medium rounded ml-6 mr-4 py-2 px-4 text-main-medium leading-tight inset-shadow-elevation-6 focus:outline-none focus:bg-background-light focus:text-main-hard z-22"
id="email-input" name="email" type="text" value="{{ .Email }}" placeholder="{{ l $.Lang "UserProfile" "TypeEmail" }}" maxlength="64"
data-validated-email="{{ .Email }}" onchange="checkIfValidated(this);">
</div>
@@ -18,9 +18,9 @@
{{ l $.Lang "UserProfile" "SendCodeButton" }}
</button>
</form>
- <div id="email-message" class="bg-paper bg-background-dark text-main-soft z-26 w-full inset-shadow-[0_0_0.4rem_black] py-2 px-4 text-center"></div>
+ <div id="email-message" class="bg-paper bg-background-dark text-main-soft z-26 w-full inset-shadow-elevation-6 py-2 px-4 text-center"></div>
- <hr class="my-2 border-t-4 border-dotted border-main-hard">
+ <hr class="my-2 border-t-[0.25rem] border-dotted border-main-hard">
<form id="email-verification-form" class="w-full mb-2 flex flex-col relative hidden crossable"
{{ if .EmailCode }}hx-post="/api/v1/email/verify" hx-target="#verification-message" hx-swap="outerHTML" hx-trigger="load" hx-indicator="this"{{ end }}>
@@ -29,7 +29,7 @@
<label class="block text-main-medium font-bold ml-1 z-22">
{{ l $.Lang "UserProfile" "VerificationCodeHeader" }}
</label>
- <input class="bg-background-medium appearance-none border-background-medium rounded ml-6 mr-4 py-2 px-4 text-main-medium leading-tight inset-shadow-[0_0_0.4rem_black] focus:outline-none focus:bg-background-light focus:text-main-hard z-22"
+ <input class="bg-background-medium appearance-none border-background-medium rounded ml-6 mr-4 py-2 px-4 text-main-medium leading-tight inset-shadow-elevation-6 focus:outline-none focus:bg-background-light focus:text-main-hard z-22"
name="email_code" type="text" value="{{ .EmailCode }}" placeholder="0123456789ABCDEF" maxlength="16" autocapitalize="characters">
</div>
</div>
@@ -38,12 +38,12 @@
{{ l $.Lang "UserProfile" "VerifyButton" }}
</button>
</form>
- <div id="verification-message" class="bg-paper bg-background-dark text-main-soft z-26 w-full inset-shadow-[0_0_0.4rem_black] py-2 px-4 text-center"></div>
+ <div id="verification-message" class="bg-paper bg-background-dark text-main-soft z-26 w-full inset-shadow-elevation-6 py-2 px-4 text-center"></div>
</div>
-<hr class="my-4 border-t-4 border-dotted border-main-hard">
+<hr class="my-4 border-t-[0.25rem] border-dotted border-main-hard">
-<div class="bg-paper bg-background-light flex flex-col inset-shadow-[0_0_0.4rem_black] px-8 py-4">
+<div class="bg-paper bg-background-light flex flex-col inset-shadow-elevation-6 px-8 py-4">
<form id="subs-form" class="w-full mb-2 flex flex-col relative crossable">
<div class="flex flex-col w-full mb-4 z-21">
<label class="block text-main-medium font-bold mb-1 z-22">
@@ -61,14 +61,14 @@
</div>
</div>
<div id="pick-tags-form" class="flex flex-col w-full relative crossable">
- <input type="text" class="bg-background-medium appearance-none border-background-medium rounded ml-6 mr-4 py-2 px-4 text-main-medium leading-tight inset-shadow-[0_0_0.4rem_black] focus:outline-none focus:bg-background-light focus:text-main-hard z-22"
+ <input type="text" class="bg-background-medium appearance-none border-background-medium rounded ml-6 mr-4 py-2 px-4 text-main-medium leading-tight inset-shadow-elevation-6 focus:outline-none focus:bg-background-light focus:text-main-hard z-22"
list="existing-tags" onchange="addTag(this.value);" onkeydown="if (event.keyCode === 13) {addTag(this.value); this.value=''; return false;}">
<datalist id="existing-tags">
{{- range .ExistingTags }}
<option value="{{ .Name }}">
{{- end }}
</datalist>
- <div id="tags-picked-list" class="bg-paper bg-background-dark flex flex-wrap inset-shadow-[0_0_0.4rem_black] p-2 m-4 w-full">
+ <div id="tags-picked-list" class="bg-paper bg-background-dark flex flex-wrap inset-shadow-elevation-6 p-2 m-4 w-full">
{{- range .TagsPickedList }}
<div id="tagPicked{{ . }}" class="bg-paper bg-main-hard text-background-light m-2 flex flex-row">
<p class="py-1 px-2">{{ . }}</p>
@@ -84,7 +84,7 @@
</button>
</div>
</form>
- <div id="subs-message" class="bg-paper bg-background-dark text-main-soft z-26 w-full inset-shadow-[0_0_0.4rem_black] py-2 px-4 text-center"></div>
+ <div id="subs-message" class="bg-paper bg-background-dark text-main-soft z-26 w-full inset-shadow-elevation-6 py-2 px-4 text-center"></div>
</div>
<script>
diff --git a/views/partials/blog-page-like-button.html b/views/partials/blog-page-like-button.html
index af668e6..50ceae9 100644
--- a/views/partials/blog-page-like-button.html
+++ b/views/partials/blog-page-like-button.html
@@ -1,5 +1,5 @@
<button hx-put="/api/v1/like" hx-vals='{"like": {{ not .Liked }}}' hx-target="this" hx-swap="outerHTML" hx-trigger="click"
- class="accent-button rounded-xl flex flex-row shrink-0 w-fit h-full mx-2 my-auto{{ if .Liked }} active{{ end }}">
+ class="accent-button rounded-xl relative shrink-0 w-fit aspect-square mr-4 p-2 my-auto{{ if .Liked }} active{{ end }}">
{{ if .Liked }}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="Like-Hand-1--Streamline-Freehand" class="h-10">
<desc>
@@ -12,7 +12,7 @@
<path d="M13.94 4.33a2.57 2.57 0 0 1 1.43 0.88 4.52 4.52 0 0 1 1 1.54 0.57 0.57 0 0 0 0.56 0.37 0.57 0.57 0 0 0 0.53 -0.41 2.81 2.81 0 0 1 1 -1.41 6.9 6.9 0 0 1 1.69 -1 0.49 0.49 0 0 0 0.31 -0.43 0.5 0.5 0 0 0 -0.24 -0.47 8.18 8.18 0 0 1 -2.26 -1.47 2.39 2.39 0 0 1 -0.71 -1.46 0.34 0.34 0 0 0 -0.34 -0.34 0.35 0.35 0 0 0 -0.34 0.35 0.29 0.29 0 0 0 -0.27 0.23 4.41 4.41 0 0 1 -1 1.63 3.53 3.53 0 0 1 -1.48 1 0.47 0.47 0 0 0 -0.32 0.5 0.48 0.48 0 0 0 0.44 0.49Zm2 -1.47a5.53 5.53 0 0 0 0.82 -1.44 3.34 3.34 0 0 0 0.59 1 6.91 6.91 0 0 0 1.53 1.3 5.93 5.93 0 0 0 -1.48 1 6.91 6.91 0 0 0 -0.51 0.57 4.8 4.8 0 0 0 -0.7 -0.85 4 4 0 0 0 -1 -0.74 5.76 5.76 0 0 0 0.71 -0.84Z" fill="var(--color-accent-deep)" fill-rule="evenodd" stroke-width="1"></path>
</g>
</svg>
- <div class="ml-auto bg-accent-light rounded-full w-6 h-6 text-main! font-m-plus! font-normal! tracking-normal! not-italic! text-lg!">{{ .LikedCount }}</div>
+ <div class="absolute left-10 -top-2 bg-accent-light rounded-full w-6 h-6 text-main! font-m-plus! font-normal! tracking-normal! not-italic! text-lg!">{{ .LikedCount }}</div>
{{ else }}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="Like-Hand--Streamline-Freehand" class="h-10">
<desc>
@@ -23,6 +23,6 @@
<path d="M3.53 9.34a2.22 2.22 0 0 0 -1.24 -0.88 5.37 5.37 0 0 0 -2 -0.26 0.3 0.3 0 0 0 -0.29 0.31 0.3 0.3 0 0 0 0.32 0.29 4.36 4.36 0 0 1 1.44 0.25 1.74 1.74 0 0 1 1 0.69A9.16 9.16 0 0 1 3 11.8c0 0.64 0.06 1.38 0.09 2.14 0 1.07 0.08 2.2 0.11 3.22s0.06 2.19 0 2.84c0 0.23 -0.12 0.45 -0.07 0.51A2.7 2.7 0 0 1 2 21a3.34 3.34 0 0 1 -1.49 0 0.34 0.34 0 0 0 -0.22 0.65 4.22 4.22 0 0 0 1.82 0.13 3.37 3.37 0 0 0 1.79 -0.69 1.82 1.82 0 0 0 0.26 -0.82 37.13 37.13 0 0 0 0.14 -5.13c0 -1 -0.1 -2 -0.19 -2.83a12.48 12.48 0 0 0 -0.58 -2.97Z" fill="var(--color-accent-deep)" fill-rule="evenodd" stroke-width="1"></path>
</g>
</svg>
- <div class="ml-auto bg-accent-deep rounded-full w-6 h-6 text-background! font-m-plus! font-normal! tracking-normal! not-italic! text-lg!">{{ .LikedCount }}</div>
+ <div class="absolute left-10 -top-2 bg-accent-deep rounded-full w-6 h-6 text-background! font-m-plus! font-normal! tracking-normal! not-italic! text-lg!">{{ .LikedCount }}</div>
{{ end }}
</button>
diff --git a/views/partials/catalogue-blog-cards.html b/views/partials/catalogue-blog-cards.html
index b066a9e..6466262 100644
--- a/views/partials/catalogue-blog-cards.html
+++ b/views/partials/catalogue-blog-cards.html
@@ -1,7 +1,7 @@
{{- range .BlogPages }}
-<hr class="first-of-type:hidden border-t-2 border-dotted border-main-hard">
-<div {{ if .ToHighlight }}id="blog-page-highlighted"{{ end }} class="w-full flex flex-row items-stretch {{ if .ToHighlight }}bg-accent-light bg-paper{{ end }}">
- <div class="relative min-h-24 flex flex-col w-28 overflow-hidden shrink-0 mask-r-from-70% mask-r-to-100%">
+<hr class="first-of-type:hidden border-t-[0.375rem] my-1 w-24 mx-auto border-dotted border-main-hard">
+<div {{ if .ToHighlight }}id="blog-page-highlighted"{{ end }} class="w-full flex flex-row items-stretch mask-t-from-[calc(100%-0.5rem)] mask-t-to-100% mask-b-from-[calc(100%-0.5rem)] mask-b-to-100% {{ if .ToHighlight }}bg-accent-light bg-paper{{ end }}">
+ <div class="relative min-h-24 flex flex-col w-32 overflow-hidden shrink-0 mask-r-from-[calc(100%-1rem)] mask-r-to-100%">
<img onclick="return changeUrl('{{ .ArticleLink }}');" class="h-full min-h-24 w-full cursor-pointer select-none object-cover block absolute" src="{{ printf $.PhotoStorage.Thumbnail320p.BaseUrl .Thumbnail }}">
<div class="w-full h-6 flex flex-row mt-auto relative">
<div class="flex-1/2 flex flex-row justify-center select-none bg-linear-180 {{ if .Liked }}from-accent-deep/40 to-accent-deep/80 text-background-dark{{ else }}from-accent-light/40 to-accent-light/80 text-main-hard{{ end }}">
@@ -14,7 +14,7 @@
</div>
</div>
</div>
- <div class="grow w-full h-fit flex flex-col justify-center my-auto py-1 px-1">
+ <div class="grow w-full h-fit flex flex-col justify-center my-auto py-1 px-2">
<div class="flex flex-row gap-2 max-w-full">
<a href="{{ .ArticleLink }}" onclick="return changeUrl('{{ .ArticleLink }}');" class="grow-2 text-base cursor-pointer font-m-plus">
<span class="font-extrabold">{{ .Title }}</span>
diff --git a/views/partials/general-page-header.html b/views/partials/general-page-header.html
index 3b8a6c8..a75d32f 100644
--- a/views/partials/general-page-header.html
+++ b/views/partials/general-page-header.html
@@ -1,8 +1,8 @@
-<title>{{ .Title }} // SAYA.UZ</title>
+<title>{{ or .PageTitle .Title }}</title>
<div class="flex flex-row mb-2">
{{ block "header" . }}{{ end }}
<h1
- class="text-4xl font-m-plus font-bold italic text-shadow-[0_2px_2px_var(--color-main-soft)] text-left my-auto"
+ class="text-4xl font-m-plus font-bold italic text-shadow-[0_0.125rem_0.125rem_var(--color-main-soft)] text-left my-auto"
>
{{ .Title }}
</h1>
diff --git a/views/partials/personal-page-status.html b/views/partials/personal-page-status.html
index 078fb24..41033a9 100644
--- a/views/partials/personal-page-status.html
+++ b/views/partials/personal-page-status.html
@@ -1,4 +1,4 @@
-<div id="{{ .StatusId }}" class='z-26 w-full inset-shadow-[0_0_0.4rem_black]
+<div id="{{ .StatusId }}" class='z-26 w-full inset-shadow-elevation-6
{{if eq .Status "OK"}}bg-green-700 text-green-100
{{else if eq .Status "Failed"}}bg-red-700 text-red-100
{{else}}bg-paper bg-background-dark text-main-soft{{end}}