Compare commits
38
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
74ed415980 | ||
|
|
cc12c4fc18 | ||
|
|
eb667f7f04 | ||
|
|
575a37accc | ||
|
|
bbad670baa | ||
|
|
4c19ffdd9f | ||
|
|
15c2b44fcf | ||
|
|
34597fe9f8 | ||
|
|
4780133019 | ||
|
|
55352af0f2 | ||
|
|
b595169e3b | ||
|
|
d75ccecdf2 | ||
|
|
a694817c28 | ||
|
|
a2125bdab7 | ||
|
|
ddca56e868 | ||
|
|
da7f526cb0 | ||
|
|
370f8204a0 | ||
|
|
2b5aea6eb8 | ||
|
|
0179e7a858 | ||
|
|
5c7342c91e | ||
|
|
3ed6cbf57a | ||
|
|
1ab42ed2e2 | ||
|
|
419b0c6ab5 | ||
|
|
f85991c409 | ||
|
|
d115d69b1b | ||
|
|
18563979a2 | ||
|
|
4b7a867a19 | ||
|
|
517a8ee8f1 | ||
|
|
0b4bf289d4 | ||
|
|
db083e20c2 | ||
|
|
fa564754f2 | ||
|
|
ae70cfc5e3 | ||
|
|
d46f62dd3f | ||
|
|
58d0378d49 | ||
|
|
23baa758cf | ||
|
|
1a3948a8eb | ||
|
|
4fca2f8b14 | ||
|
|
3173968f0e |
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"printWidth": 110,
|
|
||||||
"singleQuote": true,
|
|
||||||
"quoteProps": "consistent",
|
|
||||||
"tabWidth": 4,
|
|
||||||
"useTabs": false,
|
|
||||||
"semi": false,
|
|
||||||
"arrowParens": "avoid"
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/** @type {import("prettier").Config} */
|
||||||
|
export default {
|
||||||
|
printWidth: 120,
|
||||||
|
singleQuote: true,
|
||||||
|
quoteProps: 'consistent',
|
||||||
|
tabWidth: 4,
|
||||||
|
useTabs: false,
|
||||||
|
semi: false,
|
||||||
|
arrowParens: 'avoid',
|
||||||
|
|
||||||
|
plugins: ['prettier-plugin-astro'],
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: '*.astro',
|
||||||
|
options: {
|
||||||
|
parser: 'astro',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: '*.{yml,yaml,json}',
|
||||||
|
excludeFiles: 'package-lock.json',
|
||||||
|
options: {
|
||||||
|
tabWidth: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
Vendored
+9
-1
@@ -1,3 +1,11 @@
|
|||||||
{
|
{
|
||||||
"npm.packageManager": "bun"
|
"npm.packageManager": "bun",
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
|
"[astro]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[yaml]": {
|
||||||
|
"editor.tabSize": 2,
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,19 +17,12 @@ bun dev
|
|||||||
## Build
|
## Build
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bun build
|
bun run build
|
||||||
```
|
```
|
||||||
|
|
||||||
## Deploy [TODO]
|
## Deploy
|
||||||
|
|
||||||
Il progetto contiene un `Dockerfile` che viene usato per il deploy (del server prodotto da Astro).
|
Per ora c'è un file `.drone.yml` che viene usato per il deploy su un server remoto utilizzando Drone per il CD. Al momento il sito è solo statico e non ha ancora una backend.
|
||||||
|
|
||||||
```bash
|
|
||||||
docker build -t phc-website .
|
|
||||||
docker run -p 3000:3000 phc-website
|
|
||||||
```
|
|
||||||
|
|
||||||
C'è anche un `.drone.yml` che viene usato per il deploy su un server remoto utilizzando Drone per il CD.
|
|
||||||
|
|
||||||
## Come Contribuire
|
## Come Contribuire
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -2,6 +2,7 @@ import { defineConfig } from 'astro/config'
|
|||||||
import preact from '@astrojs/preact'
|
import preact from '@astrojs/preact'
|
||||||
|
|
||||||
import mdx from '@astrojs/mdx'
|
import mdx from '@astrojs/mdx'
|
||||||
|
import remarkMath from 'remark-math'
|
||||||
|
|
||||||
import yaml from '@rollup/plugin-yaml'
|
import yaml from '@rollup/plugin-yaml'
|
||||||
|
|
||||||
@@ -14,6 +15,7 @@ export default defineConfig({
|
|||||||
port: 3000,
|
port: 3000,
|
||||||
},
|
},
|
||||||
markdown: {
|
markdown: {
|
||||||
|
remarkPlugins: [remarkMath],
|
||||||
shikiConfig: {
|
shikiConfig: {
|
||||||
theme: 'github-light',
|
theme: 'github-light',
|
||||||
},
|
},
|
||||||
@@ -22,7 +24,9 @@ export default defineConfig({
|
|||||||
preact({
|
preact({
|
||||||
compat: true,
|
compat: true,
|
||||||
}),
|
}),
|
||||||
mdx(),
|
mdx({
|
||||||
|
remarkPlugins: [remarkMath],
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
output: 'static',
|
output: 'static',
|
||||||
})
|
})
|
||||||
|
|||||||
Generated
+11125
File diff suppressed because it is too large
Load Diff
@@ -39,6 +39,8 @@
|
|||||||
"jsdom": "^24.1.1",
|
"jsdom": "^24.1.1",
|
||||||
"linkedom": "^0.18.4",
|
"linkedom": "^0.18.4",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
|
"prettier": "^3.5.0",
|
||||||
|
"prettier-plugin-astro": "^0.14.1",
|
||||||
"rehype-autolink-headings": "^7.1.0",
|
"rehype-autolink-headings": "^7.1.0",
|
||||||
"rehype-slug": "^6.0.0",
|
"rehype-slug": "^6.0.0",
|
||||||
"remark-math": "^6.0.0",
|
"remark-math": "^6.0.0",
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 262 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 295 KiB |
@@ -34,21 +34,14 @@ export const ComboBox = ({
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div class="combobox" ref={comboRef} style={{ width: isMobile() ? undefined : itemWidth + 48 + 'px' }}>
|
||||||
class="combobox"
|
|
||||||
ref={comboRef}
|
|
||||||
style={{ width: isMobile() ? undefined : itemWidth + 48 + 'px' }}
|
|
||||||
>
|
|
||||||
<div class="selected" onClick={() => setOpen(!open)}>
|
<div class="selected" onClick={() => setOpen(!open)}>
|
||||||
<div class="content">{children[value]}</div>
|
<div class="content">{children[value]}</div>
|
||||||
{/* <span class="material-symbols-outlined">expand_more</span> */}
|
{/* <span class="material-symbols-outlined">expand_more</span> */}
|
||||||
<PhosphorIcon name="caret-down" />
|
<PhosphorIcon name="caret-down" />
|
||||||
</div>
|
</div>
|
||||||
{open && (
|
{open && (
|
||||||
<div
|
<div class={clsx('dropdown', cloak && 'invisible')} ref={el => el && setItemWidth(el.offsetWidth)}>
|
||||||
class={clsx('dropdown', cloak && 'invisible')}
|
|
||||||
ref={el => el && setItemWidth(el.offsetWidth)}
|
|
||||||
>
|
|
||||||
{Object.keys(children).map(key => (
|
{Object.keys(children).map(key => (
|
||||||
<div
|
<div
|
||||||
class="option"
|
class="option"
|
||||||
|
|||||||
@@ -2,6 +2,17 @@ import { useEffect, useState } from 'preact/hooks'
|
|||||||
import { Funnel } from '@phosphor-icons/react'
|
import { Funnel } from '@phosphor-icons/react'
|
||||||
import { marked } from 'marked'
|
import { marked } from 'marked'
|
||||||
|
|
||||||
|
import extendedLatex from '@/client/lib/marked-latex'
|
||||||
|
|
||||||
|
marked.use(
|
||||||
|
extendedLatex({
|
||||||
|
lazy: false,
|
||||||
|
render: (formula: string, display: boolean) => {
|
||||||
|
return display ? '$$' + formula + '$$' : '$' + formula + '$'
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
import type { Database } from '@/data/domande-esami.yaml'
|
import type { Database } from '@/data/domande-esami.yaml'
|
||||||
|
|
||||||
const useRemoteValue = <T,>(url: string): T | null => {
|
const useRemoteValue = <T,>(url: string): T | null => {
|
||||||
@@ -11,6 +22,7 @@ const useRemoteValue = <T,>(url: string): T | null => {
|
|||||||
fetch(url)
|
fetch(url)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(value => setValue(value))
|
.then(value => setValue(value))
|
||||||
|
.catch(error => console.error(error))
|
||||||
}, [url])
|
}, [url])
|
||||||
|
|
||||||
return value
|
return value
|
||||||
@@ -26,68 +38,59 @@ export const DomandeEsamiCourse = ({ course }: Props) => {
|
|||||||
return <>Loading...</>
|
return <>Loading...</>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ('requestIdleCallback' in window) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
requestIdleCallback(() => window.renderMath())
|
requestIdleCallback(() => window.renderMath())
|
||||||
|
} else {
|
||||||
console.log(database)
|
// @ts-ignore
|
||||||
|
setTimeout(() => window.renderMath(), 100)
|
||||||
|
}
|
||||||
|
|
||||||
const courseTags = [
|
const courseTags = [
|
||||||
...new Set(
|
...new Set(
|
||||||
database.questions
|
database.questions.filter(question => question.course === course).flatMap(question => question.tags),
|
||||||
.filter(question => question.course === course)
|
|
||||||
.flatMap(question => question.tags)
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
const [selectedTags, setSelectedTags] = useState<string[]>([])
|
const [selectedTag, setSelectedTag] = useState<string | null>(null)
|
||||||
|
|
||||||
const filteredQuestions = database.questions
|
const filteredQuestions = database.questions
|
||||||
.filter(question => question.course === course)
|
.filter(question => question.course === course)
|
||||||
.filter(
|
.filter(question => (selectedTag ? question.tags.includes(selectedTag) : true))
|
||||||
question => selectedTags.length === 0 || selectedTags.every(tag => question.tags.includes(tag))
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div class="grid-center">
|
<div class="grid-center text-center">
|
||||||
<h3>
|
<h3>
|
||||||
<a href="/domande-esami">Domande Esami</a>
|
<a href="/domande-esami">Domande Orali</a>
|
||||||
</h3>
|
</h3>
|
||||||
<h1>{database.names[course]}</h1>
|
<h1>{database.names[course]}</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{courseTags.length > 1 && (
|
||||||
<div class="card filter">
|
<div class="card filter">
|
||||||
<div class="grid-h">
|
<div class="grid-h">
|
||||||
<Funnel />
|
<Funnel />
|
||||||
<strong>Filtra Tag</strong>
|
<strong>Filtra Tag</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-row-wrap">
|
<div class="flex-row-wrap">
|
||||||
{selectedTags.length === 0
|
{!selectedTag
|
||||||
? courseTags.map(tag => (
|
? courseTags.map(tag => (
|
||||||
<div class="chip clickable" onClick={() => setSelectedTags([tag])}>
|
<div class="chip clickable" onClick={() => setSelectedTag(tag)}>
|
||||||
{tag}
|
{tag}
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
: courseTags.map(tag => (
|
: courseTags.map(tag => (
|
||||||
<div
|
<div
|
||||||
class={
|
class={tag === selectedTag ? 'chip clickable' : 'chip clickable disabled'}
|
||||||
selectedTags.includes(tag)
|
onClick={() => setSelectedTag(tag === selectedTag ? null : tag)}
|
||||||
? 'chip clickable'
|
|
||||||
: 'chip clickable disabled'
|
|
||||||
}
|
|
||||||
onClick={() =>
|
|
||||||
setSelectedTags(
|
|
||||||
selectedTags.includes(tag)
|
|
||||||
? selectedTags.filter(t => t !== tag)
|
|
||||||
: [...selectedTags, tag]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{tag}
|
{tag}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
<div class="wide-card-list" id="questions">
|
<div class="wide-card-list" id="questions">
|
||||||
{filteredQuestions.length === 0 ? (
|
{filteredQuestions.length === 0 ? (
|
||||||
<div class="grid-center">
|
<div class="grid-center">
|
||||||
|
|||||||
+2
-2
@@ -2,8 +2,8 @@ const icons = Object.fromEntries(
|
|||||||
Object.entries(
|
Object.entries(
|
||||||
import.meta.glob<{ default: ImageMetadata }>(`node_modules/@phosphor-icons/core/assets/light/*.svg`, {
|
import.meta.glob<{ default: ImageMetadata }>(`node_modules/@phosphor-icons/core/assets/light/*.svg`, {
|
||||||
eager: true,
|
eager: true,
|
||||||
})
|
}),
|
||||||
).map(([path, module]) => [path.split('/').pop()!.split('.')[0].replace('-light', ''), module])
|
).map(([path, module]) => [path.split('/').pop()!.split('.')[0].replace('-light', ''), module]),
|
||||||
)
|
)
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|||||||
@@ -0,0 +1,765 @@
|
|||||||
|
import { useState, useEffect } from 'preact/hooks'
|
||||||
|
import { render } from 'preact'
|
||||||
|
|
||||||
|
// Tipi per la gestione dei dati
|
||||||
|
type TipoStudente = 'triennale' | 'magistrale'
|
||||||
|
|
||||||
|
interface Corso {
|
||||||
|
nome: string
|
||||||
|
anno: '1' | '2' | '3' | 'M' | 'istituzioni'
|
||||||
|
cfu: number
|
||||||
|
passFailOnly?: boolean // Per materie senza voto (pass/fail)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CorsoSelezionato {
|
||||||
|
id: string
|
||||||
|
nome: string
|
||||||
|
cfu: number
|
||||||
|
voto: number | null
|
||||||
|
lode: boolean
|
||||||
|
passFailOnly?: boolean // Per materie senza voto (pass/fail)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CorsoCustom {
|
||||||
|
nome: string
|
||||||
|
cfu: number
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dati dei corsi aggiornati dalla tabella ufficiale
|
||||||
|
const CORSI_DISPONIBILI: Corso[] = [
|
||||||
|
// Primo Anno
|
||||||
|
{ nome: 'Analisi matematica 1', anno: '1', cfu: 15 },
|
||||||
|
{ nome: 'Aritmetica', anno: '1', cfu: 9 },
|
||||||
|
{ nome: 'Fisica I con laboratorio', anno: '1', cfu: 9 },
|
||||||
|
{ nome: 'Fondamenti di programmazione con laboratorio', anno: '1', cfu: 9 },
|
||||||
|
{ nome: 'Geometria 1', anno: '1', cfu: 15 },
|
||||||
|
{ nome: 'Laboratorio di introduzione alla matematica computazionale', anno: '1', cfu: 6, passFailOnly: true },
|
||||||
|
{ nome: 'Laboratorio di comunicazione mediante calcolatore', anno: '1', cfu: 3, passFailOnly: true },
|
||||||
|
|
||||||
|
// Secondo Anno
|
||||||
|
{ nome: 'Algebra 1', anno: '2', cfu: 6 },
|
||||||
|
{ nome: 'Algoritmi e strutture dati', anno: '2', cfu: 6 },
|
||||||
|
{ nome: 'Analisi matematica 2', anno: '2', cfu: 12 },
|
||||||
|
{ nome: 'Analisi numerica con laboratorio', anno: '2', cfu: 9 },
|
||||||
|
{ nome: 'Elementi di probabilità e statistica', anno: '2', cfu: 6 },
|
||||||
|
{ nome: 'Geometria 2', anno: '2', cfu: 12 },
|
||||||
|
{ nome: 'Inglese scientifico', anno: '2', cfu: 6, passFailOnly: true },
|
||||||
|
{ nome: 'Laboratorio didattico di matematica computazionale', anno: '2', cfu: 3, passFailOnly: true },
|
||||||
|
|
||||||
|
// Terzo Anno
|
||||||
|
{ nome: 'Algebra 2', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Analisi matematica 3', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Analisi reale', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Calcolo scientifico', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Elementi di analisi complessa', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Elementi di calcolo delle variazioni', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Elementi di geometria algebrica', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Elementi di meccanica celeste', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Elementi di teoria degli insiemi', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Elementi di teoria delle rappresentazioni', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Elementi di topologia algebrica', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Equazioni alle derivate parziali', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Fisica II', anno: '3', cfu: 9 },
|
||||||
|
{ nome: 'Fisica III', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Geometria e topologia differenziale', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Gruppi e rappresentazioni', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Laboratorio computazionale', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Linguaggi di programmazione con laboratorio', anno: '3', cfu: 9 },
|
||||||
|
{ nome: 'Logica matematica', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Matematiche elementari da un punto di vista superiore: aritmetica', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Matematiche elementari da un punto di vista superiore: geometria', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Meccanica razionale', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Metodi numerici per equazioni differenziali ordinarie', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Metodi topologici in analisi globale', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Ottimizzazione non lineare', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Probabilità', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Ricerca operativa', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Sistemi dinamici', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Spazi di Sobolev', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Statistica matematica', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Storia della matematica', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Teoria algebrica dei numeri 1', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Teoria dei campi e teoria di Galois', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Teoria dei numeri elementare', anno: '3', cfu: 6 },
|
||||||
|
{ nome: 'Teoria della misura', anno: '3', cfu: 6 },
|
||||||
|
|
||||||
|
// Istituzioni (Magistrale)
|
||||||
|
{ nome: 'Istituzioni di algebra', anno: 'istituzioni', cfu: 11 },
|
||||||
|
{ nome: 'Istituzioni di analisi matematica', anno: 'istituzioni', cfu: 11 },
|
||||||
|
{ nome: 'Istituzioni di analisi numerica', anno: 'istituzioni', cfu: 11 },
|
||||||
|
{ nome: 'Istituzioni di didattica della matematica', anno: 'istituzioni', cfu: 11 },
|
||||||
|
{ nome: 'Istituzioni di fisica matematica', anno: 'istituzioni', cfu: 11 },
|
||||||
|
{ nome: 'Istituzioni di geometria', anno: 'istituzioni', cfu: 11 },
|
||||||
|
{ nome: 'Istituzioni di probabilità', anno: 'istituzioni', cfu: 11 },
|
||||||
|
|
||||||
|
// Materie a scelta (Magistrale)
|
||||||
|
{ nome: '4-varietà', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Algebra superiore A', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Algebre e gruppi di Lie', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Analisi armonica', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Analisi complessa A', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Analisi complessa B', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Analisi convessa', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Analisi dei dati', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Analisi non standard', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Analisi reale', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Analisi su spazi gaussiani', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Analisi superiore', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Analisi superiore A', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Analisi superiore B', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Aspetti matematici nella computazione quantistica', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Calcolo delle variazioni B', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Calcolo della variazioni A', anno: 'M', cfu: 6 }, // Variante nome
|
||||||
|
{ nome: 'Combinatoria algebrica', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Complementi di analisi funzionale', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Complementi di meccanica razionale', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Crittografia post-quantistica', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Curve ellittiche', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Determinazione orbitale', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Didattica della matematica e nuove tecnologie', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Dinamica del sistema solare', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Dinamica iperbolica', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Dinamica olomorfa', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Elementi di calcolo in gruppi omogenei', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Equazioni della fluidodinamica', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Equazioni differenziali stocastiche e applicazioni', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Equazioni ellittiche', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Finanza matematica', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Fisica matematica', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Forme modulari', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Geometria algebrica B', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Geometria algebrica C', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Geometria algebrica complessa', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Geometria algebrica D', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Geometria algebrica E', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Geometria algebrica F', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Geometria algebrica G', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Geometria e analisi complessa', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Geometria differenziale complessa', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Geometria iperbolica', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Geometria riemanniana', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Gruppi algebrici lineari', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Gruppi di Coxeter', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Gruppi di Galois e gruppi fondamentali', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Meccanica celeste', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Meccanica spaziale', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Meccanica superiore', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Metodi di analisi armonica in analisi non lineare', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Metodi di approssimazione', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Metodi matematici della crittografia', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Metodi matematici della meccanica quantistica', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Metodi numerici per catene di Markov', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Metodi numerici per equazioni alle derivate parziali', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Metodi numerici per il calcolo tensoriale', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Metodi numerici per il controllo ottimo', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Metodi numerici per la grafica', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Metodi numerici per problemi inversi', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: "Metodi probabilistici per l'algebra lineare numerica", anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Modelli matematici in biomedicina e fisica matematica', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Origini e sviluppo delle matematiche moderne', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Probabilità superiore', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Problemi e metodi della ricerca in didattica della matematica', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Problemi e metodi in storia della matematica', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Sistemi dinamici aleatori', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Statistica superiore', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Storia della matematica antica e della sua tradizione', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Superfici di Riemann e curve algebriche', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Tecnologie per la didattica', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Teoria algebrica dei numeri 2', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Teoria analitica dei numeri A', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Teoria dei giochi', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Teoria dei modelli', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Teoria dei nodi A', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Teoria degli insiemi', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Teoria degli insiemi A', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Teoria degli insiemi B', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Teoria delle categorie', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Teoria delle rappresentazioni A', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: "Teoria e metodi dell'ottimizzazione", anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Teoria ergodica', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Teoria geometrica della misura', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Topologia algebrica', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Topologia algebrica A', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Topologia algebrica B', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Topologia differenziale', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Topologia e geometria in bassa dimensione', anno: 'M', cfu: 6 },
|
||||||
|
{ nome: 'Ultrafiltri e metodi non-standard', anno: 'M', cfu: 6 },
|
||||||
|
]
|
||||||
|
|
||||||
|
export function MediaPesataApp() {
|
||||||
|
// Funzioni per localStorage
|
||||||
|
const loadFromStorage = () => {
|
||||||
|
try {
|
||||||
|
const savedData = localStorage.getItem('media-pesata-data')
|
||||||
|
if (savedData) {
|
||||||
|
const parsed = JSON.parse(savedData)
|
||||||
|
return {
|
||||||
|
tipoStudente: parsed.tipoStudente || 'triennale',
|
||||||
|
corsiSelezionati: parsed.corsiSelezionati || [],
|
||||||
|
sezioniAperte: parsed.sezioniAperte || {},
|
||||||
|
mostraRisultati: parsed.mostraRisultati || false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Errore nel caricamento dei dati salvati:', error)
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
tipoStudente: 'triennale' as TipoStudente,
|
||||||
|
corsiSelezionati: [],
|
||||||
|
sezioniAperte: {},
|
||||||
|
mostraRisultati: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveToStorage = (data: any) => {
|
||||||
|
try {
|
||||||
|
localStorage.setItem('media-pesata-data', JSON.stringify(data))
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Errore nel salvataggio dei dati:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inizializzazione con dati salvati
|
||||||
|
// const initialData = loadFromStorage()
|
||||||
|
const [tipoStudente, setTipoStudente] = useState<TipoStudente>('triennale')
|
||||||
|
const [corsiSelezionati, setCorsiSelezionati] = useState<CorsoSelezionato[]>([])
|
||||||
|
const [showCustomForm, setShowCustomForm] = useState(false)
|
||||||
|
const [customCorso, setCustomCorso] = useState<CorsoCustom>({ nome: '', cfu: 0 })
|
||||||
|
const [sezioniAperte, setSezioniAperte] = useState<Record<string, boolean>>({})
|
||||||
|
const [mostraRisultati, setMostraRisultati] = useState(false)
|
||||||
|
|
||||||
|
// Load data from localStorage on mount
|
||||||
|
useEffect(() => {
|
||||||
|
const initialData = loadFromStorage()
|
||||||
|
setTipoStudente(initialData.tipoStudente)
|
||||||
|
setCorsiSelezionati(initialData.corsiSelezionati)
|
||||||
|
setSezioniAperte(initialData.sezioniAperte)
|
||||||
|
setMostraRisultati(initialData.mostraRisultati)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
// Salva automaticamente quando cambiano i dati importanti
|
||||||
|
useEffect(() => {
|
||||||
|
const dataToSave = {
|
||||||
|
tipoStudente,
|
||||||
|
corsiSelezionati,
|
||||||
|
sezioniAperte,
|
||||||
|
mostraRisultati,
|
||||||
|
}
|
||||||
|
saveToStorage(dataToSave)
|
||||||
|
}, [tipoStudente, corsiSelezionati, sezioniAperte, mostraRisultati])
|
||||||
|
|
||||||
|
const toggleSezione = (nomeSezione: string) => {
|
||||||
|
setSezioniAperte(prev => ({
|
||||||
|
...prev,
|
||||||
|
[nomeSezione]: !prev[nomeSezione],
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
const calcolaMedia = () => {
|
||||||
|
const corsiConVoto = corsiSelezionati.filter(corso => corso.voto !== null && !corso.passFailOnly)
|
||||||
|
if (corsiConVoto.length === 0) {
|
||||||
|
alert('Inserisci almeno un voto per calcolare la media!')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setMostraRisultati(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Funzioni per la gestione dei corsi
|
||||||
|
const aggiungiCorso = (corso: Corso) => {
|
||||||
|
// Controlla se la materia esiste già
|
||||||
|
const materiaEsiste = corsiSelezionati.some(c => c.nome.toLowerCase() === corso.nome.toLowerCase())
|
||||||
|
if (materiaEsiste) {
|
||||||
|
alert('Questa materia è già stata aggiunta')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Controllo per magistrali: massimo 3 istituzioni
|
||||||
|
if (tipoStudente === 'magistrale' && corso.anno === 'istituzioni') {
|
||||||
|
const istituzioniAttuali = corsiSelezionati.filter(c => c.nome.toLowerCase().includes('istituzioni')).length
|
||||||
|
if (istituzioniAttuali >= 3) {
|
||||||
|
alert('Puoi selezionare al massimo 3 istituzioni per la magistrale')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const id = Date.now().toString()
|
||||||
|
const nuovoCorso: CorsoSelezionato = {
|
||||||
|
id,
|
||||||
|
nome: corso.nome,
|
||||||
|
cfu: corso.cfu,
|
||||||
|
voto: null,
|
||||||
|
lode: false,
|
||||||
|
passFailOnly: corso.passFailOnly,
|
||||||
|
}
|
||||||
|
setCorsiSelezionati([...corsiSelezionati, nuovoCorso])
|
||||||
|
}
|
||||||
|
|
||||||
|
const aggiungiCorsoCustom = () => {
|
||||||
|
// Validazioni
|
||||||
|
if (!customCorso.nome.trim()) {
|
||||||
|
alert('Il nome della materia non può essere vuoto')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (customCorso.cfu <= 0 || customCorso.cfu > 30) {
|
||||||
|
alert('I CFU devono essere tra 1 e 30')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!Number.isInteger(customCorso.cfu)) {
|
||||||
|
alert('I CFU devono essere un numero intero')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Controlla se la materia esiste già
|
||||||
|
const materiaEsiste = corsiSelezionati.some(
|
||||||
|
corso => corso.nome.toLowerCase().trim() === customCorso.nome.toLowerCase().trim(),
|
||||||
|
)
|
||||||
|
if (materiaEsiste) {
|
||||||
|
alert('Questa materia è già stata aggiunta')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const id = Date.now().toString()
|
||||||
|
const nuovoCorso: CorsoSelezionato = {
|
||||||
|
id,
|
||||||
|
nome: customCorso.nome.trim(),
|
||||||
|
cfu: customCorso.cfu,
|
||||||
|
voto: null,
|
||||||
|
lode: false,
|
||||||
|
}
|
||||||
|
setCorsiSelezionati([...corsiSelezionati, nuovoCorso])
|
||||||
|
setCustomCorso({ nome: '', cfu: 0 })
|
||||||
|
setShowCustomForm(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const rimuoviCorso = (id: string) => {
|
||||||
|
setCorsiSelezionati(corsiSelezionati.filter(corso => corso.id !== id))
|
||||||
|
}
|
||||||
|
|
||||||
|
const aggiornaVoto = (id: string, voto: number | null) => {
|
||||||
|
// Validazione voto: deve essere tra 18 e 30 e intero
|
||||||
|
if (voto !== null && (voto < 18 || voto > 30 || !Number.isInteger(voto))) {
|
||||||
|
return // Ignora valori non validi
|
||||||
|
}
|
||||||
|
|
||||||
|
setCorsiSelezionati(
|
||||||
|
corsiSelezionati.map(corso =>
|
||||||
|
corso.id === id ? { ...corso, voto, lode: voto !== 30 ? false : corso.lode } : corso,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const aggiornaLode = (id: string, lode: boolean) => {
|
||||||
|
setCorsiSelezionati(corsiSelezionati.map(corso => (corso.id === id ? { ...corso, lode } : corso)))
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetTutto = () => {
|
||||||
|
if (corsiSelezionati.length > 0) {
|
||||||
|
if (confirm('Sei sicuro di voler cancellare tutte le materie selezionate?')) {
|
||||||
|
setCorsiSelezionati([])
|
||||||
|
setCustomCorso({ nome: '', cfu: 0 })
|
||||||
|
setShowCustomForm(false)
|
||||||
|
setSezioniAperte({})
|
||||||
|
setMostraRisultati(false)
|
||||||
|
// Pulisce anche il localStorage
|
||||||
|
try {
|
||||||
|
localStorage.removeItem('media-pesata-data')
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Errore nella pulizia del localStorage:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calcoli della media pesata
|
||||||
|
const calcolaMediaPesata = () => {
|
||||||
|
// Escludi le materie pass/fail dal calcolo
|
||||||
|
const corsiConVoto = corsiSelezionati.filter(corso => corso.voto !== null && !corso.passFailOnly)
|
||||||
|
if (corsiConVoto.length === 0) {
|
||||||
|
return {
|
||||||
|
mediaPesata: 0,
|
||||||
|
votoAmmissione: 0,
|
||||||
|
massimoVotoLaurea: 0,
|
||||||
|
conLode: false,
|
||||||
|
bonusLodi: 0,
|
||||||
|
errore: 'Nessun voto inserito per il calcolo della media',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calcola CFU totali con voto
|
||||||
|
const cfuTotaliConVoto = corsiConVoto.reduce((sum, corso) => sum + corso.cfu, 0)
|
||||||
|
const cfuDaEscludere = tipoStudente === 'triennale' ? 15 : 9
|
||||||
|
|
||||||
|
// Se i CFU sono insufficienti per l'esclusione, avvisa l'utente
|
||||||
|
if (cfuTotaliConVoto < cfuDaEscludere) {
|
||||||
|
return {
|
||||||
|
mediaPesata: 0,
|
||||||
|
votoAmmissione: 0,
|
||||||
|
massimoVotoLaurea: 0,
|
||||||
|
conLode: false,
|
||||||
|
bonusLodi: 0,
|
||||||
|
errore: `Hai inserito solo ${cfuTotaliConVoto} CFU con voto. Servono almeno ${cfuDaEscludere} CFU per applicare le regole di esclusione.`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ordina per voto crescente
|
||||||
|
const corsiOrdinati = [...corsiConVoto].sort((a, b) => a.voto! - b.voto!)
|
||||||
|
|
||||||
|
let cfuEsclusi = 0
|
||||||
|
const corsiValidi: CorsoSelezionato[] = []
|
||||||
|
|
||||||
|
for (const corso of corsiOrdinati) {
|
||||||
|
if (cfuEsclusi < cfuDaEscludere) {
|
||||||
|
const cfuRimanentiDaEscludere = cfuDaEscludere - cfuEsclusi
|
||||||
|
if (corso.cfu <= cfuRimanentiDaEscludere) {
|
||||||
|
// Escludi tutto il corso
|
||||||
|
cfuEsclusi += corso.cfu
|
||||||
|
} else {
|
||||||
|
// Escludi solo una parte del corso
|
||||||
|
const cfuValidi = corso.cfu - cfuRimanentiDaEscludere
|
||||||
|
corsiValidi.push({ ...corso, cfu: cfuValidi })
|
||||||
|
cfuEsclusi = cfuDaEscludere
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
corsiValidi.push(corso)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calcola media pesata
|
||||||
|
const sommaPesata = corsiValidi.reduce((sum, corso) => sum + corso.voto! * corso.cfu, 0)
|
||||||
|
const sommaCfu = corsiValidi.reduce((sum, corso) => sum + corso.cfu, 0)
|
||||||
|
|
||||||
|
const mediaPesata = sommaCfu > 0 ? sommaPesata / sommaCfu : 0
|
||||||
|
|
||||||
|
// Calcola bonus lodi
|
||||||
|
const bonusLodi = corsiConVoto.reduce((bonus, corso) => {
|
||||||
|
if (corso.lode) {
|
||||||
|
return bonus + (corso.cfu > 6 ? 0.5 : 0.25)
|
||||||
|
}
|
||||||
|
return bonus
|
||||||
|
}, 0)
|
||||||
|
|
||||||
|
// Cap del bonus lodi basato sul tipo di studente
|
||||||
|
const capBonusLodi = tipoStudente === 'triennale' ? 1.5 : 2
|
||||||
|
const bonusLodiFinal = Math.min(bonusLodi, capBonusLodi)
|
||||||
|
|
||||||
|
// Voto di ammissione alla laurea (media pesata * 11/3)
|
||||||
|
const votoAmmissione = (mediaPesata * 11) / 3
|
||||||
|
|
||||||
|
// Voto di ammissione finale = voto ammissione + bonus lodi
|
||||||
|
const votoAmmissioneFinale = votoAmmissione + bonusLodiFinal
|
||||||
|
|
||||||
|
// Massimo voto di laurea possibile = voto ammissione + 10 (cappato a 110)
|
||||||
|
const massimoVotoLaurea = Math.min(votoAmmissioneFinale + 10, 110)
|
||||||
|
const conLode = massimoVotoLaurea === 110
|
||||||
|
|
||||||
|
return {
|
||||||
|
mediaPesata: Math.round(mediaPesata * 100) / 100,
|
||||||
|
votoAmmissione: Math.round(votoAmmissioneFinale * 100) / 100,
|
||||||
|
massimoVotoLaurea: Math.round(massimoVotoLaurea * 100) / 100,
|
||||||
|
conLode,
|
||||||
|
bonusLodi: Math.round(bonusLodiFinal * 100) / 100,
|
||||||
|
errore: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filtra corsi disponibili in base al tipo di studente
|
||||||
|
const getCorsiDisponibili = () => {
|
||||||
|
if (tipoStudente === 'triennale') {
|
||||||
|
return CORSI_DISPONIBILI.filter(corso => corso.anno !== 'istituzioni')
|
||||||
|
} else {
|
||||||
|
return CORSI_DISPONIBILI.filter(
|
||||||
|
corso => corso.anno === 'istituzioni' || corso.anno === '3' || corso.anno === 'M',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Raggruppa corsi per categoria
|
||||||
|
const raggruppaCorsi = () => {
|
||||||
|
const corsi = getCorsiDisponibili()
|
||||||
|
const gruppi: Record<string, Corso[]> = {}
|
||||||
|
|
||||||
|
if (tipoStudente === 'triennale') {
|
||||||
|
gruppi['Primo Anno'] = corsi.filter(c => c.anno === '1')
|
||||||
|
gruppi['Secondo Anno'] = corsi.filter(c => c.anno === '2')
|
||||||
|
gruppi['Terzo Anno'] = corsi.filter(c => c.anno === '3')
|
||||||
|
gruppi['Materie a Scelta'] = corsi.filter(c => c.anno === 'M')
|
||||||
|
} else {
|
||||||
|
// Per magistrali: prima le istituzioni, poi tutto il resto come "Materie a Scelta"
|
||||||
|
gruppi['Istituzioni'] = corsi.filter(c => c.anno === 'istituzioni')
|
||||||
|
gruppi['Materie a Scelta'] = corsi.filter(c => c.anno === '3' || c.anno === 'M')
|
||||||
|
}
|
||||||
|
|
||||||
|
return gruppi
|
||||||
|
}
|
||||||
|
|
||||||
|
const cambiaTipoStudente = (nuovoTipo: TipoStudente) => {
|
||||||
|
setTipoStudente(nuovoTipo)
|
||||||
|
}
|
||||||
|
|
||||||
|
const gruppiCorsi = raggruppaCorsi()
|
||||||
|
const risultati = calcolaMediaPesata()
|
||||||
|
const totaleCfu = corsiSelezionati.reduce((sum, corso) => sum + corso.cfu, 0)
|
||||||
|
const maxCfu = tipoStudente === 'triennale' ? 171 : 93 // 180 − 9 e 120 − 27 per la tesi
|
||||||
|
const cfuError = totaleCfu > maxCfu
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="media-pesata-app">
|
||||||
|
{/* Selezione tipo studente */}
|
||||||
|
<div class="card student-type-switcher wide">
|
||||||
|
<div class="grid-center">
|
||||||
|
<h2>Corso di Laurea</h2>
|
||||||
|
<div class="compound-button">
|
||||||
|
<button
|
||||||
|
class={tipoStudente === 'triennale' ? 'active' : ''}
|
||||||
|
onClick={() => cambiaTipoStudente('triennale')}
|
||||||
|
>
|
||||||
|
Triennale
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class={tipoStudente === 'magistrale' ? 'active' : ''}
|
||||||
|
onClick={() => cambiaTipoStudente('magistrale')}
|
||||||
|
>
|
||||||
|
Magistrale
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Counter CFU */}
|
||||||
|
<div class={`cfu-counter wide ${cfuError ? 'error' : ''}`}>
|
||||||
|
<h3>
|
||||||
|
CFU Totali: {totaleCfu}/{maxCfu}
|
||||||
|
{tipoStudente === 'triennale' ? ' (+9 tesi)' : ' (+27 tesi)'}
|
||||||
|
</h3>
|
||||||
|
{cfuError && <p class="error-text">⚠️ Hai superato il limite di CFU consentiti!</p>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Sezione selezione corsi */}
|
||||||
|
<div class="card">
|
||||||
|
<div class="title">
|
||||||
|
<h2>Seleziona Materie</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{Object.entries(gruppiCorsi).map(([categoria, corsi]) => (
|
||||||
|
<div key={categoria} class="course-category">
|
||||||
|
<button onClick={() => toggleSezione(categoria)}>
|
||||||
|
<div class="h-flex">
|
||||||
|
{categoria}
|
||||||
|
<div class="spacer"></div>
|
||||||
|
<span class={`toggle-icon ${sezioniAperte[categoria] ? 'expanded' : ''}`}>▶</span>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{sezioniAperte[categoria] && (
|
||||||
|
<div class="course-grid">
|
||||||
|
{corsi.map((corso, index) => (
|
||||||
|
<button
|
||||||
|
key={index}
|
||||||
|
class="course-button"
|
||||||
|
onClick={() => aggiungiCorso(corso)}
|
||||||
|
disabled={corsiSelezionati.some(c => c.nome === corso.nome)}
|
||||||
|
>
|
||||||
|
<span class="course-name">{corso.nome}</span>
|
||||||
|
<span class="course-cfu">{corso.cfu} CFU</span>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{/* Form per materia custom */}
|
||||||
|
<div class="custom-course">
|
||||||
|
<h3>Materia Personalizzata</h3>
|
||||||
|
{!showCustomForm ? (
|
||||||
|
<button onClick={() => setShowCustomForm(true)}>+ Aggiungi Materia Personalizzata</button>
|
||||||
|
) : (
|
||||||
|
<div class="custom-form">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Nome materia"
|
||||||
|
value={customCorso.nome}
|
||||||
|
onChange={e =>
|
||||||
|
setCustomCorso({ ...customCorso, nome: (e.target as HTMLInputElement).value })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
placeholder="CFU"
|
||||||
|
min="1"
|
||||||
|
max="30"
|
||||||
|
step="1"
|
||||||
|
value={customCorso.cfu || ''}
|
||||||
|
onChange={e =>
|
||||||
|
setCustomCorso({
|
||||||
|
...customCorso,
|
||||||
|
cfu: parseInt((e.target as HTMLInputElement).value) || 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<button onClick={aggiungiCorsoCustom}>Aggiungi</button>
|
||||||
|
<button onClick={() => setShowCustomForm(false)}>Annulla</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Sezione lista corsi selezionati */}
|
||||||
|
<div class="card">
|
||||||
|
<div class="h-flex">
|
||||||
|
<div class="title">
|
||||||
|
<h2>Materie Selezionate</h2>
|
||||||
|
</div>
|
||||||
|
<div class="spacer"></div>
|
||||||
|
{corsiSelezionati.length > 0 && <button onClick={resetTutto}>🗑️ Cancella Tutto</button>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{corsiSelezionati.length === 0 ? (
|
||||||
|
<p>Nessuna materia selezionata</p>
|
||||||
|
) : (
|
||||||
|
<div class="courses-list">
|
||||||
|
{corsiSelezionati.map(corso => (
|
||||||
|
<div key={corso.id} class="course-item">
|
||||||
|
<span class="course-name">{corso.nome}</span>
|
||||||
|
<span class="course-cfu">{corso.cfu} CFU</span>
|
||||||
|
|
||||||
|
{!corso.passFailOnly && (
|
||||||
|
<div class="course-grade tall">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
placeholder="Voto"
|
||||||
|
min="18"
|
||||||
|
max="30"
|
||||||
|
step="1"
|
||||||
|
value={corso.voto || ''}
|
||||||
|
onChange={e =>
|
||||||
|
aggiornaVoto(
|
||||||
|
corso.id,
|
||||||
|
parseInt((e.target as HTMLInputElement).value) || null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<label class={`lode-checkbox ${corso.voto !== 30 ? 'disabled' : ''}`}>
|
||||||
|
<input
|
||||||
|
class="star"
|
||||||
|
type="checkbox"
|
||||||
|
checked={corso.lode}
|
||||||
|
disabled={corso.voto !== 30}
|
||||||
|
onChange={e =>
|
||||||
|
aggiornaLode(corso.id, (e.target as HTMLInputElement).checked)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
Lode
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div class="actions tall">
|
||||||
|
<button
|
||||||
|
class="icon remove-btn"
|
||||||
|
onClick={() => rimuoviCorso(corso.id)}
|
||||||
|
title="Rimuovi materia"
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Pulsante Calcola */}
|
||||||
|
{corsiSelezionati.length > 0 && (
|
||||||
|
<div class="calculate-section wide">
|
||||||
|
<button onClick={calcolaMedia}>🧮 Calcola Media e Voto di Laurea</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Risultati */}
|
||||||
|
{risultati && mostraRisultati && (
|
||||||
|
<div class="results wide">
|
||||||
|
<h2>Risultati</h2>
|
||||||
|
{risultati.errore ? (
|
||||||
|
<div class="error-message">
|
||||||
|
<p>⚠️ {risultati.errore}</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div class="results-grid">
|
||||||
|
<div class="result-item">
|
||||||
|
<span class="label">Media Pesata:</span>
|
||||||
|
<span class="value">{risultati.mediaPesata}</span>
|
||||||
|
</div>
|
||||||
|
<div class="result-item">
|
||||||
|
<span class="label">Bonus Lodi:</span>
|
||||||
|
<span class="value">+{risultati.bonusLodi}</span>
|
||||||
|
</div>
|
||||||
|
<div class="result-item highlight">
|
||||||
|
<span class="label">Voto di Ammissione:</span>
|
||||||
|
<span class="value">{risultati.votoAmmissione}</span>
|
||||||
|
</div>
|
||||||
|
<div class="result-item highlight">
|
||||||
|
<span class="label">Massimo Voto Di Laurea Possibile:</span>
|
||||||
|
<span class="value">
|
||||||
|
{risultati.massimoVotoLaurea}
|
||||||
|
{risultati.conLode && <span class="lode-badge">(+lode)</span>}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Nota informativa */}
|
||||||
|
<div class="card wide">
|
||||||
|
<h3>📋 Come viene calcolata la media</h3>
|
||||||
|
<div class="info-content">
|
||||||
|
<h4>Regole di esclusione CFU:</h4>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<strong>Triennale:</strong> I 15 CFU con i voti più bassi vengono esclusi dalla media
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Magistrale:</strong> I 9 CFU con i voti più bassi vengono esclusi dalla media
|
||||||
|
</li>
|
||||||
|
<li>Se un corso ha più CFU di quelli da escludere, viene diviso proporzionalmente</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4>Calcolo del voto finale:</h4>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<strong>Media pesata:</strong> Somma dei (voto × CFU) diviso per i CFU totali
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Bonus lodi:</strong> +0.5 per lodi in materie > 6 CFU, +0.25 per lodi in materie
|
||||||
|
≤ 6 CFU (max +1.5 per triennale, max +2 per magistrale)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Voto di laurea:</strong> (Voto finale × 11) ÷ 3
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4>Note:</h4>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Le materie <strong>Pass/Fail</strong> non contribuiscono al calcolo della media
|
||||||
|
</li>
|
||||||
|
<li>Il voto finale è limitato a 30</li>
|
||||||
|
<li>Per i magistrali: massimo 3 istituzioni selezionabili</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Funzione per inizializzare l'app
|
||||||
|
// export function initMediaPesataApp() {
|
||||||
|
// const container = document.getElementById('media-pesata-app')
|
||||||
|
// if (container) {
|
||||||
|
// render(<MediaPesataApp />, container)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// export default MediaPesataApp
|
||||||
@@ -69,21 +69,21 @@ export const UtentiPage = () => {
|
|||||||
? $utentiData.value.filter(user => MACCHINISTI.includes(user.uid))
|
? $utentiData.value.filter(user => MACCHINISTI.includes(user.uid))
|
||||||
: $filter.value === 'rappstud'
|
: $filter.value === 'rappstud'
|
||||||
? $utentiData.value.filter(user => RAPPSTUD.includes(user.uid))
|
? $utentiData.value.filter(user => RAPPSTUD.includes(user.uid))
|
||||||
: $utentiData.value
|
: $utentiData.value,
|
||||||
)
|
)
|
||||||
|
|
||||||
const $fuse = useComputed(
|
const $fuse = useComputed(
|
||||||
() =>
|
() =>
|
||||||
new Fuse($filteredData.value, {
|
new Fuse($filteredData.value, {
|
||||||
keys: ['gecos', 'uid'],
|
keys: ['gecos', 'uid'],
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
const $searchText = useSignal('')
|
const $searchText = useSignal('')
|
||||||
const $searchResults = useComputed(() =>
|
const $searchResults = useComputed(() =>
|
||||||
$searchText.value.trim().length > 0
|
$searchText.value.trim().length > 0
|
||||||
? $fuse.value?.search($searchText.value).map(result => result.item) ?? []
|
? ($fuse.value?.search($searchText.value).map(result => result.item) ?? [])
|
||||||
: $filteredData.value
|
: $filteredData.value,
|
||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -110,7 +110,7 @@ export const UtentiPage = () => {
|
|||||||
<PhosphorIcon name={v.icon} />
|
<PhosphorIcon name={v.icon} />
|
||||||
{v.label}
|
{v.label}
|
||||||
</>,
|
</>,
|
||||||
])
|
]),
|
||||||
)}
|
)}
|
||||||
</ComboBox>
|
</ComboBox>
|
||||||
<div class="search">
|
<div class="search">
|
||||||
@@ -149,10 +149,7 @@ export const UtentiPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="text">{poissonUser.gecos}</div>
|
<div class="text">{poissonUser.gecos}</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<a
|
<a href={`https://poisson.phc.dm.unipi.it/~${poissonUser.uid}`} target="_blank">
|
||||||
href={`https://poisson.phc.dm.unipi.it/~${poissonUser.uid}`}
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
{/* <span class="material-symbols-outlined">open_in_new</span> */}
|
{/* <span class="material-symbols-outlined">open_in_new</span> */}
|
||||||
<PhosphorIcon name="arrow-square-out" />
|
<PhosphorIcon name="arrow-square-out" />
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
const $debugConsole = document.createElement('div')
|
||||||
|
|
||||||
|
$debugConsole.style.position = 'fixed'
|
||||||
|
$debugConsole.style.bottom = '0'
|
||||||
|
$debugConsole.style.left = '0'
|
||||||
|
$debugConsole.style.width = '100%'
|
||||||
|
$debugConsole.style.height = '25vh'
|
||||||
|
$debugConsole.style.backgroundColor = 'black'
|
||||||
|
$debugConsole.style.color = 'white'
|
||||||
|
$debugConsole.style.overflow = 'auto'
|
||||||
|
$debugConsole.style.padding = '10px'
|
||||||
|
$debugConsole.style.boxSizing = 'border-box'
|
||||||
|
$debugConsole.style.fontFamily = 'monospace'
|
||||||
|
$debugConsole.style.zIndex = '9999'
|
||||||
|
$debugConsole.style.fontSize = '15px'
|
||||||
|
$debugConsole.style.opacity = '0.8'
|
||||||
|
|
||||||
|
document.body.appendChild($debugConsole)
|
||||||
|
|
||||||
|
function logDebugConsole(...args) {
|
||||||
|
$debugConsole.innerHTML += args.join(' ') + '<br>'
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error = logDebugConsole
|
||||||
|
console.warn = logDebugConsole
|
||||||
|
console.log = logDebugConsole
|
||||||
|
console.debug = logDebugConsole
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
// took from: https://github.com/sxyazi/marked-extended-latex
|
||||||
|
// this has a peer dependency bug
|
||||||
|
|
||||||
|
const CLASS_NAME = 'latex-b172fea480b'
|
||||||
|
|
||||||
|
const extBlock = options => ({
|
||||||
|
name: 'latex-block',
|
||||||
|
level: 'block',
|
||||||
|
start(src) {
|
||||||
|
return src.match(/\$\$[^\$]/)?.index ?? -1
|
||||||
|
},
|
||||||
|
tokenizer(src, tokens) {
|
||||||
|
const match = /^\$\$([^\$]+)\$\$/.exec(src)
|
||||||
|
return match ? { type: 'latex-block', raw: match[0], formula: match[1] } : undefined
|
||||||
|
},
|
||||||
|
renderer(token) {
|
||||||
|
if (!options.lazy) return options.render(token.formula, true)
|
||||||
|
return `<span class="${CLASS_NAME}" block>${token.formula}</span>`
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const extInline = options => ({
|
||||||
|
name: 'latex',
|
||||||
|
level: 'inline',
|
||||||
|
start(src) {
|
||||||
|
return src.match(/\$[^\$]/)?.index ?? -1
|
||||||
|
},
|
||||||
|
tokenizer(src, tokens) {
|
||||||
|
const match = /^\$([^\$]+)\$/.exec(src)
|
||||||
|
return match ? { type: 'latex', raw: match[0], formula: match[1] } : undefined
|
||||||
|
},
|
||||||
|
renderer(token) {
|
||||||
|
if (!options.lazy) return options.render(token.formula, false)
|
||||||
|
return `<span class="${CLASS_NAME}">${token.formula}</span>`
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
let observer
|
||||||
|
/* istanbul ignore next */
|
||||||
|
export default (options = {}) => {
|
||||||
|
/* istanbul ignore next */
|
||||||
|
if (options.lazy && options.env !== 'test') {
|
||||||
|
observer = new IntersectionObserver(
|
||||||
|
(entries, self) => {
|
||||||
|
for (const entry of entries) {
|
||||||
|
if (!entry.isIntersecting) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const span = entry.target
|
||||||
|
self.unobserve(span)
|
||||||
|
|
||||||
|
Promise.resolve(options.render(span.innerText, span.hasAttribute('block'))).then(html => {
|
||||||
|
span.innerHTML = html
|
||||||
|
})
|
||||||
|
span.classList.add('latex-rendered')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ threshold: 1.0 },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
extensions: [extBlock(options), extInline(options)],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* istanbul ignore next */
|
||||||
|
export const observe = () => {
|
||||||
|
if (!observer) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
observer.disconnect()
|
||||||
|
document.querySelectorAll(`span.${CLASS_NAME}:not(.latex-rendered)`).forEach(span => {
|
||||||
|
observer.observe(span)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/* istanbul ignore next */
|
||||||
|
export const disconnect = () => {
|
||||||
|
observer?.disconnect()
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ import { useEffect, useState } from 'preact/hooks'
|
|||||||
export const trottleDebounce = <T extends any[], R>(
|
export const trottleDebounce = <T extends any[], R>(
|
||||||
fn: (...args: T) => R,
|
fn: (...args: T) => R,
|
||||||
delay: number,
|
delay: number,
|
||||||
options: { leading?: boolean; trailing?: boolean } = {}
|
options: { leading?: boolean; trailing?: boolean } = {},
|
||||||
): ((...args: T) => R | undefined) => {
|
): ((...args: T) => R | undefined) => {
|
||||||
let lastCall = 0
|
let lastCall = 0
|
||||||
let lastResult: R | undefined
|
let lastResult: R | undefined
|
||||||
|
|||||||
@@ -9,11 +9,16 @@ const ICONS_MAP: Record<string, string> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
image: ImageMetadata
|
|
||||||
fullName: string
|
fullName: string
|
||||||
|
description: string
|
||||||
|
|
||||||
|
image: ImageMetadata
|
||||||
|
|
||||||
entranceDate: number
|
entranceDate: number
|
||||||
exitDate?: number
|
exitDate?: number
|
||||||
description: string
|
|
||||||
|
founder?: boolean
|
||||||
|
|
||||||
social?: {
|
social?: {
|
||||||
github?: string
|
github?: string
|
||||||
linkedin?: string
|
linkedin?: string
|
||||||
@@ -22,13 +27,14 @@ type Props = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { image, fullName, entranceDate, exitDate, description, social } = Astro.props
|
const { fullName, description, image, entranceDate, exitDate, founder, social } = Astro.props
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="bubble">
|
<div class="bubble">
|
||||||
<img src={image.src} alt={fullName.toLowerCase()} />
|
<img src={image.src} alt={fullName.toLowerCase()} />
|
||||||
<div class="title">{fullName}</div>
|
<div class="title">{fullName}</div>
|
||||||
<div class="date">{entranceDate}—{exitDate ?? 'Presente'}</div>
|
<div class="date">{entranceDate}—{exitDate ?? 'Presente'}</div>
|
||||||
|
{founder && <div class="founder">Fondatore</div>}
|
||||||
<div class="description">{description}</div>
|
<div class="description">{description}</div>
|
||||||
{
|
{
|
||||||
social && (
|
social && (
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ const links = [
|
|||||||
// { href: '/appunti', text: 'Appunti' },
|
// { href: '/appunti', text: 'Appunti' },
|
||||||
{ href: '/notizie', text: 'Notizie' },
|
{ href: '/notizie', text: 'Notizie' },
|
||||||
{ href: '/guide', text: 'Guide' },
|
{ href: '/guide', text: 'Guide' },
|
||||||
|
{ href: '/domande-esami', text: 'Domande Orali' },
|
||||||
|
{ href: '/media-pesata', text: 'Calcolo Media' }, // Beta testing - solo URL diretto
|
||||||
{ href: '/storia', text: 'Storia' },
|
{ href: '/storia', text: 'Storia' },
|
||||||
// { href: '/login', text: 'Login' },
|
// { href: '/login', text: 'Login' },
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ const { name } = Astro.props
|
|||||||
|
|
||||||
const icons = Object.fromEntries(
|
const icons = Object.fromEntries(
|
||||||
Object.entries(
|
Object.entries(
|
||||||
import.meta.glob<{ default: ImageMetadata }>(`node_modules/@phosphor-icons/core/assets/light/*.svg`)
|
import.meta.glob<{ default: ImageMetadata }>(`node_modules/@phosphor-icons/core/assets/light/*.svg`),
|
||||||
).map(([path, module]) => [path.split('/').pop()!.split('.')[0].replace('-light', ''), module])
|
).map(([path, module]) => [path.split('/').pop()!.split('.')[0].replace('-light', ''), module]),
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!icons[name]) {
|
if (!icons[name]) {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const { href, imgSrc, style, title } = Astro.props
|
|||||||
{imgSrc ? <img src={imgSrc} alt={'logo for ' + title.toLowerCase()} /> : <div class="box" />}
|
{imgSrc ? <img src={imgSrc} alt={'logo for ' + title.toLowerCase()} /> : <div class="box" />}
|
||||||
</div>
|
</div>
|
||||||
<div class="title">{title}</div>
|
<div class="title">{title}</div>
|
||||||
<div class="description">
|
<div class="description text">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -66,7 +66,10 @@ Vediamo un piccolo esempio di file `index.html` che possiamo creare:
|
|||||||
style="max-width: 300px; border-radius: 10px;"
|
style="max-width: 300px; border-radius: 10px;"
|
||||||
/>
|
/>
|
||||||
<p>Ciao! Sono Sergio Steffè.</p>
|
<p>Ciao! Sono Sergio Steffè.</p>
|
||||||
<p>Email: <a href="mailto:sergio.steffe@example.com">sergio.steffe@example.com</a></p>
|
<p>
|
||||||
|
Email:
|
||||||
|
<a href="mailto:sergio.steffe@example.com">sergio.steffe@example.com</a>
|
||||||
|
</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
|||||||
+13
-33
@@ -35,10 +35,7 @@ Una card semplice ha un titolo ed una descrizione.
|
|||||||
```astro
|
```astro
|
||||||
<div class="card" style="--card-base: var(--guide-base); max-width: 25rem;">
|
<div class="card" style="--card-base: var(--guide-base); max-width: 25rem;">
|
||||||
<div class="title">Titolo</div>
|
<div class="title">Titolo</div>
|
||||||
<div class="text">
|
<div class="text">Descrizione lorem ipsum dolor sit amet consectetur adipisicing elit. Aspernatur, labore?</div>
|
||||||
Descrizione lorem ipsum dolor sit amet consectetur
|
|
||||||
adipisicing elit. Aspernatur, labore?
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -51,14 +48,11 @@ Le card possono essere di dimensioni diverse. Questa è una card grande.
|
|||||||
```astro
|
```astro
|
||||||
<div class="card large" style="--card-base: lightgreen; max-width: 25rem;">
|
<div class="card large" style="--card-base: lightgreen; max-width: 25rem;">
|
||||||
<div class="title">Titolo</div>
|
<div class="title">Titolo</div>
|
||||||
<div class="text">
|
<div class="text">Descrizione lorem ipsum dolor sit amet consectetur adipisicing elit. Aspernatur, labore?</div>
|
||||||
Descrizione lorem ipsum dolor sit amet consectetur
|
|
||||||
adipisicing elit. Aspernatur, labore?
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Low Level: Mixin SCSS
|
### ~~Low Level: Mixin SCSS~~ Old CSS Mixin
|
||||||
|
|
||||||
Non dovrebbe essere mai necessario usarlo direttamente ma l'effetto di ombra delle card è ottenuto con questo mixin SCSS (che si trova in `src/styles/mixins.scss`).
|
Non dovrebbe essere mai necessario usarlo direttamente ma l'effetto di ombra delle card è ottenuto con questo mixin SCSS (che si trova in `src/styles/mixins.scss`).
|
||||||
|
|
||||||
@@ -100,10 +94,7 @@ Se c'è poco testo, può essere inserito direttamente nella card.
|
|||||||
|
|
||||||
```astro
|
```astro
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="text">
|
<div class="text">Descrizione lorem ipsum dolor sit amet consectetur adipisicing elit. Aspernatur, labore?</div>
|
||||||
Descrizione lorem ipsum dolor sit amet consectetur
|
|
||||||
adipisicing elit. Aspernatur, labore?
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -113,16 +104,15 @@ Altrimenti può essere inserito in un tag `<p>`.
|
|||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="text">
|
<div class="text">
|
||||||
<p>
|
<p>
|
||||||
Lorem ipsum dolor sit amet consectetur, adipisicing elit.
|
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Distinctio, vel! Veritatis est sit beatae eveniet.
|
||||||
Distinctio, vel! Veritatis est sit beatae eveniet.
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Error, minus, asperiores quaerat nulla cumque, nisi ipsam
|
Error, minus, asperiores quaerat nulla cumque, nisi ipsam assumenda consectetur accusamus tempore
|
||||||
assumenda consectetur accusamus tempore consequatur quae. Fugit?
|
consequatur quae. Fugit?
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Quos sapiente amet numquam quis, libero odit eum, eius
|
Quos sapiente amet numquam quis, libero odit eum, eius perspiciatis repellat nesciunt cupiditate asperiores
|
||||||
perspiciatis repellat nesciunt cupiditate asperiores maiores?
|
maiores?
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -132,19 +122,10 @@ C'è anche il modificatore `small` e `dimmed` per ridurre la grandezza del testo
|
|||||||
|
|
||||||
```astro
|
```astro
|
||||||
<div class="card" style="max-width: 25rem;">
|
<div class="card" style="max-width: 25rem;">
|
||||||
<div class="text">
|
<div class="text">Some normal text, this is a very long text that should wrap on the next line</div>
|
||||||
Some normal text, this is a very long
|
<div class="text small">This is some small text</div>
|
||||||
text that should wrap on the next line
|
<div class="text dimmed">This is some dimmed text</div>
|
||||||
</div>
|
<div class="text small dimmed">This is some small dimmed text</div>
|
||||||
<div class="text small">
|
|
||||||
This is some small text
|
|
||||||
</div>
|
|
||||||
<div class="text dimmed">
|
|
||||||
This is some dimmed text
|
|
||||||
</div>
|
|
||||||
<div class="text small dimmed">
|
|
||||||
This is some small dimmed text
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -197,7 +178,6 @@ import { ComboBox } from '@/lib/components/ComboBox'
|
|||||||
const [value, setValue] = useState('option-1')
|
const [value, setValue] = useState('option-1')
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
<ComboBox value={value} setValue={setValue}>
|
<ComboBox value={value} setValue={setValue}>
|
||||||
{{
|
{{
|
||||||
|
|||||||
@@ -35,4 +35,3 @@ Il nuovo sito unifica varie funzionalità che prima erano sparse in diversi siti
|
|||||||
## Conclusioni
|
## Conclusioni
|
||||||
|
|
||||||
Speriamo che il nuovo sito vi piaccia e vi sia utile. Se avete suggerimenti o richieste, non esitate a contattarci. Buona navigazione, magari iniziando dalla [pagina sulla storia del PHC](/storia)!
|
Speriamo che il nuovo sito vi piaccia e vi sia utile. Se avete suggerimenti o richieste, non esitate a contattarci. Buona navigazione, magari iniziando dalla [pagina sulla storia del PHC](/storia)!
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
title: Calcola la tua media ed il voto di laurea con il nuovissimo calcolatore del PHC!
|
||||||
|
description: È ora disponibile uno strumento per calcolare la propria media pesata e il voto di ammissione alla laurea secondo le regole del dipartimento
|
||||||
|
publishDate: 2025-06-26
|
||||||
|
---
|
||||||
|
|
||||||
|
# Calcola la tua media ed il voto di laurea con il nuovissimo calcolatore del PHC!
|
||||||
|
|
||||||
|
È ora disponibile nella sezione "Calcolo Media" del sito uno strumento per calcolare la propria media pesata e il voto di ammissione alla laurea secondo le regole ufficiali del dipartimento.
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://phc.dm.unipi.it/media-pesata/">phc.dm.unipi.it/media-pesata/</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
Il calcolatore applica automaticamente le regole di esclusione previste dal regolamento:
|
||||||
|
|
||||||
|
- **Triennale**: vengono esclusi i 15 CFU con i voti più bassi
|
||||||
|
- **Magistrale**: vengono esclusi i 9 CFU con i voti più bassi
|
||||||
|
|
||||||
|
Il sistema calcola anche il bonus per le lodi, che vale +0.5 punti per ogni materia superiore a 6 CFU e +0.25 punti per materie da 6 CFU o meno, con un tetto massimo di +1.5 punti per la triennale e +2 punti per la magistrale.
|
||||||
|
|
||||||
|
Se dovessero esserci bug scriveteci un'email a <a href="mailto:macchinisti@lists.dm.unipi.it">macchinisti@lists.dm.unipi.it</a>!
|
||||||
+2237
-97
File diff suppressed because it is too large
Load Diff
@@ -37,10 +37,11 @@
|
|||||||
|
|
||||||
# Vecchi Macchinisti
|
# Vecchi Macchinisti
|
||||||
|
|
||||||
# - fullName: Francesco Manicastri
|
- fullName: Francesco Manicastri
|
||||||
# entranceDate: 2022
|
entranceDate: 2020
|
||||||
# exitDate: 2024
|
exitDate: 2024
|
||||||
# description: Bla bla Keenan Crane
|
social:
|
||||||
|
linkedin: https://www.linkedin.com/in/gustavo-sass%C3%ACnculo-phd-92916a202/
|
||||||
|
|
||||||
- fullName: Cristiano Cricci
|
- fullName: Cristiano Cricci
|
||||||
entranceDate: 2010
|
entranceDate: 2010
|
||||||
@@ -70,3 +71,24 @@
|
|||||||
description: Traviato da Linux in età troppo giovane ha difficoltà ad usare il mouse ma ama gli shortcuts con una decina di tasti.
|
description: Traviato da Linux in età troppo giovane ha difficoltà ad usare il mouse ma ama gli shortcuts con una decina di tasti.
|
||||||
social:
|
social:
|
||||||
linkedin: https://www.linkedin.com/in/emiliano-rago-1a8018109/
|
linkedin: https://www.linkedin.com/in/emiliano-rago-1a8018109/
|
||||||
|
|
||||||
|
- fullName: Francesco Caporali
|
||||||
|
entranceDate: 2018
|
||||||
|
exitDate: 2022
|
||||||
|
social:
|
||||||
|
github: https://github.com/caporali
|
||||||
|
website: https://caporali.github.io/
|
||||||
|
linkedin: https://www.linkedin.com/in/francescocaporali
|
||||||
|
|
||||||
|
- fullName: Antonio Spanu
|
||||||
|
entranceDate: 2005
|
||||||
|
exitDate: 2009
|
||||||
|
social:
|
||||||
|
linkedin: https://www.linkedin.com/in/antonio-spanu-609b3516a/
|
||||||
|
|
||||||
|
- fullName: Riccardo Murri
|
||||||
|
entranceDate: 1995
|
||||||
|
exitDate: 2000
|
||||||
|
founder: true
|
||||||
|
social:
|
||||||
|
github: https://github.com/riccardomurri
|
||||||
|
|||||||
Vendored
+5
-1
@@ -6,10 +6,14 @@ declare module '*.yaml' {
|
|||||||
declare module '@/data/macchinisti.yaml' {
|
declare module '@/data/macchinisti.yaml' {
|
||||||
type Macchinista = {
|
type Macchinista = {
|
||||||
fullName: string
|
fullName: string
|
||||||
|
description: string
|
||||||
|
|
||||||
entranceDate: number
|
entranceDate: number
|
||||||
exitDate?: number
|
exitDate?: number
|
||||||
description: string
|
|
||||||
social: Record<string, string>
|
social: Record<string, string>
|
||||||
|
|
||||||
|
founder?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const value: Macchinista[]
|
const value: Macchinista[]
|
||||||
|
|||||||
@@ -9,20 +9,17 @@ import '@fontsource/iosevka/latin.css'
|
|||||||
|
|
||||||
import '@fontsource-variable/material-symbols-outlined/full.css'
|
import '@fontsource-variable/material-symbols-outlined/full.css'
|
||||||
|
|
||||||
import '../styles/main.scss'
|
import '@/styles/main.css'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
title?: string
|
title?: string
|
||||||
description?: string
|
description?: string
|
||||||
thumbnail?: string
|
thumbnail?: string
|
||||||
|
|
||||||
/** Tags for the page, used for styling */
|
|
||||||
pageTags?: string | string[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
import phcIcon from '../assets/icon.png'
|
import phcIcon from '../assets/icon.png'
|
||||||
|
|
||||||
const { title, description, thumbnail, pageTags } = Astro.props
|
const { title, description, thumbnail } = Astro.props
|
||||||
---
|
---
|
||||||
|
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
@@ -75,9 +72,14 @@ const { title, description, thumbnail, pageTags } = Astro.props
|
|||||||
src="//analytics.phc.dm.unipi.it/count.js"
|
src="//analytics.phc.dm.unipi.it/count.js"
|
||||||
data-goatcounter="https://analytics.phc.dm.unipi.it/count"></script>
|
data-goatcounter="https://analytics.phc.dm.unipi.it/count"></script>
|
||||||
|
|
||||||
|
<style is:inline>
|
||||||
|
/* Workaround Astro CSS loading order, this forces the layering upfront */
|
||||||
|
@layer base, typography, component, page, utility;
|
||||||
|
</style>
|
||||||
|
|
||||||
<title>{title ?? 'PHC'}</title>
|
<title>{title ?? 'PHC'}</title>
|
||||||
</head>
|
</head>
|
||||||
<body class:list={typeof pageTags === 'string' ? [pageTags] : pageTags}>
|
<body>
|
||||||
<slot />
|
<slot />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
import '@/styles/pages/appunti.css'
|
||||||
|
|
||||||
import PageLayout from '@layouts/PageLayout.astro'
|
import PageLayout from '@layouts/PageLayout.astro'
|
||||||
|
|
||||||
import { AppuntiList, AppuntiCard } from '@client/Appunti'
|
import { AppuntiList, AppuntiCard } from '@client/Appunti'
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
---
|
---
|
||||||
|
import '@/styles/pages/domande-esami.css'
|
||||||
|
|
||||||
import type { GetStaticPaths } from 'astro'
|
import type { GetStaticPaths } from 'astro'
|
||||||
import BaseLayout from '@/layouts/BaseLayout.astro'
|
import BaseLayout from '@/layouts/BaseLayout.astro'
|
||||||
import Footer from '@/components/Footer.astro'
|
import Footer from '@/components/Footer.astro'
|
||||||
import Header from '@/components/Header.astro'
|
import Header from '@/components/Header.astro'
|
||||||
|
|
||||||
import { marked } from 'marked'
|
|
||||||
|
|
||||||
import database from '@/data/domande-esami.yaml'
|
import database from '@/data/domande-esami.yaml'
|
||||||
import PhosphorIcon from '@/components/PhosphorIcon.astro'
|
|
||||||
import { DomandeEsamiCourse } from '@/client/DomandeEsamiCourse'
|
import { DomandeEsamiCourse } from '@/client/DomandeEsamiCourse'
|
||||||
|
|
||||||
export const getStaticPaths = (() => {
|
export const getStaticPaths = (() => {
|
||||||
@@ -19,10 +18,10 @@ export const getStaticPaths = (() => {
|
|||||||
const { course } = Astro.params
|
const { course } = Astro.params
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout title="Domande Esami | PHC" pageTags={'domande-esami'}>
|
<BaseLayout title="Domande Orali | PHC">
|
||||||
<Header />
|
<Header />
|
||||||
<main>
|
<main>
|
||||||
<DomandeEsamiCourse client:load course={course} />
|
<DomandeEsamiCourse client:only="preact" course={course} />
|
||||||
</main>
|
</main>
|
||||||
<Footer />
|
<Footer />
|
||||||
</BaseLayout>
|
</BaseLayout>
|
||||||
|
|||||||
@@ -19,6 +19,6 @@ export const GET: APIRoute = ({ params: { course } }) => {
|
|||||||
headers: {
|
headers: {
|
||||||
'content-type': 'application/json',
|
'content-type': 'application/json',
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
import '@/styles/pages/domande-esami.css'
|
||||||
|
|
||||||
import { PhosphorIcon } from '@/client/Icon'
|
import { PhosphorIcon } from '@/client/Icon'
|
||||||
import Footer from '@/components/Footer.astro'
|
import Footer from '@/components/Footer.astro'
|
||||||
import Header from '@/components/Header.astro'
|
import Header from '@/components/Header.astro'
|
||||||
@@ -10,14 +12,14 @@ const courseQuestionCounts = Object.fromEntries(
|
|||||||
database.questions.reduce((acc, question) => {
|
database.questions.reduce((acc, question) => {
|
||||||
acc.set(question.course, (acc.get(question.course) || 0) + 1)
|
acc.set(question.course, (acc.get(question.course) || 0) + 1)
|
||||||
return acc
|
return acc
|
||||||
}, new Map())
|
}, new Map()),
|
||||||
)
|
)
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout title="Domande Esami | PHC" pageTags={'domande-esami'}>
|
<BaseLayout title="Domande Orali | PHC">
|
||||||
<Header />
|
<Header />
|
||||||
<main>
|
<main>
|
||||||
<h1>Domande Esami</h1>
|
<h1>Domande Orali</h1>
|
||||||
{
|
{
|
||||||
database.groups.map(group => (
|
database.groups.map(group => (
|
||||||
<details open>
|
<details open>
|
||||||
@@ -33,7 +35,9 @@ const courseQuestionCounts = Object.fromEntries(
|
|||||||
</h2>
|
</h2>
|
||||||
</summary>
|
</summary>
|
||||||
<div class="wide-card-list">
|
<div class="wide-card-list">
|
||||||
{group.items.map(course => (
|
{group.items
|
||||||
|
.filter(course => courseQuestionCounts[course] > 0)
|
||||||
|
.map(course => (
|
||||||
<a href={`/domande-esami/${course}`}>
|
<a href={`/domande-esami/${course}`}>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h2>{database.names[course]}</h2>
|
<h2>{database.names[course]}</h2>
|
||||||
@@ -51,7 +55,10 @@ const courseQuestionCounts = Object.fromEntries(
|
|||||||
<h3>Come Contribuire</h3>
|
<h3>Come Contribuire</h3>
|
||||||
<div class="card large">
|
<div class="card large">
|
||||||
<div class="text">
|
<div class="text">
|
||||||
<p>Se hai raccolte di domande da condividere, puoi...</p>
|
<p>
|
||||||
|
Se hai raccolto delle domande da un orale, puoi inviarcele per email all'indirizzo
|
||||||
|
<a href="mailto:macchinisti@lists.dm.unipi.it"> macchinisti@lists.dm.unipi.it</a>.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
import '@/styles/pages/guide-item.css'
|
||||||
|
|
||||||
import { getCollection } from 'astro:content'
|
import { getCollection } from 'astro:content'
|
||||||
|
|
||||||
import ArticleLayout from '@/layouts/ArticleLayout.astro'
|
import ArticleLayout from '@/layouts/ArticleLayout.astro'
|
||||||
@@ -16,11 +18,9 @@ const { entry } = Astro.props
|
|||||||
const { Content } = await entry.render()
|
const { Content } = await entry.render()
|
||||||
---
|
---
|
||||||
|
|
||||||
<ArticleLayout
|
<ArticleLayout {...entry.data} title={entry.data.title + ' | Guide | PHC'}>
|
||||||
{...entry.data}
|
<!-- pageTags={['guida', entry.data.id, entry.data.series && 'series']} -->
|
||||||
title={entry.data.title + ' | Guide | PHC'}
|
|
||||||
pageTags={['guida', entry.data.id, entry.data.series && 'series']}
|
|
||||||
>
|
|
||||||
<h1>{entry.data.title}</h1>
|
<h1>{entry.data.title}</h1>
|
||||||
|
|
||||||
{entry.data.series && <div class="series">Serie: {entry.data.series}</div>}
|
{entry.data.series && <div class="series">Serie: {entry.data.series}</div>}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
import '@/styles/pages/guide-list.css'
|
||||||
|
|
||||||
import { getCollection } from 'astro:content'
|
import { getCollection } from 'astro:content'
|
||||||
|
|
||||||
import PageLayout from '@layouts/PageLayout.astro'
|
import PageLayout from '@layouts/PageLayout.astro'
|
||||||
@@ -6,7 +8,7 @@ import PageLayout from '@layouts/PageLayout.astro'
|
|||||||
const guides = await getCollection('guides')
|
const guides = await getCollection('guides')
|
||||||
---
|
---
|
||||||
|
|
||||||
<PageLayout title="Guide | PHC" pageTags="guide">
|
<PageLayout title="Guide | PHC">
|
||||||
<h1>
|
<h1>
|
||||||
<a href="/guide">Guide</a>
|
<a href="/guide">Guide</a>
|
||||||
</h1>
|
</h1>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
import '@/styles/pages/guide-list.css'
|
||||||
|
|
||||||
import { getCollection } from 'astro:content'
|
import { getCollection } from 'astro:content'
|
||||||
import type { CollectionEntry } from 'astro:content'
|
import type { CollectionEntry } from 'astro:content'
|
||||||
import PageLayout from '@/layouts/PageLayout.astro'
|
import PageLayout from '@/layouts/PageLayout.astro'
|
||||||
@@ -33,7 +35,7 @@ interface Props {
|
|||||||
const { tag, guides } = Astro.props
|
const { tag, guides } = Astro.props
|
||||||
---
|
---
|
||||||
|
|
||||||
<PageLayout title={`#${tag} | Guide | PHC`} pageTags="guide tag">
|
<PageLayout title={`#${tag} | Guide | PHC`}>
|
||||||
<h1><a href="/guide">Guide</a> > <a href={`/guide/tags/${tag}`}>#{tag}</a></h1>
|
<h1><a href="/guide">Guide</a> > <a href={`/guide/tags/${tag}`}>#{tag}</a></h1>
|
||||||
<div class="card-list">
|
<div class="card-list">
|
||||||
{
|
{
|
||||||
|
|||||||
+28
-27
@@ -1,4 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
import '@/styles/pages/homepage.css'
|
||||||
|
|
||||||
import { getCollection } from 'astro:content'
|
import { getCollection } from 'astro:content'
|
||||||
import PageLayout from '@/layouts/PageLayout.astro'
|
import PageLayout from '@/layouts/PageLayout.astro'
|
||||||
import { Content as WhatPhcContent, frontmatter as whatsPhcFrontmatter } from '@/content/meta/whats-phc.md'
|
import { Content as WhatPhcContent, frontmatter as whatsPhcFrontmatter } from '@/content/meta/whats-phc.md'
|
||||||
@@ -45,7 +47,7 @@ const galleryCollage = await Astro.glob('@/assets/gallery/*.jpg')
|
|||||||
|
|
||||||
<div class="card-list">
|
<div class="card-list">
|
||||||
{
|
{
|
||||||
news.map(newsItem => (
|
news.toReversed().map(newsItem => (
|
||||||
<Card>
|
<Card>
|
||||||
<a href={`/notizie/${newsItem.slug}`} class="title">
|
<a href={`/notizie/${newsItem.slug}`} class="title">
|
||||||
{newsItem.data.title}
|
{newsItem.data.title}
|
||||||
@@ -80,8 +82,7 @@ const galleryCollage = await Astro.glob('@/assets/gallery/*.jpg')
|
|||||||
>
|
>
|
||||||
<p>Gitea è un servizio di hosting per progetti software, come GitHub ma autogestito.</p>
|
<p>Gitea è un servizio di hosting per progetti software, come GitHub ma autogestito.</p>
|
||||||
<p>
|
<p>
|
||||||
Qui puoi trovare i progetti del PHC, e accedendo con un account di Ateneo potrai crearne
|
Qui puoi trovare i progetti del PHC, e accedendo con un account di Ateneo potrai crearne di nuovi.
|
||||||
di nuovi.
|
|
||||||
</p>
|
</p>
|
||||||
</ProjectCard>
|
</ProjectCard>
|
||||||
<!-- <ProjectCard
|
<!-- <ProjectCard
|
||||||
@@ -98,8 +99,8 @@ const galleryCollage = await Astro.glob('@/assets/gallery/*.jpg')
|
|||||||
imgSrc="https://lab.phc.dm.unipi.it/orario/icon.png"
|
imgSrc="https://lab.phc.dm.unipi.it/orario/icon.png"
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
Questo sito permette di visualizzare il proprio orario delle lezioni, con informazioni sui
|
Questo sito permette di visualizzare il proprio orario delle lezioni, con informazioni sui docenti e
|
||||||
docenti e le aule.
|
le aule.
|
||||||
</p>
|
</p>
|
||||||
</ProjectCard>
|
</ProjectCard>
|
||||||
<ProjectCard
|
<ProjectCard
|
||||||
@@ -118,8 +119,8 @@ const galleryCollage = await Astro.glob('@/assets/gallery/*.jpg')
|
|||||||
imgSrc="https://steffe.lb.cs.dm.unipi.it/assets/img/logo.png"
|
imgSrc="https://steffe.lb.cs.dm.unipi.it/assets/img/logo.png"
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
Cluster progettato ed assemblato durante il progetto speciale per la didattica "Calcolo
|
Cluster progettato ed assemblato durante il progetto speciale per la didattica "Calcolo Parallelo
|
||||||
Parallelo dall'Infrastruttura alla Matematica".
|
dall'Infrastruttura alla Matematica".
|
||||||
</p>
|
</p>
|
||||||
</ProjectCard>
|
</ProjectCard>
|
||||||
<ProjectCard
|
<ProjectCard
|
||||||
@@ -128,10 +129,7 @@ const galleryCollage = await Astro.glob('@/assets/gallery/*.jpg')
|
|||||||
style="--card-bg: #bd9fec; --masonry-height: 2;"
|
style="--card-bg: #bd9fec; --masonry-height: 2;"
|
||||||
imgSrc="https://seminarietti.phc.dm.unipi.it/favicon.png"
|
imgSrc="https://seminarietti.phc.dm.unipi.it/favicon.png"
|
||||||
>
|
>
|
||||||
<p>
|
<p>Storico degli incontri organizzati dal PHC su argomenti di informatica, matematica e tecnologia.</p>
|
||||||
Storico degli incontri organizzati dal PHC su argomenti di informatica, matematica e
|
|
||||||
tecnologia.
|
|
||||||
</p>
|
|
||||||
</ProjectCard>
|
</ProjectCard>
|
||||||
<ProjectCard
|
<ProjectCard
|
||||||
title="Tutorato"
|
title="Tutorato"
|
||||||
@@ -140,8 +138,8 @@ const galleryCollage = await Astro.glob('@/assets/gallery/*.jpg')
|
|||||||
imgSrc="https://tutorato.phc.dm.unipi.it/favicon.svg"
|
imgSrc="https://tutorato.phc.dm.unipi.it/favicon.svg"
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
Un sito con tutte le informazioni sui tutorati di Matematica, con tanto di archivio degli
|
Un sito con tutte le informazioni sui tutorati di Matematica, con tanto di archivio degli anni
|
||||||
anni passati.
|
passati.
|
||||||
</p>
|
</p>
|
||||||
</ProjectCard>
|
</ProjectCard>
|
||||||
<ProjectCard
|
<ProjectCard
|
||||||
@@ -151,10 +149,18 @@ const galleryCollage = await Astro.glob('@/assets/gallery/*.jpg')
|
|||||||
imgSrc="https://ggwp.phc.dm.unipi.it/ggwp-icon.png"
|
imgSrc="https://ggwp.phc.dm.unipi.it/ggwp-icon.png"
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
Sito per il tabellone del GGWP, utilizzato durante la gara di Novembre 2024 dagli
|
Sito per il tabellone del GGWP, utilizzato durante la gara di Novembre 2024 dagli organizzatori per
|
||||||
organizzatori per inserire le risposte alla gara in tempo reale.
|
inserire le risposte alla gara in tempo reale.
|
||||||
</p>
|
</p>
|
||||||
</ProjectCard>
|
</ProjectCard>
|
||||||
|
<ProjectCard
|
||||||
|
title="Chat"
|
||||||
|
href="https://chat.phc.dm.unipi.it/"
|
||||||
|
style="--card-bg: #383838; --card-fg: #ddd; --masonry-height: 1;"
|
||||||
|
imgSrc="https://chat.phc.dm.unipi.it/favicon.png"
|
||||||
|
>
|
||||||
|
<p>Istanza di Open-WebUI, una chat stile ChatGPT con alcuni LLM self-hostati dal PHC.</p>
|
||||||
|
</ProjectCard>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="wanna-be-macchinista">
|
<section class="wanna-be-macchinista">
|
||||||
@@ -172,22 +178,18 @@ const galleryCollage = await Astro.glob('@/assets/gallery/*.jpg')
|
|||||||
supporto tecnico per installare ed usare <strong>Linux</strong> sul proprio portatile
|
supporto tecnico per installare ed usare <strong>Linux</strong> sul proprio portatile
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>costruiamo</strong>, <strong>smontiamo</strong> ed <strong>aggiustiamo</strong
|
<strong>costruiamo</strong>, <strong>smontiamo</strong> ed <strong>aggiustiamo</strong>
|
||||||
>
|
|
||||||
computer (antichi e moderni)
|
computer (antichi e moderni)
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>sviluppo software</strong> di backend e frontend per siti web (ma non solo)
|
<strong>sviluppo software</strong> di backend e frontend per siti web (ma non solo)
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
organizzazione di <strong>seminari</strong> di divulgazione (vedi <a href="#projects"
|
organizzazione di <strong>seminari</strong> di divulgazione (vedi <a href="#projects">sopra</a>)
|
||||||
>sopra</a
|
|
||||||
>)
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
Infine, il PHC è prima di tutto un luogo dove <strong>imparare</strong>, <strong
|
Infine, il PHC è prima di tutto un luogo dove <strong>imparare</strong>, <strong>trasmettere</strong
|
||||||
>trasmettere</strong
|
|
||||||
> le proprie conoscenze e <strong>condividere</strong> la passione per la tecnologia.
|
> le proprie conoscenze e <strong>condividere</strong> la passione per la tecnologia.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -219,13 +221,12 @@ const galleryCollage = await Astro.glob('@/assets/gallery/*.jpg')
|
|||||||
<div class="title">Vuoi diventare macchinista?</div>
|
<div class="title">Vuoi diventare macchinista?</div>
|
||||||
<div class="text">
|
<div class="text">
|
||||||
<p>
|
<p>
|
||||||
<strong>Macchinista non si nasce, si diventa:</strong> se sei uno studente di Matematica e
|
<strong>Macchinista non si nasce, si diventa:</strong> se sei uno studente di Matematica e vuoi diventare
|
||||||
vuoi diventare un macchinista, vienici a trovare!
|
un macchinista, vienici a trovare!
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
L'unico prerequisito è la voglia di imparare! Di solito, c'è un periodo di "apprendistato"
|
L'unico prerequisito è la voglia di imparare! Di solito, c'è un periodo di "apprendistato" nel quale
|
||||||
nel quale si apprendono le basi; una volta superato potrai diventare un macchinista a
|
si apprendono le basi; una volta superato potrai diventare un macchinista a tutti gli effetti.
|
||||||
tutti gli effetti.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
+13
-10
@@ -1,4 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
import '@/styles/pages/macchinisti.css'
|
||||||
|
|
||||||
import BaseLayout from '../layouts/BaseLayout.astro'
|
import BaseLayout from '../layouts/BaseLayout.astro'
|
||||||
import Header from '../components/Header.astro'
|
import Header from '../components/Header.astro'
|
||||||
import Footer from '../components/Footer.astro'
|
import Footer from '../components/Footer.astro'
|
||||||
@@ -12,8 +14,8 @@ const images = Object.fromEntries(
|
|||||||
Object.entries(
|
Object.entries(
|
||||||
import.meta.glob<{ default: ImageMetadata }>('@/assets/macchinisti/*', {
|
import.meta.glob<{ default: ImageMetadata }>('@/assets/macchinisti/*', {
|
||||||
eager: true,
|
eager: true,
|
||||||
})
|
}),
|
||||||
).map(([path, module]) => [path.split('/').pop()!.split('.')[0], module])
|
).map(([path, module]) => [path.split('/').pop()!.split('.')[0], module]),
|
||||||
)
|
)
|
||||||
|
|
||||||
const currentMacchinisti = macchinisti.filter(macchinista => !macchinista.exitDate)
|
const currentMacchinisti = macchinisti.filter(macchinista => !macchinista.exitDate)
|
||||||
@@ -26,7 +28,7 @@ const getMacchinistaPicture = (fullName: string) => {
|
|||||||
}
|
}
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout title="Macchinisti | PHC" pageTags={'macchinisti'}>
|
<BaseLayout title="Macchinisti | PHC">
|
||||||
<Header />
|
<Header />
|
||||||
<main>
|
<main>
|
||||||
<div class="card large" style={{ '--card-base': '#e1766b' }}>
|
<div class="card large" style={{ '--card-base': '#e1766b' }}>
|
||||||
@@ -35,9 +37,9 @@ const getMacchinistaPicture = (fullName: string) => {
|
|||||||
<p>
|
<p>
|
||||||
<em>> Chi sono i macchinisti?</em>
|
<em>> Chi sono i macchinisti?</em>
|
||||||
<br />
|
<br />
|
||||||
Questo è l'appellativo dato agli studenti che si occupano di gestire l'infrastuttura e i servizi
|
Questo è l'appellativo dato agli studenti che si occupano di gestire l'infrastuttura e i servizi del
|
||||||
del PHC (vedi la homepage per informazioni su come diventare un macchinista). Qua sotto trovi
|
PHC (vedi la homepage per informazioni su come diventare un macchinista). Qua sotto trovi i macchinisti
|
||||||
i macchinisti attualmente attivi in PHC.
|
attualmente attivi in PHC.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -60,8 +62,8 @@ const getMacchinistaPicture = (fullName: string) => {
|
|||||||
<div class="title"><s>Deus</s> Ex Macchinisti</div>
|
<div class="title"><s>Deus</s> Ex Macchinisti</div>
|
||||||
<div class="text">
|
<div class="text">
|
||||||
<p>
|
<p>
|
||||||
Qui raccogliamo qualche informazione sui macchinisti del passato, che hanno contribuito a
|
Qui raccogliamo qualche informazione sui macchinisti del passato, che hanno contribuito a rendere il
|
||||||
rendere il PHC quello che è oggi.
|
PHC quello che è oggi.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -70,11 +72,12 @@ const getMacchinistaPicture = (fullName: string) => {
|
|||||||
{
|
{
|
||||||
pastMacchinisti.map(macchinista => (
|
pastMacchinisti.map(macchinista => (
|
||||||
<Bubble
|
<Bubble
|
||||||
image={getMacchinistaPicture(macchinista.fullName)}
|
|
||||||
fullName={macchinista.fullName}
|
fullName={macchinista.fullName}
|
||||||
|
description={macchinista.description}
|
||||||
|
image={getMacchinistaPicture(macchinista.fullName)}
|
||||||
entranceDate={macchinista.entranceDate}
|
entranceDate={macchinista.entranceDate}
|
||||||
exitDate={macchinista.exitDate}
|
exitDate={macchinista.exitDate}
|
||||||
description={macchinista.description}
|
founder={macchinista.founder}
|
||||||
social={macchinista.social}
|
social={macchinista.social}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
import '@/styles/pages/media-pesata.css'
|
||||||
|
import PageLayout from '../layouts/PageLayout.astro'
|
||||||
|
|
||||||
|
import { MediaPesataApp } from '@/client/MediaPesataApp'
|
||||||
|
---
|
||||||
|
|
||||||
|
<PageLayout
|
||||||
|
title="Voto Laurea"
|
||||||
|
description="Calcola la tua media pesata e il voto di laurea seguendo le regole del dipartimento"
|
||||||
|
>
|
||||||
|
<div class="media-pesata-container">
|
||||||
|
<h1>Calcolo Media e Voto di Laurea</h1>
|
||||||
|
<p>
|
||||||
|
Calcola la tua media pesata e il voto con cui ti siederai alla discussione di laurea, seguendo le regole del
|
||||||
|
dipartimento di Matematica.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<MediaPesataApp client:load />
|
||||||
|
</div>
|
||||||
|
</PageLayout>
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
import '@/styles/pages/meta-design.css'
|
||||||
|
|
||||||
import BaseLayout from '../../layouts/BaseLayout.astro'
|
import BaseLayout from '../../layouts/BaseLayout.astro'
|
||||||
|
|
||||||
import Header from '../../components/Header.astro'
|
import Header from '../../components/Header.astro'
|
||||||
@@ -11,7 +13,7 @@ import { Content, getHeadings } from '../../content/meta/design.mdx'
|
|||||||
const headings = getHeadings()
|
const headings = getHeadings()
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout {...Astro.props} pageTags="design">
|
<BaseLayout {...Astro.props}>
|
||||||
<Header />
|
<Header />
|
||||||
<aside>
|
<aside>
|
||||||
<nav>
|
<nav>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
import '@/styles/pages/news-item.css'
|
||||||
|
|
||||||
import { getCollection } from 'astro:content'
|
import { getCollection } from 'astro:content'
|
||||||
|
|
||||||
import ArticleLayout from '../../layouts/ArticleLayout.astro'
|
import ArticleLayout from '../../layouts/ArticleLayout.astro'
|
||||||
@@ -15,6 +17,6 @@ const { entry } = Astro.props
|
|||||||
const { Content } = await entry.render()
|
const { Content } = await entry.render()
|
||||||
---
|
---
|
||||||
|
|
||||||
<ArticleLayout {...entry.data} title={entry.data.title + ' | Notizie | PHC'} pageTags={['notizia']}>
|
<ArticleLayout {...entry.data} title={entry.data.title + ' | Notizie | PHC'}>
|
||||||
<Content />
|
<Content />
|
||||||
</ArticleLayout>
|
</ArticleLayout>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
import '@/styles/pages/news-list.css'
|
||||||
|
|
||||||
import { getCollection } from 'astro:content'
|
import { getCollection } from 'astro:content'
|
||||||
|
|
||||||
import PageLayout from '@layouts/PageLayout.astro'
|
import PageLayout from '@layouts/PageLayout.astro'
|
||||||
@@ -6,7 +8,7 @@ import PageLayout from '@layouts/PageLayout.astro'
|
|||||||
const news = await getCollection('news')
|
const news = await getCollection('news')
|
||||||
---
|
---
|
||||||
|
|
||||||
<PageLayout title="Notizie | PHC" pageTags="notizie">
|
<PageLayout title="Notizie | PHC">
|
||||||
<h1><a href="/notizie">Notizie</a></h1>
|
<h1><a href="/notizie">Notizie</a></h1>
|
||||||
<div class="card-list">
|
<div class="card-list">
|
||||||
{
|
{
|
||||||
|
|||||||
+27
-33
@@ -1,4 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
import '@/styles/pages/storia.css'
|
||||||
|
|
||||||
import BaseLayout from '../layouts/BaseLayout.astro'
|
import BaseLayout from '../layouts/BaseLayout.astro'
|
||||||
|
|
||||||
import Header from '../components/Header.astro'
|
import Header from '../components/Header.astro'
|
||||||
@@ -10,16 +12,15 @@ import imgCluster from '@/assets/gallery/001-cluster-fra-luca@4x3.jpg'
|
|||||||
import WebSite from '@/assets/gallery/005-website-development@3x4.jpg'
|
import WebSite from '@/assets/gallery/005-website-development@3x4.jpg'
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout title="Storia | PHC" pageTags={'storia'}>
|
<BaseLayout title="Storia | PHC">
|
||||||
<Header />
|
<Header />
|
||||||
<main>
|
<main>
|
||||||
<div class="card large" style={{ '--card-base': '#ffd3a0' }}>
|
<div class="card large" style={{ '--card-base': '#ffd3a0' }}>
|
||||||
<div class="title">Storia</div>
|
<div class="title">Storia</div>
|
||||||
<div class="text">
|
<div class="text">
|
||||||
<p>
|
<p>
|
||||||
Il PHC nasce quasi venti anni fa, nel lontano 1999 ed ha perciò una ricca storia. Qui
|
Il PHC nasce quasi venti anni fa, nel lontano 1999 ed ha perciò una ricca storia. Qui proveremo ad
|
||||||
proveremo ad annoverare la storia del PHC, in una timeline con gli eventi più salienti del
|
annoverare la storia del PHC, in una timeline con gli eventi più salienti del progetto.
|
||||||
progetto.
|
|
||||||
</p>
|
</p>
|
||||||
<img
|
<img
|
||||||
class="small flat"
|
class="small flat"
|
||||||
@@ -36,26 +37,25 @@ import WebSite from '@/assets/gallery/005-website-development@3x4.jpg'
|
|||||||
<div class="timeline">
|
<div class="timeline">
|
||||||
<Timeline title="Un nuovo look" year="Nov 2024">
|
<Timeline title="Un nuovo look" year="Nov 2024">
|
||||||
<p>
|
<p>
|
||||||
Dopo <s>mesi</s> anni di lavoro e di progettazione, il sito del PHC viene riscritto da zero
|
Dopo <s>mesi</s> anni di lavoro e di progettazione, il sito del PHC viene riscritto da zero in Astro.
|
||||||
in Astro. Il progetto è stato voluto principalmente da <strong
|
Il progetto è stato voluto principalmente da <strong>Antonio De Lucreziis</strong> (in foto, in fase
|
||||||
>Antonio De Lucreziis</strong
|
di sviluppo), con il supporto di <strong>Francesco Minnocci</strong>.
|
||||||
> (in foto, in fase di sviluppo), con il supporto di <strong>Francesco Minnocci</strong>.
|
|
||||||
</p>
|
</p>
|
||||||
<img class="fill" src={WebSite.src} alt="Sviluppo del sito" />
|
<img class="fill" src={WebSite.src} alt="Sviluppo del sito" />
|
||||||
</Timeline>
|
</Timeline>
|
||||||
<Timeline title="Luca e le grandi pulizie" year="Apr 2024">
|
<Timeline title="Luca e le grandi pulizie" year="Apr 2024">
|
||||||
<p>
|
<p>
|
||||||
Nel 2024, <strong>Luca Lombardo</strong> entra a far parte del PHC. Questo stesso anno vengono
|
Nel 2024, <strong>Luca Lombardo</strong> entra a far parte del PHC. Questo stesso anno vengono effettuate
|
||||||
effettuate delle grandi pulizie nella stanza del PHC, come non si faceva dal lontano 2006.
|
delle grandi pulizie nella stanza del PHC, come non si faceva dal lontano 2006.
|
||||||
</p>
|
</p>
|
||||||
<img class="fill" src={imgPulizie.src} alt="pulizie phc" />
|
<img class="fill" src={imgPulizie.src} alt="pulizie phc" />
|
||||||
</Timeline>
|
</Timeline>
|
||||||
<Timeline title="Il cluster di Raspberry Pi" year="2023">
|
<Timeline title="Il cluster di Raspberry Pi" year="2023">
|
||||||
<p>
|
<p>
|
||||||
Il dipartimento acquista in due fasi diverse 34 (cloni) di Raspberry Pi 4, che vengono
|
Il dipartimento acquista in due fasi diverse 34 (cloni) di Raspberry Pi 4, che vengono assemblati in
|
||||||
assemblati in un cluster per il progetto "High Performance Mathematics". Il cluster è
|
un cluster per il progetto "High Performance Mathematics". Il cluster è stato assemblato,
|
||||||
stato assemblato, configurato e messo in funzione con la forte collaborazione macchinisti
|
configurato e messo in funzione con la forte collaborazione macchinisti del PHC, che ancora oggi ne
|
||||||
del PHC, che ancora oggi ne curano la manutenzione.
|
curano la manutenzione.
|
||||||
</p>
|
</p>
|
||||||
<img class="fill" src={imgCluster.src} alt="cluster di raspberry pi" />
|
<img class="fill" src={imgCluster.src} alt="cluster di raspberry pi" />
|
||||||
</Timeline>
|
</Timeline>
|
||||||
@@ -82,9 +82,8 @@ import WebSite from '@/assets/gallery/005-website-development@3x4.jpg'
|
|||||||
</Timeline>
|
</Timeline>
|
||||||
<Timeline title="Rinnovo del sito" year="2004">
|
<Timeline title="Rinnovo del sito" year="2004">
|
||||||
<p>
|
<p>
|
||||||
Dopo un periodo di inattività del progetto, il sito del PHC viene riscritto in PHP e
|
Dopo un periodo di inattività del progetto, il sito del PHC viene riscritto in PHP e trasferito sul
|
||||||
trasferito sul dominio <a
|
dominio <a href="https://web.archive.org/web/20040823112401/http://poisson.phc.unipi.it/"
|
||||||
href="https://web.archive.org/web/20040823112401/http://poisson.phc.unipi.it/"
|
|
||||||
>poisson.phc.unipi.it</a
|
>poisson.phc.unipi.it</a
|
||||||
>, il cui design è caratterizzato da un <a
|
>, il cui design è caratterizzato da un <a
|
||||||
href="https://web.archive.org/web/20060609003904im_/http://poisson.phc.unipi.it/logo_studenti.orig.png"
|
href="https://web.archive.org/web/20060609003904im_/http://poisson.phc.unipi.it/logo_studenti.orig.png"
|
||||||
@@ -108,33 +107,28 @@ import WebSite from '@/assets/gallery/005-website-development@3x4.jpg'
|
|||||||
</Timeline>
|
</Timeline>
|
||||||
<Timeline title="Rete del PHC e DNS" year="1999">
|
<Timeline title="Rete del PHC e DNS" year="1999">
|
||||||
<p>
|
<p>
|
||||||
Nel maggio del 1999 viene attivata la rete 131.114.10.0, con tanto di nameserver sul
|
Nel maggio del 1999 viene attivata la rete 131.114.10.0, con tanto di nameserver sul dominio <a
|
||||||
dominio <a href="https://web.archive.org/web/20010410215451/http://www.phc.unipi.it/"
|
href="https://web.archive.org/web/20010410215451/http://www.phc.unipi.it/">phc.unipi.it</a
|
||||||
>phc.unipi.it</a
|
|
||||||
>.
|
>.
|
||||||
</p>
|
</p>
|
||||||
</Timeline>
|
</Timeline>
|
||||||
<Timeline title="Fondazione del PHC" year="1999">
|
<Timeline title="Fondazione del PHC" year="1999">
|
||||||
<p>
|
<p>
|
||||||
In seguito alla proposta del prof. <strong>Sergio Steffè</strong>, in data 26 febbraio
|
In seguito alla proposta del prof. <strong>Sergio Steffè</strong>, in data 26 febbraio 1999 il
|
||||||
1999 il Dipartimento di Matematica approva una delibera per stanziare la stanza 106 ed
|
Dipartimento di Matematica approva una delibera per stanziare la stanza 106, una sottorete, il
|
||||||
alcuni computer ad uso di un gruppo di studenti, così da avere un luogo in cui
|
dominio DNS phc.dm.unipi.it ed alcuni computer ad uso di un gruppo di studenti (Riccardo Murri e
|
||||||
"smanettare", dare supporto informatica agli studenti e gestire il sito Poisson.
|
Massimiliano Sala), così da avere un luogo in cui "smanettare", offrire spazio a progetti
|
||||||
|
interessanti, dare supporto informatico agli studenti e gestire il sito Poisson
|
||||||
</p>
|
</p>
|
||||||
<img
|
<img class="fill" src="https://poisson.phc.dm.unipi.it/~steffe/sergio.jpg" alt="Sergio Steffè" />
|
||||||
class="fill"
|
|
||||||
src="https://poisson.phc.dm.unipi.it/~steffe/sergio.jpg"
|
|
||||||
alt="Sergio Steffè"
|
|
||||||
/>
|
|
||||||
</Timeline>
|
</Timeline>
|
||||||
<Timeline title="Apertura di Poisson" year="~1994">
|
<Timeline title="Apertura di Poisson" year="~1995">
|
||||||
<p>
|
<p>
|
||||||
Nell'attuale Aula 4, allora semplice Aula studenti, nasce il sito web <strong
|
Nell'attuale Aula 4, allora semplice Aula studenti, nasce il sito web <strong
|
||||||
>poisson.dm.unipi.it</strong
|
>poisson.dm.unipi.it</strong
|
||||||
>
|
>
|
||||||
su dei computer messi a disposizione agli studenti da Vinicio Villani. Una versione del 1996
|
su dei computer messi a disposizione agli studenti da Vinicio Villani. Una versione del 1996 di tale
|
||||||
di tale sito si trova nel <a
|
sito si trova nel <a href="https://web.archive.org/web/19971017065805/http://poisson.dm.unipi.it/"
|
||||||
href="https://web.archive.org/web/19971017065805/http://poisson.dm.unipi.it/"
|
|
||||||
>Web Archive</a
|
>Web Archive</a
|
||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
---
|
---
|
||||||
|
import '@/styles/pages/utenti.css'
|
||||||
|
|
||||||
import PageLayout from '../layouts/PageLayout.astro'
|
import PageLayout from '../layouts/PageLayout.astro'
|
||||||
|
|
||||||
import { UtentiPage } from '../client/UtentiPage.tsx'
|
import { UtentiPage } from '../client/UtentiPage.tsx'
|
||||||
---
|
---
|
||||||
|
|
||||||
<PageLayout title="Utenti | PHC" pageTags="utenti">
|
<PageLayout title="Utenti | PHC">
|
||||||
<h1>Utenti</h1>
|
<h1>Utenti</h1>
|
||||||
<UtentiPage client:load />
|
<UtentiPage client:load />
|
||||||
</PageLayout>
|
</PageLayout>
|
||||||
|
|||||||
@@ -75,12 +75,7 @@ function setup() {
|
|||||||
const handle = window.setInterval(() => {
|
const handle = window.setInterval(() => {
|
||||||
const time = new Date().getTime() - startTime.getTime()
|
const time = new Date().getTime() - startTime.getTime()
|
||||||
|
|
||||||
update(
|
update(state, g.canvas.width / window.devicePixelRatio, g.canvas.height / window.devicePixelRatio, time)
|
||||||
state,
|
|
||||||
g.canvas.width / window.devicePixelRatio,
|
|
||||||
g.canvas.height / window.devicePixelRatio,
|
|
||||||
time
|
|
||||||
)
|
|
||||||
render(g, state, time)
|
render(g, state, time)
|
||||||
}, 1000 / RENDERER_FPS)
|
}, 1000 / RENDERER_FPS)
|
||||||
|
|
||||||
@@ -266,25 +261,16 @@ const DIR_AVAILABLE_PREDICATE: Record<WireDirection, (pos: Point2, grid: Grid<Wi
|
|||||||
implies(grid.has([x - 1, y]), () => grid.get([x - 1, y]) !== 'down-right') &&
|
implies(grid.has([x - 1, y]), () => grid.get([x - 1, y]) !== 'down-right') &&
|
||||||
implies(grid.has([x + 1, y]), () => grid.get([x + 1, y]) !== 'down-left'),
|
implies(grid.has([x + 1, y]), () => grid.get([x + 1, y]) !== 'down-left'),
|
||||||
['down-left']: ([x, y], grid) =>
|
['down-left']: ([x, y], grid) =>
|
||||||
!grid.has([x - 1, y + 1]) &&
|
!grid.has([x - 1, y + 1]) && implies(grid.has([x - 1, y]), () => grid.get([x - 1, y]) === 'down-left'),
|
||||||
implies(grid.has([x - 1, y]), () => grid.get([x - 1, y]) === 'down-left'),
|
|
||||||
['down-right']: ([x, y], grid) =>
|
['down-right']: ([x, y], grid) =>
|
||||||
!grid.has([x + 1, y + 1]) &&
|
!grid.has([x + 1, y + 1]) && implies(grid.has([x + 1, y]), () => grid.get([x + 1, y]) === 'down-right'),
|
||||||
implies(grid.has([x + 1, y]), () => grid.get([x + 1, y]) === 'down-right'),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function pruneDirections(
|
function pruneDirections(grid: Grid<WireCell>, position: Point2, directions: WireDirection[]): WireDirection[] {
|
||||||
grid: Grid<WireCell>,
|
|
||||||
position: Point2,
|
|
||||||
directions: WireDirection[]
|
|
||||||
): WireDirection[] {
|
|
||||||
return directions.filter(dir => DIR_AVAILABLE_PREDICATE[dir](position, grid))
|
return directions.filter(dir => DIR_AVAILABLE_PREDICATE[dir](position, grid))
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateWire(
|
function generateWire(grid: Grid<WireCell>, startingPoint: Point2): { position: Point2; direction: WireCell }[] {
|
||||||
grid: Grid<WireCell>,
|
|
||||||
startingPoint: Point2
|
|
||||||
): { position: Point2; direction: WireCell }[] {
|
|
||||||
const segmentLength = Math.floor(1 - Math.random() ** 2) * 10 + 30
|
const segmentLength = Math.floor(1 - Math.random() ** 2) * 10 + 30
|
||||||
let currentPosition = startingPoint
|
let currentPosition = startingPoint
|
||||||
let currentDirection: WireDirection = randomChoice(['down', 'down', 'down', 'down-left', 'down-right'])
|
let currentDirection: WireDirection = randomChoice(['down', 'down', 'down', 'down-left', 'down-right'])
|
||||||
@@ -292,11 +278,7 @@ function generateWire(
|
|||||||
const steps: { position: Point2; direction: WireCell }[] = []
|
const steps: { position: Point2; direction: WireCell }[] = []
|
||||||
|
|
||||||
for (let i = 0; i < segmentLength; i++) {
|
for (let i = 0; i < segmentLength; i++) {
|
||||||
const availableDirections = pruneDirections(grid, currentPosition, [
|
const availableDirections = pruneDirections(grid, currentPosition, ['down', 'down-left', 'down-right'])
|
||||||
'down',
|
|
||||||
'down-left',
|
|
||||||
'down-right',
|
|
||||||
])
|
|
||||||
if (availableDirections.length === 0) {
|
if (availableDirections.length === 0) {
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
@mixin neo-brutalist-card($size: 3px, $offset: $size + 1, $shadow: true, $hoverable: false) {
|
/* This file is here for historical reasons but is not used anymore */
|
||||||
|
|
||||||
|
/* @mixin neo-brutalist-card($size: 3px, $offset: $size + 1, $shadow: true, $hoverable: false) {
|
||||||
border: $size solid #222;
|
border: $size solid #222;
|
||||||
border-radius: $size * 2;
|
border-radius: $size * 2;
|
||||||
|
|
||||||
@@ -14,4 +16,4 @@
|
|||||||
box-shadow: $offset + 1 $offset + 1 0 0 #222;
|
box-shadow: $offset + 1 $offset + 1 0 0 #222;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/* This file is here for historical reasons but is not used anymore */
|
||||||
|
|
||||||
|
@layer page {
|
||||||
|
/*
|
||||||
|
.login {
|
||||||
|
background: #ddfaff;
|
||||||
|
|
||||||
|
main {
|
||||||
|
justify-self: center;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
max-width: 80ch;
|
||||||
|
padding: 3rem 0;
|
||||||
|
|
||||||
|
gap: 3rem;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
@@ -1,12 +1,15 @@
|
|||||||
// $news-bg: #fffbeb;
|
/*
|
||||||
// $news-accent-bg: #f8e8b1;
|
$news-bg: #fffbeb;
|
||||||
|
$news-accent-bg: #f8e8b1;
|
||||||
|
*/
|
||||||
|
|
||||||
@import './mixins.scss';
|
/* @TODO: SCSS conversion - @import becomes more complex */
|
||||||
|
/* @import './mixins.scss'; */
|
||||||
|
|
||||||
@layer component {
|
@layer component {
|
||||||
//
|
/*
|
||||||
// Components - for complex parts of the UI like search bars or compound buttons
|
/* Components - for complex parts of the UI like search bars or compound buttons
|
||||||
//
|
*/
|
||||||
|
|
||||||
.phosphor-icon {
|
.phosphor-icon {
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
@@ -33,7 +36,11 @@
|
|||||||
place-content: center;
|
place-content: center;
|
||||||
|
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-variation-settings: 'FILL' 0, 'wght' 300, 'GRAD' 0, 'opsz' 24;
|
font-variation-settings:
|
||||||
|
'FILL' 0,
|
||||||
|
'wght' 300,
|
||||||
|
'GRAD' 0,
|
||||||
|
'opsz' 24;
|
||||||
|
|
||||||
max-width: 32px;
|
max-width: 32px;
|
||||||
}
|
}
|
||||||
@@ -48,7 +55,13 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 2.5rem;
|
height: 2.5rem;
|
||||||
|
|
||||||
@include neo-brutalist-card;
|
/* @TODO: SCSS conversion - mixin */
|
||||||
|
/* @include neo-brutalist-card; */
|
||||||
|
border: 3px solid #222;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 4px 4px 0 0 #222;
|
||||||
|
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr auto;
|
grid-template-columns: 1fr auto;
|
||||||
@@ -56,8 +69,6 @@
|
|||||||
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
background: #fff;
|
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:hover input[type='text'] {
|
&:hover input[type='text'] {
|
||||||
background: #f8f8f8;
|
background: #f8f8f8;
|
||||||
@@ -101,7 +112,11 @@
|
|||||||
|
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
|
||||||
@include neo-brutalist-card;
|
/* @TODO: SCSS conversion - mixin */
|
||||||
|
/* @include neo-brutalist-card; */
|
||||||
|
border: 3px solid #222;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 4px 4px 0 0 #222;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
display: contents;
|
display: contents;
|
||||||
@@ -157,7 +172,16 @@
|
|||||||
aspect-ratio: 10 / 14;
|
aspect-ratio: 10 / 14;
|
||||||
background: #d0d0d0;
|
background: #d0d0d0;
|
||||||
|
|
||||||
@include neo-brutalist-card($hoverable: true);
|
/* @TODO: SCSS conversion - mixin */
|
||||||
|
/* @include neo-brutalist-card($hoverable: true); */
|
||||||
|
border: 3px solid #222;
|
||||||
|
border-radius: 6px;
|
||||||
|
transition: all 64ms linear;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translate(-1px, -1px);
|
||||||
|
box-shadow: 4px 4px 0 0 #222;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
& > .thumbnail + * {
|
& > .thumbnail + * {
|
||||||
@@ -191,7 +215,11 @@
|
|||||||
background: var(--card-bg, var(--project-card-bg));
|
background: var(--card-bg, var(--project-card-bg));
|
||||||
color: #000e;
|
color: #000e;
|
||||||
|
|
||||||
@include neo-brutalist-card($size: 3px, $offset: 9px);
|
/* @TODO: SCSS conversion - mixin */
|
||||||
|
/* @include neo-brutalist-card($size: 3px, $offset: 9px); */
|
||||||
|
border: 3px solid #222;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 9px 9px 0 0 #222;
|
||||||
|
|
||||||
row-gap: 0.5rem;
|
row-gap: 0.5rem;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
@@ -215,109 +243,109 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-auto-flow: column;
|
grid-auto-flow: column;
|
||||||
|
|
||||||
// .news-item {
|
/* .news-item {
|
||||||
// background: $news-bg;
|
background: $news-bg;
|
||||||
// color: #111;
|
color: #111;
|
||||||
|
|
||||||
// @include neo-brutalist-card($size: 3px, $offset: 9px);
|
@include neo-brutalist-card($size: 3px, $offset: 9px);
|
||||||
|
|
||||||
// display: flex;
|
display: flex;
|
||||||
// flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
// width: 22rem;
|
width: 22rem;
|
||||||
// max-height: 27rem;
|
max-height: 27rem;
|
||||||
|
|
||||||
// overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
// ::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
// width: 10px;
|
width: 10px;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// ::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
// background-color: #c67e14;
|
background-color: #c67e14;
|
||||||
// border: 2px solid #222;
|
border: 2px solid #222;
|
||||||
|
|
||||||
// &:hover {
|
&:hover {
|
||||||
// background-color: #e69419;
|
background-color: #e69419;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// a {
|
a {
|
||||||
// font-weight: 600;
|
font-weight: 600;
|
||||||
// text-decoration: none;
|
text-decoration: none;
|
||||||
// color: #c67e14;
|
color: #c67e14;
|
||||||
|
|
||||||
// &:hover {
|
&:hover {
|
||||||
// text-decoration: underline solid 2px;
|
text-decoration: underline solid 2px;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// & > .title {
|
& > .title {
|
||||||
// padding: 1rem;
|
padding: 1rem;
|
||||||
// background: $news-accent-bg;
|
background: $news-accent-bg;
|
||||||
// line-height: 1;
|
line-height: 1;
|
||||||
// font-size: 26px;
|
font-size: 26px;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// a.title {
|
a.title {
|
||||||
// color: #83530c;
|
color: #83530c;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// & > .abstract {
|
& > .abstract {
|
||||||
// flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
|
||||||
// padding: 1rem;
|
padding: 1rem;
|
||||||
|
|
||||||
// overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
// @extend .text;
|
@extend .text;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// & > .content {
|
& > .content {
|
||||||
// display: flex;
|
display: flex;
|
||||||
// padding: 1rem;
|
padding: 1rem;
|
||||||
// flex-direction: column;
|
flex-direction: column;
|
||||||
// gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
|
||||||
// background: #fff8da;
|
background: #fff8da;
|
||||||
|
|
||||||
// & > .continue {
|
& > .continue {
|
||||||
// padding: 1rem;
|
padding: 1rem;
|
||||||
|
|
||||||
// display: grid;
|
display: grid;
|
||||||
// align-items: end;
|
align-items: end;
|
||||||
// justify-content: end;
|
justify-content: end;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// & > .description {
|
& > .description {
|
||||||
// font-size: 16px;
|
font-size: 16px;
|
||||||
// line-height: 1.5;
|
line-height: 1.5;
|
||||||
|
|
||||||
// flex-grow: 1;
|
flex-grow: 1;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// & > .tags {
|
& > .tags {
|
||||||
// display: flex;
|
display: flex;
|
||||||
// gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
// flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
// font-size: 14px;
|
font-size: 14px;
|
||||||
// color: #555;
|
color: #555;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// & > .date {
|
& > .date {
|
||||||
// font-size: 14px;
|
font-size: 14px;
|
||||||
// font-style: italic;
|
font-style: italic;
|
||||||
// font-weight: 600;
|
font-weight: 600;
|
||||||
// color: #0008;
|
color: #0008;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// & > .author {
|
& > .author {
|
||||||
// font-weight: 600;
|
font-weight: 600;
|
||||||
// font-size: 15px;
|
font-size: 15px;
|
||||||
// color: #555;
|
color: #555;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline {
|
.timeline {
|
||||||
@@ -330,7 +358,7 @@
|
|||||||
max-width: 120ch;
|
max-width: 120ch;
|
||||||
grid-template-columns: 1fr var(--timeline-track-size) 1fr;
|
grid-template-columns: 1fr var(--timeline-track-size) 1fr;
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
@media screen and (max-width: 1024px) {
|
||||||
--timeline-track-size: 3rem;
|
--timeline-track-size: 3rem;
|
||||||
grid-template-columns: var(--timeline-track-size) 1fr;
|
grid-template-columns: var(--timeline-track-size) 1fr;
|
||||||
}
|
}
|
||||||
@@ -344,7 +372,7 @@
|
|||||||
grid-template-columns: auto;
|
grid-template-columns: auto;
|
||||||
padding: 2rem 1rem;
|
padding: 2rem 1rem;
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
@media screen and (max-width: 1024px) {
|
||||||
padding: 1rem 1rem 1rem 0;
|
padding: 1rem 1rem 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,7 +388,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// timeline vertical line
|
/* timeline vertical line */
|
||||||
&::before {
|
&::before {
|
||||||
content: '';
|
content: '';
|
||||||
|
|
||||||
@@ -382,7 +410,7 @@
|
|||||||
bottom: 50%;
|
bottom: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
// timeline circle
|
/* timeline circle */
|
||||||
&::after {
|
&::after {
|
||||||
content: '';
|
content: '';
|
||||||
|
|
||||||
@@ -402,7 +430,7 @@
|
|||||||
grid-column: 1 / span 1;
|
grid-column: 1 / span 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (min-width: $screen-desktop-min) {
|
@media screen and (min-width: 1024px) {
|
||||||
&:nth-child(odd)::before {
|
&:nth-child(odd)::before {
|
||||||
grid-column: 2 / span 1;
|
grid-column: 2 / span 1;
|
||||||
}
|
}
|
||||||
@@ -421,7 +449,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dropdown {
|
.dropdown {
|
||||||
@include neo-brutalist-card;
|
/* @TODO: SCSS conversion - mixin */
|
||||||
|
/* @include neo-brutalist-card; */
|
||||||
|
border: 3px solid #222;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 3px 3px 0 0 #222;
|
||||||
|
|
||||||
max-width: 15rem;
|
max-width: 15rem;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -431,8 +463,12 @@
|
|||||||
border-top: none;
|
border-top: none;
|
||||||
border-radius: 0 0 0.5rem 0.5rem;
|
border-radius: 0 0 0.5rem 0.5rem;
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
@media screen and (max-width: 1024px) {
|
||||||
@include neo-brutalist-card;
|
/* @TODO: SCSS conversion - mixin */
|
||||||
|
/* @include neo-brutalist-card; */
|
||||||
|
border: 3px solid #222;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 3px 3px 0 0 #222;
|
||||||
|
|
||||||
position: static;
|
position: static;
|
||||||
transform: none;
|
transform: none;
|
||||||
@@ -440,7 +476,7 @@
|
|||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media screen and (min-width: $screen-desktop-min) {
|
@media screen and (min-width: 1024px) {
|
||||||
&:nth-child(odd) {
|
&:nth-child(odd) {
|
||||||
grid-column: 1 / span 2;
|
grid-column: 1 / span 2;
|
||||||
grid-template-columns: 1fr var(--timeline-track-size);
|
grid-template-columns: 1fr var(--timeline-track-size);
|
||||||
@@ -471,7 +507,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
@media screen and (max-width: 1024px) {
|
||||||
grid-column: 1 / span 2;
|
grid-column: 1 / span 2;
|
||||||
|
|
||||||
grid-template-columns: var(--timeline-track-size) 1fr;
|
grid-template-columns: var(--timeline-track-size) 1fr;
|
||||||
@@ -483,9 +519,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
/*
|
||||||
// Cards
|
/* Cards
|
||||||
//
|
*/
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -495,17 +531,25 @@
|
|||||||
background: var(--card-base-internal);
|
background: var(--card-base-internal);
|
||||||
color: color-mix(in srgb, var(--card-base-internal), #000 80%);
|
color: color-mix(in srgb, var(--card-base-internal), #000 80%);
|
||||||
|
|
||||||
@include neo-brutalist-card($size: 3px, $offset: 9px);
|
/* @TODO: SCSS conversion - mixin */
|
||||||
|
/* @include neo-brutalist-card($size: 3px, $offset: 9px); */
|
||||||
|
border: 3px solid #222;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 9px 9px 0 0 #222;
|
||||||
|
|
||||||
row-gap: 0.5rem;
|
row-gap: 0.5rem;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
|
|
||||||
// Variants
|
/* Variants */
|
||||||
|
|
||||||
&.large {
|
&.large {
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
|
|
||||||
@include neo-brutalist-card($size: 4px, $offset: 8px);
|
/* @TODO: SCSS conversion - mixin */
|
||||||
|
/* @include neo-brutalist-card($size: 4px, $offset: 8px); */
|
||||||
|
border: 4px solid #222;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 8px 8px 0 0 #222;
|
||||||
|
|
||||||
row-gap: 1rem;
|
row-gap: 1rem;
|
||||||
|
|
||||||
@@ -519,7 +563,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Child Items
|
/* Child Items */
|
||||||
|
|
||||||
& > .title {
|
& > .title {
|
||||||
color: color-mix(in srgb, var(--card-base-internal), #000 75%);
|
color: color-mix(in srgb, var(--card-base-internal), #000 75%);
|
||||||
@@ -576,7 +620,7 @@
|
|||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
@media screen and (max-width: 1024px) {
|
||||||
padding: 0.9rem;
|
padding: 0.9rem;
|
||||||
|
|
||||||
&.large {
|
&.large {
|
||||||
@@ -600,7 +644,8 @@
|
|||||||
place-content: center;
|
place-content: center;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
|
|
||||||
background: #0003;
|
color: #111;
|
||||||
|
background: #0004;
|
||||||
|
|
||||||
padding: 0 0.25rem;
|
padding: 0 0.25rem;
|
||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
@@ -615,7 +660,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.disabled {
|
&.disabled {
|
||||||
color: #0005;
|
color: #0004;
|
||||||
background: #0002;
|
background: #0002;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -624,9 +669,9 @@
|
|||||||
display: contents;
|
display: contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
/*
|
||||||
// Card List
|
/* Card List
|
||||||
//
|
*/
|
||||||
|
|
||||||
.card-list {
|
.card-list {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -658,7 +703,7 @@
|
|||||||
|
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
@media screen and (max-width: 1024px) {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
|
|
||||||
& > .search {
|
& > .search {
|
||||||
@@ -713,7 +758,10 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
padding: 0 0.25rem 0 0.25rem;
|
padding: 0 0.25rem 0 0.25rem;
|
||||||
|
|
||||||
@include neo-brutalist-card;
|
/* @TODO: SCSS conversion - mixin */
|
||||||
|
border: 3px solid #222;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 4px 4px 0 0 #222;
|
||||||
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
@@ -748,7 +796,10 @@
|
|||||||
top: calc(100% + 8px);
|
top: calc(100% + 8px);
|
||||||
left: -3px;
|
left: -3px;
|
||||||
|
|
||||||
@include neo-brutalist-card;
|
/* @TODO: SCSS conversion - mixin */
|
||||||
|
border: 3px solid #222;
|
||||||
|
border-radius: 6px;
|
||||||
|
/* box-shadow: 3px 3px 0 0 #222; */
|
||||||
|
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
|
||||||
@@ -765,7 +816,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
@media screen and (max-width: 1024px) {
|
||||||
.dropdown {
|
.dropdown {
|
||||||
left: 3px;
|
left: 3px;
|
||||||
right: 3px;
|
right: 3px;
|
||||||
@@ -776,10 +827,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.gallery-collage {
|
.gallery-collage {
|
||||||
// display: flex;
|
/* display: flex;
|
||||||
// flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
// width: 64rem;
|
width: 64rem; */
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
@@ -794,9 +845,9 @@
|
|||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
|
||||||
place-content: center;
|
place-content: center;
|
||||||
// align-items: center;
|
/* align-items: center; */
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
@media screen and (max-width: 1024px) {
|
||||||
grid-template-columns: auto;
|
grid-template-columns: auto;
|
||||||
grid-template-rows: auto;
|
grid-template-rows: auto;
|
||||||
grid-auto-rows: auto;
|
grid-auto-rows: auto;
|
||||||
@@ -813,7 +864,7 @@
|
|||||||
grid-column: span var(--cols, 1);
|
grid-column: span var(--cols, 1);
|
||||||
grid-row: span var(--rows, 1);
|
grid-row: span var(--rows, 1);
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
@media screen and (max-width: 1024px) {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
|
||||||
grid-column: span 1;
|
grid-column: span 1;
|
||||||
@@ -832,7 +883,7 @@
|
|||||||
|
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
@media screen and (max-width: 1024px) {
|
||||||
max-height: none;
|
max-height: none;
|
||||||
|
|
||||||
width: 25rem;
|
width: 25rem;
|
||||||
@@ -847,17 +898,15 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 3rem 6rem;
|
gap: 3rem 0rem;
|
||||||
|
|
||||||
> .bubble {
|
> .bubble {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: auto auto auto auto;
|
|
||||||
grid-auto-rows: auto;
|
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
justify-items: center;
|
justify-items: center;
|
||||||
align-content: start;
|
align-content: start;
|
||||||
width: 28ch;
|
width: 18rem;
|
||||||
|
|
||||||
.date {
|
.date {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -869,6 +918,29 @@
|
|||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.founder {
|
||||||
|
display: grid;
|
||||||
|
place-content: center;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 700;
|
||||||
|
|
||||||
|
/* gold badge */
|
||||||
|
background: #ffdb12;
|
||||||
|
color: #725306;
|
||||||
|
|
||||||
|
padding: 0 0.25rem;
|
||||||
|
|
||||||
|
border: 2px solid #b98c19;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
|
||||||
|
box-shadow: 0.125rem 0.125rem 0 0 #664b06;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
font-size: 16px;
|
||||||
|
text-wrap: balance;
|
||||||
|
}
|
||||||
|
|
||||||
.social {
|
.social {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-auto-flow: column;
|
grid-auto-flow: column;
|
||||||
@@ -887,25 +959,33 @@
|
|||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
aspect-ratio: 1 / 1;
|
aspect-ratio: 1 / 1;
|
||||||
|
|
||||||
|
width: 12rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.wide-card-list {
|
.wide-card-list {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(auto, 30rem));
|
grid-template-columns: repeat(auto-fit, minmax(auto, 28rem));
|
||||||
gap: 2rem;
|
gap: 2rem;
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
/* align-items: start; */
|
||||||
|
|
||||||
.text > * {
|
.text > * {
|
||||||
max-width: none;
|
max-width: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
.card {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: 1fr auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1024px) {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -966,7 +1046,7 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// just to know for reference
|
/* just to know for reference */
|
||||||
.fake-masonry {
|
.fake-masonry {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(var(--columns), 1fr);
|
grid-template-columns: repeat(var(--columns), 1fr);
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
@import './mixins.scss';
|
/* @import './mixins.scss'; */
|
||||||
|
|
||||||
//
|
/*
|
||||||
// Controls - for things like buttons, input, select
|
Controls - for things like buttons, input, select
|
||||||
//
|
*/
|
||||||
|
|
||||||
@layer common {
|
@layer base {
|
||||||
button,
|
button,
|
||||||
.button,
|
.button,
|
||||||
[role='button'] {
|
[role='button'] {
|
||||||
@@ -12,7 +12,10 @@
|
|||||||
|
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
|
||||||
@include neo-brutalist-card;
|
/* @include neo-brutalist-card; */
|
||||||
|
border: 3px solid #222;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 4px 4px 0 0 #222;
|
||||||
|
|
||||||
transition: all 64ms linear;
|
transition: all 64ms linear;
|
||||||
|
|
||||||
@@ -35,7 +38,7 @@
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #222;
|
color: #222;
|
||||||
|
|
||||||
font-family: var(--font-secondary);
|
font-family: var(--font-secondary); /* TODO: check if this is a global variable and replace */
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -72,9 +75,12 @@
|
|||||||
input[type='text'],
|
input[type='text'],
|
||||||
input[type='password'] {
|
input[type='password'] {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 2.5rem;
|
min-height: 1.75rem;
|
||||||
|
|
||||||
@include neo-brutalist-card;
|
/* @include neo-brutalist-card; */
|
||||||
|
border: 3px solid #222;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 4px 4px 0 0 #222;
|
||||||
|
|
||||||
padding: 0 0.25rem;
|
padding: 0 0.25rem;
|
||||||
|
|
||||||
@@ -83,6 +89,95 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type='checkbox'] {
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
|
||||||
|
width: calc(1.5rem + 1px);
|
||||||
|
height: calc(1.5rem + 1px);
|
||||||
|
|
||||||
|
background: #fff;
|
||||||
|
border: 3px solid #222;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 3px 3px 0 0 #222;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
transition: all 64ms linear;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translate(-1px, -1px);
|
||||||
|
box-shadow: 4px 4px 0 0 #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: translate(1px, 1px);
|
||||||
|
box-shadow: 2px 2px 0 0 #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:checked {
|
||||||
|
background: #1e6733;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
|
width: 0.8rem;
|
||||||
|
height: 0.8rem;
|
||||||
|
background: #1e6733;
|
||||||
|
|
||||||
|
clip-path: polygon(10% 55%, 35% 75%, 85% 25%, 90% 35%, 40% 95%, 5% 60%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #2b8b47;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
background: #eee;
|
||||||
|
border-color: #888;
|
||||||
|
box-shadow: 3px 3px 0 0 #888;
|
||||||
|
cursor: not-allowed;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: none;
|
||||||
|
box-shadow: 3px 3px 0 0 #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:checked {
|
||||||
|
background: #aaa;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
background: #666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.star {
|
||||||
|
&:checked::after {
|
||||||
|
background: rgb(255, 197, 49);
|
||||||
|
clip-path: polygon(
|
||||||
|
50% 0%,
|
||||||
|
61% 35%,
|
||||||
|
98% 35%,
|
||||||
|
68% 57%,
|
||||||
|
79% 91%,
|
||||||
|
50% 70%,
|
||||||
|
21% 91%,
|
||||||
|
32% 57%,
|
||||||
|
2% 35%,
|
||||||
|
39% 35%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
form {
|
form {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
@@ -92,7 +187,10 @@
|
|||||||
|
|
||||||
min-width: 40ch;
|
min-width: 40ch;
|
||||||
|
|
||||||
@include neo-brutalist-card($size: 3px, $offset: 9px);
|
/* @include neo-brutalist-card($size: 3px, $offset: 9px); */
|
||||||
|
border: 3px solid #222;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 9px 9px 0 0 #222;
|
||||||
|
|
||||||
button,
|
button,
|
||||||
.button,
|
.button,
|
||||||
@@ -165,7 +263,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
@media screen and (max-width: 1024px) {
|
||||||
|
/* TODO: check if this is a global variable and replace */
|
||||||
summary {
|
summary {
|
||||||
place-content: stretch;
|
place-content: stretch;
|
||||||
place-items: stretch;
|
place-items: stretch;
|
||||||
@@ -0,0 +1,371 @@
|
|||||||
|
@layer base, typography, component, page, utility;
|
||||||
|
|
||||||
|
@import url(./controls.css);
|
||||||
|
@import url(./components.css);
|
||||||
|
@import url(./typography.css);
|
||||||
|
|
||||||
|
/* $screen-desktop-min: 1024px; */
|
||||||
|
/* @TODO: SCSS conversion - @import becomes more complex */
|
||||||
|
/* @import './mixins.scss'; */
|
||||||
|
/* @import './typography.scss'; */
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--palette-black: #222;
|
||||||
|
--border-large: 4px solid var(--palette-black);
|
||||||
|
|
||||||
|
--header-bg: #fff;
|
||||||
|
|
||||||
|
--footer-bg: #444;
|
||||||
|
--footer-fg: #fdfdfd;
|
||||||
|
|
||||||
|
--homepage-principal-bg: #ecffe3;
|
||||||
|
--homepage-whatsphc-bg: #e4c5ff;
|
||||||
|
--homepage-news-bg: #c2a8eb;
|
||||||
|
--homepage-projects-bg: #f5f2cc;
|
||||||
|
--homepage-macchinisti-bg: #888;
|
||||||
|
|
||||||
|
--project-card-bg: #a2d4f3;
|
||||||
|
|
||||||
|
--font-primary: 'Open Sans', sans-serif;
|
||||||
|
--font-display: 'Iosevka', monospace;
|
||||||
|
--font-mono: 'Source Code Pro', monospace;
|
||||||
|
--font-secondary: 'Source Sans Pro', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--guide-base: #a2d4f3;
|
||||||
|
|
||||||
|
--guide-darkest: color-mix(in srgb, var(--guide-base), #000 75%);
|
||||||
|
--guide-darker: color-mix(in srgb, var(--guide-base), #000 50%);
|
||||||
|
--guide-dark: color-mix(in srgb, var(--guide-base), #000 25%);
|
||||||
|
|
||||||
|
--guide-light: color-mix(in srgb, var(--guide-base), #fff 25%);
|
||||||
|
--guide-lighter: color-mix(in srgb, var(--guide-base), #fff 50%);
|
||||||
|
--guide-lightest: color-mix(in srgb, var(--guide-base), #fff 75%);
|
||||||
|
|
||||||
|
--news-base: #f8e8b1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
font: inherit;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
min-height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
font-family: var(--font-primary);
|
||||||
|
font-size: 18px;
|
||||||
|
color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
html {
|
||||||
|
scroll-snap-type: y mandatory;
|
||||||
|
scroll-padding-top: 4rem;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
img {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
/*
|
||||||
|
for the header spacing
|
||||||
|
padding-top: 6rem;
|
||||||
|
*/
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: auto 1fr auto;
|
||||||
|
|
||||||
|
header {
|
||||||
|
z-index: 10;
|
||||||
|
|
||||||
|
height: 6rem;
|
||||||
|
border-bottom: var(--border-large);
|
||||||
|
background: var(--header-bg);
|
||||||
|
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
|
||||||
|
top: 0;
|
||||||
|
position: sticky;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
padding-left: 1rem;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 3.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.links {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1.5rem;
|
||||||
|
|
||||||
|
padding: 0 1.5rem;
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-family: var(--font-display);
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
color: #333;
|
||||||
|
|
||||||
|
padding: 0.25rem 1.325rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1024px) {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.side-menu {
|
||||||
|
position: fixed;
|
||||||
|
|
||||||
|
/*
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 3rem;
|
||||||
|
*/
|
||||||
|
|
||||||
|
top: 5rem;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
background: #f0f0f0;
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
/*
|
||||||
|
grid-template-rows: auto 1fr;
|
||||||
|
*/
|
||||||
|
grid-template-rows: 1fr;
|
||||||
|
|
||||||
|
gap: 1.5rem;
|
||||||
|
padding: 1.5rem;
|
||||||
|
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
/*
|
||||||
|
& > :first-child {
|
||||||
|
justify-self: end;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
.links {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
|
||||||
|
align-content: start;
|
||||||
|
|
||||||
|
width: calc(100vw - 3rem);
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
|
gap: 1.5rem;
|
||||||
|
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#header-menu-toggle {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
&:not(:checked) ~ .side-menu {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:has(#header-menu-toggle:checked) #header-menu-toggle-menu {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:has(#header-menu-toggle:not(:checked)) #header-menu-toggle-close {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1024px) {
|
||||||
|
height: 5rem;
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
padding-left: 0;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
@media screen and (max-width: 1024px) {
|
||||||
|
padding: 3rem 1rem;
|
||||||
|
gap: 3rem;
|
||||||
|
|
||||||
|
.card {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
z-index: 10;
|
||||||
|
padding: 1rem 0;
|
||||||
|
--paragraph-margin: 0.5rem;
|
||||||
|
--zone-color: #aaa;
|
||||||
|
|
||||||
|
min-height: 6rem;
|
||||||
|
border-top: var(--border-large);
|
||||||
|
background: var(--footer-bg);
|
||||||
|
color: var(--footer-fg);
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
place-content: center;
|
||||||
|
|
||||||
|
font-family: var(--font-secondary);
|
||||||
|
font-size: 18px;
|
||||||
|
|
||||||
|
scroll-snap-align: end;
|
||||||
|
|
||||||
|
@media screen and (max-width: 1024px) {
|
||||||
|
min-height: 5rem;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track:vertical {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border-left: 2px solid #222;
|
||||||
|
border-top: 2px solid #222;
|
||||||
|
border-bottom: 2px solid #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track:horizontal {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border-top: 2px solid #222;
|
||||||
|
border-left: 2px solid #222;
|
||||||
|
border-right: 2px solid #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background-color: #1e6733;
|
||||||
|
border: 2px solid #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background-color: #2b8b47;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-corner {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
/* border-left: 2px solid #222; */
|
||||||
|
/* border-top: 2px solid #222; */
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::selection {
|
||||||
|
background: #0002;
|
||||||
|
}
|
||||||
|
|
||||||
|
body:has(#header-menu-toggle:checked) {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Typography
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @TODO: SCSS conversion - @import becomes more complex */
|
||||||
|
/* @import './controls.scss'; */
|
||||||
|
/* @import './components.scss'; */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Custom Page Styles
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @TODO: SCSS conversion - @import becomes more complex */
|
||||||
|
/* @import './pages.scss'; */
|
||||||
|
|
||||||
|
@layer utility {
|
||||||
|
.hide {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.invisible {
|
||||||
|
opacity: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-center {
|
||||||
|
display: grid;
|
||||||
|
place-content: center;
|
||||||
|
place-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-flex {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-flex {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-flex,
|
||||||
|
.v-flex {
|
||||||
|
place-self: stretch;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .spacer {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 1024px) {
|
||||||
|
.mobile-only {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1024px) {
|
||||||
|
.desktop-only {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,313 +0,0 @@
|
|||||||
$screen-desktop-min: 1024px;
|
|
||||||
|
|
||||||
:root {
|
|
||||||
--palette-black: #222;
|
|
||||||
--border-large: 4px solid var(--palette-black);
|
|
||||||
|
|
||||||
--header-bg: #fff;
|
|
||||||
|
|
||||||
--footer-bg: #444;
|
|
||||||
--footer-fg: #fdfdfd;
|
|
||||||
|
|
||||||
--homepage-principal-bg: #ecffe3;
|
|
||||||
--homepage-whatsphc-bg: #e4c5ff;
|
|
||||||
--homepage-news-bg: #c2a8eb;
|
|
||||||
--homepage-projects-bg: #f5f2cc;
|
|
||||||
--homepage-macchinisti-bg: #888;
|
|
||||||
|
|
||||||
--project-card-bg: #a2d4f3;
|
|
||||||
|
|
||||||
--font-primary: 'Open Sans', sans-serif;
|
|
||||||
--font-display: 'Iosevka', monospace;
|
|
||||||
--font-mono: 'Source Code Pro', monospace;
|
|
||||||
--font-secondary: 'Source Sans Pro', sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
@layer common, typography, component, page;
|
|
||||||
|
|
||||||
@import './mixins.scss';
|
|
||||||
@import './typography.scss';
|
|
||||||
|
|
||||||
@layer common {
|
|
||||||
*,
|
|
||||||
*::before,
|
|
||||||
*::after {
|
|
||||||
box-sizing: border-box;
|
|
||||||
font: inherit;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
html,
|
|
||||||
body {
|
|
||||||
min-height: 100%;
|
|
||||||
margin: 0;
|
|
||||||
|
|
||||||
font-family: var(--font-primary);
|
|
||||||
font-size: 18px;
|
|
||||||
color: #222;
|
|
||||||
}
|
|
||||||
|
|
||||||
// html {
|
|
||||||
// scroll-snap-type: y mandatory;
|
|
||||||
// scroll-padding-top: 4rem;
|
|
||||||
// }
|
|
||||||
|
|
||||||
img {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Typography
|
|
||||||
//
|
|
||||||
|
|
||||||
@import './controls.scss';
|
|
||||||
@import './components.scss';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Custom Page Styles
|
|
||||||
//
|
|
||||||
|
|
||||||
body {
|
|
||||||
// for the header spacing
|
|
||||||
// padding-top: 6rem;
|
|
||||||
|
|
||||||
display: grid;
|
|
||||||
grid-template-rows: auto 1fr auto;
|
|
||||||
|
|
||||||
header {
|
|
||||||
z-index: 10;
|
|
||||||
|
|
||||||
height: 6rem;
|
|
||||||
border-bottom: var(--border-large);
|
|
||||||
background: var(--header-bg);
|
|
||||||
|
|
||||||
grid-column: 1 / -1;
|
|
||||||
|
|
||||||
top: 0;
|
|
||||||
position: sticky;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
padding-left: 1rem;
|
|
||||||
|
|
||||||
img {
|
|
||||||
height: 3.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.links {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 1.5rem;
|
|
||||||
|
|
||||||
padding: 0 1.5rem;
|
|
||||||
|
|
||||||
a {
|
|
||||||
font-family: var(--font-display);
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 500;
|
|
||||||
letter-spacing: 1px;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.side-menu {
|
|
||||||
position: fixed;
|
|
||||||
|
|
||||||
// top: 0;
|
|
||||||
// right: 0;
|
|
||||||
// bottom: 0;
|
|
||||||
// left: 3rem;
|
|
||||||
|
|
||||||
top: 5rem;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
|
|
||||||
background: #f0f0f0;
|
|
||||||
|
|
||||||
display: grid;
|
|
||||||
// grid-template-rows: auto 1fr;
|
|
||||||
grid-template-rows: 1fr;
|
|
||||||
|
|
||||||
gap: 1.5rem;
|
|
||||||
padding: 1.5rem;
|
|
||||||
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
// & > :first-child {
|
|
||||||
// justify-self: end;
|
|
||||||
// }
|
|
||||||
|
|
||||||
.links {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
|
|
||||||
align-content: start;
|
|
||||||
|
|
||||||
width: calc(100vw - 3rem);
|
|
||||||
max-width: 100%;
|
|
||||||
|
|
||||||
gap: 1.5rem;
|
|
||||||
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#header-menu-toggle {
|
|
||||||
display: none;
|
|
||||||
|
|
||||||
&:not(:checked) ~ .side-menu {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:has(#header-menu-toggle:checked) #header-menu-toggle-menu {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:has(#header-menu-toggle:not(:checked)) #header-menu-toggle-close {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
|
||||||
height: 5rem;
|
|
||||||
padding: 0 0.5rem;
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
padding-left: 0;
|
|
||||||
|
|
||||||
img {
|
|
||||||
height: 3rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
|
||||||
padding: 3rem 1rem;
|
|
||||||
gap: 3rem;
|
|
||||||
|
|
||||||
.card {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
|
||||||
z-index: 10;
|
|
||||||
padding: 1rem 0;
|
|
||||||
--paragraph-margin: 0.5rem;
|
|
||||||
--zone-color: #aaa;
|
|
||||||
|
|
||||||
min-height: 6rem;
|
|
||||||
border-top: var(--border-large);
|
|
||||||
background: var(--footer-bg);
|
|
||||||
color: var(--footer-fg);
|
|
||||||
|
|
||||||
display: grid;
|
|
||||||
place-content: center;
|
|
||||||
|
|
||||||
font-family: var(--font-secondary);
|
|
||||||
font-size: 18px;
|
|
||||||
|
|
||||||
scroll-snap-align: end;
|
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
|
||||||
min-height: 5rem;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@import './pages.scss';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Misc
|
|
||||||
//
|
|
||||||
|
|
||||||
::-webkit-scrollbar-track:vertical {
|
|
||||||
background-color: #f0f0f0;
|
|
||||||
border-left: 2px solid #222;
|
|
||||||
border-top: 2px solid #222;
|
|
||||||
border-bottom: 2px solid #222;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-track:horizontal {
|
|
||||||
background-color: #f0f0f0;
|
|
||||||
border-top: 2px solid #222;
|
|
||||||
border-left: 2px solid #222;
|
|
||||||
border-right: 2px solid #222;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
|
||||||
background-color: #1e6733;
|
|
||||||
border: 2px solid #222;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb:hover {
|
|
||||||
background-color: #2b8b47;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-corner {
|
|
||||||
background-color: #f0f0f0;
|
|
||||||
// border-left: 2px solid #222;
|
|
||||||
// border-top: 2px solid #222;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
|
||||||
width: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
::selection {
|
|
||||||
background: #0002;
|
|
||||||
}
|
|
||||||
|
|
||||||
body:has(#header-menu-toggle:checked) {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Utility Classes
|
|
||||||
//
|
|
||||||
|
|
||||||
.hide {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.invisible {
|
|
||||||
opacity: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: $screen-desktop-min) {
|
|
||||||
.mobile-only {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
|
||||||
.desktop-only {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,879 +0,0 @@
|
|||||||
:root {
|
|
||||||
--guide-base: #a2d4f3;
|
|
||||||
|
|
||||||
--guide-darkest: color-mix(in srgb, var(--guide-base), #000 75%);
|
|
||||||
--guide-darker: color-mix(in srgb, var(--guide-base), #000 50%);
|
|
||||||
--guide-dark: color-mix(in srgb, var(--guide-base), #000 25%);
|
|
||||||
|
|
||||||
--guide-light: color-mix(in srgb, var(--guide-base), #fff 25%);
|
|
||||||
--guide-lighter: color-mix(in srgb, var(--guide-base), #fff 50%);
|
|
||||||
--guide-lightest: color-mix(in srgb, var(--guide-base), #fff 75%);
|
|
||||||
|
|
||||||
--news-base: #f8e8b1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@layer page {
|
|
||||||
.homepage {
|
|
||||||
header:has(#header-menu-toggle:not(:checked)) .logo {
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
section {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
min-height: calc(100vh - 6rem);
|
|
||||||
|
|
||||||
&:last-of-type {
|
|
||||||
min-height: calc(100vh - 10rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
// display: flex;
|
|
||||||
// flex-direction: column;
|
|
||||||
// align-items: center;
|
|
||||||
& {
|
|
||||||
display: grid;
|
|
||||||
grid-auto-flow: row;
|
|
||||||
justify-items: center;
|
|
||||||
align-content: start;
|
|
||||||
|
|
||||||
gap: 2rem;
|
|
||||||
|
|
||||||
scroll-snap-align: start;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .title {
|
|
||||||
font-size: 48px;
|
|
||||||
padding-top: 4rem;
|
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
|
||||||
padding-top: 2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.zig-zag {
|
|
||||||
z-index: 5;
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
bottom: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
section.principal {
|
|
||||||
z-index: 2;
|
|
||||||
|
|
||||||
min-height: calc(100vh - 7rem);
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
|
|
||||||
align-items: center;
|
|
||||||
place-content: center;
|
|
||||||
|
|
||||||
gap: 4rem;
|
|
||||||
|
|
||||||
padding: 3rem 2rem 6rem;
|
|
||||||
|
|
||||||
background: var(--homepage-principal-bg);
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.circuit-layer {
|
|
||||||
pointer-events: none;
|
|
||||||
|
|
||||||
z-index: 1;
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
canvas {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .logo {
|
|
||||||
z-index: 2;
|
|
||||||
|
|
||||||
width: 32rem;
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
user-select: none;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
// filter: drop-shadow(6px 6px 0 var(--palette-black))
|
|
||||||
// drop-shadow(4px 0 0 var(--palette-black)) drop-shadow(0 4px 0 var(--palette-black))
|
|
||||||
// drop-shadow(-4px 0 0 var(--palette-black)) drop-shadow(0 -4px 0 var(--palette-black));
|
|
||||||
}
|
|
||||||
|
|
||||||
max-width: calc(100vw - 3rem);
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .whats-phc {
|
|
||||||
z-index: 2;
|
|
||||||
background: #e4c5ff;
|
|
||||||
|
|
||||||
--zone-color: color-mix(in lab, #e4c5ff, #000 75%);
|
|
||||||
|
|
||||||
max-width: 37rem;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
text-decoration: underline 2px solid;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
--zone-color: color-mix(in lab, #e4c5ff, #000 60%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
span.highlighted {
|
|
||||||
background: color-mix(in lab, #e4c5ff, #000 10%);
|
|
||||||
cursor: default;
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
padding: 0.125rem 0.25rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
section.news {
|
|
||||||
--card-base: color-mix(in lab, var(--news-base), #fff 25%);
|
|
||||||
--zone-color: color-mix(in lab, var(--news-base), #000 50%);
|
|
||||||
|
|
||||||
background: var(--homepage-news-bg);
|
|
||||||
|
|
||||||
gap: 3rem;
|
|
||||||
|
|
||||||
padding-bottom: 6rem;
|
|
||||||
|
|
||||||
& > .news-list {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 3rem;
|
|
||||||
|
|
||||||
align-items: flex-start;
|
|
||||||
|
|
||||||
padding: 0 3rem;
|
|
||||||
|
|
||||||
justify-content: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
[role='button'] {
|
|
||||||
padding: 0.5rem 2rem;
|
|
||||||
|
|
||||||
&.primary {
|
|
||||||
background: #ffdd6e;
|
|
||||||
color: #000d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
section.projects {
|
|
||||||
background: var(--homepage-projects-bg);
|
|
||||||
|
|
||||||
padding-bottom: 6rem;
|
|
||||||
|
|
||||||
.project-list {
|
|
||||||
// width: calc(20rem * 3 + 1.5rem * 2 + 6rem * 2);
|
|
||||||
// max-width: calc(100vw - 2rem); // HACK: capire come si propagano le width per bene
|
|
||||||
|
|
||||||
max-width: calc(20rem * 3 + 1.5rem * 2 + 1rem * 2);
|
|
||||||
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
|
|
||||||
grid-auto-flow: dense;
|
|
||||||
|
|
||||||
gap: 1.5rem;
|
|
||||||
padding: 0 1rem;
|
|
||||||
|
|
||||||
& > * {
|
|
||||||
grid-row: span var(--masonry-height);
|
|
||||||
}
|
|
||||||
|
|
||||||
.project {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
// background: #fcddff;
|
|
||||||
// background: #ffa89c;
|
|
||||||
background: var(--card-bg, var(--project-card-bg));
|
|
||||||
color: #000e;
|
|
||||||
|
|
||||||
@include neo-brutalist-card($size: 3px, $offset: 9px);
|
|
||||||
|
|
||||||
padding: 1rem;
|
|
||||||
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: auto 1fr;
|
|
||||||
grid-template-rows: auto 1fr;
|
|
||||||
|
|
||||||
gap: 0.25rem 1rem;
|
|
||||||
|
|
||||||
transition: all 128ms ease-out;
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 32px;
|
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
|
||||||
font-size: 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.image {
|
|
||||||
grid-row: span 2;
|
|
||||||
// place-self: center;
|
|
||||||
|
|
||||||
.box {
|
|
||||||
background: #0003;
|
|
||||||
border: 3px solid #0006;
|
|
||||||
border-radius: 6px;
|
|
||||||
width: 4rem;
|
|
||||||
height: 4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
object-fit: cover;
|
|
||||||
width: 4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
// &.auto {
|
|
||||||
// img {
|
|
||||||
// width: auto;
|
|
||||||
// height: auto;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
font-size: 16px;
|
|
||||||
@extend .text;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
transform: translate(0, -4px);
|
|
||||||
box-shadow: 9px 13px 0 0 #222;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
|
||||||
padding: 0 1rem;
|
|
||||||
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
|
|
||||||
.project {
|
|
||||||
padding: 0.8rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
section.wanna-be-macchinista {
|
|
||||||
background: var(--homepage-macchinisti-bg);
|
|
||||||
color: #fdfdfd;
|
|
||||||
|
|
||||||
padding-bottom: 6rem;
|
|
||||||
|
|
||||||
.card {
|
|
||||||
max-width: 40rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
@extend .text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
|
||||||
& > main {
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
section.principal {
|
|
||||||
padding: 3rem 0 6rem;
|
|
||||||
|
|
||||||
.whats-phc {
|
|
||||||
padding: 1.5rem;
|
|
||||||
|
|
||||||
margin: 0 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#mobile-whats-phc-read-more {
|
|
||||||
&:checked ~ .text {
|
|
||||||
max-height: 7lh;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
height: 3lh;
|
|
||||||
|
|
||||||
background: linear-gradient(to bottom, transparent, #e4c5ff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(:checked) ~ * .button span:nth-child(1) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
&:checked ~ * .button span:nth-child(2) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
section.news {
|
|
||||||
& > .news-list {
|
|
||||||
padding: 0 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
section.projects {
|
|
||||||
.project-list {
|
|
||||||
padding: 0 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
section.wanna-be-macchinista {
|
|
||||||
.content {
|
|
||||||
padding: 0 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
section {
|
|
||||||
padding: 1rem 1rem 4rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.utenti {
|
|
||||||
background: #ffffe4;
|
|
||||||
|
|
||||||
--filter-bg-color: #ffd270;
|
|
||||||
|
|
||||||
main {
|
|
||||||
justify-self: center;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
padding: 5rem 0;
|
|
||||||
|
|
||||||
gap: 5rem;
|
|
||||||
|
|
||||||
max-width: 80ch;
|
|
||||||
|
|
||||||
.search-result {
|
|
||||||
background: #ffeabc;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
background: #ffd270;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.appunti {
|
|
||||||
main {
|
|
||||||
background: #e8e8e8;
|
|
||||||
|
|
||||||
justify-self: center;
|
|
||||||
|
|
||||||
display: grid;
|
|
||||||
grid-auto-flow: row;
|
|
||||||
|
|
||||||
justify-items: center;
|
|
||||||
|
|
||||||
padding: 3rem;
|
|
||||||
|
|
||||||
gap: 3rem;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
content: '';
|
|
||||||
width: 100%;
|
|
||||||
height: 80vh;
|
|
||||||
|
|
||||||
background: linear-gradient(to bottom, transparent, #e8e8e8);
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search {
|
|
||||||
max-width: 80ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.appunti-scrollable {
|
|
||||||
justify-self: stretch;
|
|
||||||
|
|
||||||
&.center {
|
|
||||||
justify-self: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.domande-esami {
|
|
||||||
background: hsl(45, 100%, 95%);
|
|
||||||
--card-base: hsl(45, 100%, 80%);
|
|
||||||
|
|
||||||
main {
|
|
||||||
justify-self: center;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
padding: 4rem 0;
|
|
||||||
|
|
||||||
gap: 2rem;
|
|
||||||
|
|
||||||
.search {
|
|
||||||
max-width: 80ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
background: hsl(45, 100%, 72%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card a {
|
|
||||||
color: color-mix(in srgb, var(--card-base-internal), #000 80%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// .login {
|
|
||||||
// background: #ddfaff;
|
|
||||||
|
|
||||||
// main {
|
|
||||||
// justify-self: center;
|
|
||||||
|
|
||||||
// display: flex;
|
|
||||||
// flex-direction: column;
|
|
||||||
// align-items: center;
|
|
||||||
|
|
||||||
// max-width: 80ch;
|
|
||||||
// padding: 3rem 0;
|
|
||||||
|
|
||||||
// gap: 3rem;
|
|
||||||
|
|
||||||
// h3 {
|
|
||||||
// font-size: 28px;
|
|
||||||
// font-weight: 600;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Notizie
|
|
||||||
//
|
|
||||||
|
|
||||||
.notizie,
|
|
||||||
.notizia {
|
|
||||||
--card-base: color-mix(in lab, var(--news-base), #fff 25%);
|
|
||||||
--zone-color: color-mix(in lab, var(--news-base), #000 75%);
|
|
||||||
background: color-mix(in lab, var(--news-base), #fff 90%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.notizie {
|
|
||||||
h1 > a {
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline 3px solid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
justify-self: center;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
padding: 5rem;
|
|
||||||
gap: 5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.notizia {
|
|
||||||
main {
|
|
||||||
--card-base: color-mix(in lab, var(--news-base), #fff 25%);
|
|
||||||
|
|
||||||
max-width: calc(46rem + 2rem * 2);
|
|
||||||
justify-self: center;
|
|
||||||
padding: 3rem 2rem 2rem;
|
|
||||||
|
|
||||||
margin-top: 3rem;
|
|
||||||
margin-bottom: 6rem;
|
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
|
||||||
box-shadow: none;
|
|
||||||
border: none;
|
|
||||||
border-radius: 0;
|
|
||||||
max-width: none;
|
|
||||||
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Guide
|
|
||||||
//
|
|
||||||
|
|
||||||
.guide,
|
|
||||||
.guida {
|
|
||||||
--card-base: color-mix(in lab, var(--guide-base), #fff 25%);
|
|
||||||
--zone-color: color-mix(in lab, var(--guide-base), #000 75%);
|
|
||||||
background: color-mix(in lab, var(--guide-base), #fff 90%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.guide {
|
|
||||||
h1 > a {
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline 3px solid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
justify-self: center;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
padding: 5rem;
|
|
||||||
gap: 5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.guida {
|
|
||||||
main {
|
|
||||||
--card-base: color-mix(in lab, var(--guide-base), #fff 50%);
|
|
||||||
|
|
||||||
max-width: calc(46rem + 2rem * 2);
|
|
||||||
justify-self: center;
|
|
||||||
padding: 3rem 2rem 2rem;
|
|
||||||
|
|
||||||
margin-top: 3rem;
|
|
||||||
margin-bottom: 6rem;
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.metadata {
|
|
||||||
position: absolute;
|
|
||||||
top: -2px;
|
|
||||||
left: calc(100% + 2rem);
|
|
||||||
width: 15rem;
|
|
||||||
|
|
||||||
display: grid;
|
|
||||||
grid-auto-flow: row;
|
|
||||||
gap: 1rem;
|
|
||||||
|
|
||||||
justify-items: start;
|
|
||||||
|
|
||||||
.metadata-item {
|
|
||||||
background: var(--card-base);
|
|
||||||
|
|
||||||
display: grid;
|
|
||||||
grid-template-rows: auto auto;
|
|
||||||
justify-items: start;
|
|
||||||
gap: 0.25rem;
|
|
||||||
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
|
|
||||||
@include neo-brutalist-card($size: 3px);
|
|
||||||
|
|
||||||
.tags {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
|
||||||
box-shadow: none;
|
|
||||||
border: none;
|
|
||||||
border-radius: 0;
|
|
||||||
max-width: none;
|
|
||||||
|
|
||||||
margin: 0 auto;
|
|
||||||
|
|
||||||
.metadata {
|
|
||||||
position: static;
|
|
||||||
padding: 0;
|
|
||||||
width: auto;
|
|
||||||
margin: 0;
|
|
||||||
|
|
||||||
--card-base: color-mix(in lab, var(--guide-base), #fff 30%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag {
|
|
||||||
main {
|
|
||||||
justify-self: center;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
padding: 5rem 0;
|
|
||||||
gap: 5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.storia {
|
|
||||||
--card-base: #e4c5ff;
|
|
||||||
|
|
||||||
main {
|
|
||||||
justify-self: center;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
padding: 5rem 0;
|
|
||||||
gap: 3rem;
|
|
||||||
|
|
||||||
// background horizontal linear gradient that is black in the center
|
|
||||||
background: linear-gradient(
|
|
||||||
to right,
|
|
||||||
#ffe4c544 0%,
|
|
||||||
// #ffe4c599 25%,
|
|
||||||
#ffe4c5ff 50%,
|
|
||||||
// #ffe4c599 75%,
|
|
||||||
#ffe4c544 100%
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.macchinisti {
|
|
||||||
main {
|
|
||||||
justify-self: center;
|
|
||||||
background: linear-gradient(to top, #d5fbff, #ffd9d5);
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
padding: 6rem;
|
|
||||||
gap: 6rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Meta
|
|
||||||
//
|
|
||||||
|
|
||||||
.design {
|
|
||||||
grid-template-columns: minmax(15rem, 2fr) 10fr;
|
|
||||||
|
|
||||||
@media screen and (max-width: 1400px) {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
aside {
|
|
||||||
margin: 1rem;
|
|
||||||
padding: 1rem;
|
|
||||||
|
|
||||||
@include neo-brutalist-card();
|
|
||||||
|
|
||||||
background: #f0f0f0;
|
|
||||||
|
|
||||||
align-self: start;
|
|
||||||
position: sticky;
|
|
||||||
top: 7rem;
|
|
||||||
height: calc(100dvh - 8rem - 6rem);
|
|
||||||
|
|
||||||
nav {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 0.25rem;
|
|
||||||
|
|
||||||
ul {
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 0.25rem;
|
|
||||||
|
|
||||||
li {
|
|
||||||
padding-left: calc((var(--depth) - 1) * 1rem);
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
a {
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 600;
|
|
||||||
|
|
||||||
transform: translate(-0.25rem, 0);
|
|
||||||
|
|
||||||
padding: 0.125rem 0.25rem;
|
|
||||||
border-radius: 0.125rem;
|
|
||||||
|
|
||||||
color: #444;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: #00000018;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 1400px) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
|
||||||
grid-column: 1 / -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
justify-self: center;
|
|
||||||
|
|
||||||
@media screen and (min-width: $screen-desktop-min) {
|
|
||||||
padding: 3rem 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pre[data-language='astro'] {
|
|
||||||
--code-bg: #fff7ef;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
max-width: 46rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
margin: 2rem auto;
|
|
||||||
|
|
||||||
border: 2px dashed #ddd;
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
|
|
||||||
&.large {
|
|
||||||
min-width: calc(100% - 4rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(.large) {
|
|
||||||
& > .content {
|
|
||||||
display: grid;
|
|
||||||
place-content: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .content {
|
|
||||||
padding: 2rem;
|
|
||||||
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
// label in the top left corner
|
|
||||||
&::before {
|
|
||||||
content: 'Preview';
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
bottom: 100%;
|
|
||||||
left: 0;
|
|
||||||
|
|
||||||
padding: 0.125rem 0.5rem;
|
|
||||||
|
|
||||||
background: #eee;
|
|
||||||
color: #000;
|
|
||||||
|
|
||||||
font-family: var(--font-display);
|
|
||||||
font-size: 14px;
|
|
||||||
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
|
|
||||||
z-index: -1;
|
|
||||||
|
|
||||||
transform: translate(-2px, -4px);
|
|
||||||
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 64ms ease-in;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-color: #bbb;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.palette {
|
|
||||||
margin: 2rem auto;
|
|
||||||
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: auto auto;
|
|
||||||
|
|
||||||
gap: 1rem;
|
|
||||||
|
|
||||||
place-content: center;
|
|
||||||
|
|
||||||
& > .color {
|
|
||||||
width: 2rem;
|
|
||||||
height: 2rem;
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
|
|
||||||
border: 2px solid #000;
|
|
||||||
box-shadow: 4px 4px 0 0 #000;
|
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
& > .region {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
border: 2px solid #fff;
|
|
||||||
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .label {
|
|
||||||
display: grid;
|
|
||||||
align-content: center;
|
|
||||||
|
|
||||||
font-family: 'JetBrains Mono', var(--font-mono);
|
|
||||||
font-size: 16px;
|
|
||||||
|
|
||||||
user-select: all;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
@layer page {
|
||||||
|
main {
|
||||||
|
background: #e8e8e8;
|
||||||
|
|
||||||
|
justify-self: center;
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
grid-auto-flow: row;
|
||||||
|
|
||||||
|
justify-items: center;
|
||||||
|
|
||||||
|
padding: 3rem;
|
||||||
|
|
||||||
|
gap: 3rem;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
width: 100%;
|
||||||
|
height: 80vh;
|
||||||
|
|
||||||
|
background: linear-gradient(to bottom, transparent, #e8e8e8);
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search {
|
||||||
|
max-width: 80ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.appunti-scrollable {
|
||||||
|
justify-self: stretch;
|
||||||
|
|
||||||
|
&.center {
|
||||||
|
justify-self: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1024px) {
|
||||||
|
padding: 3rem 1rem;
|
||||||
|
gap: 3rem;
|
||||||
|
|
||||||
|
overflow: clip;
|
||||||
|
|
||||||
|
.card {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
:root {
|
||||||
|
--card-base: hsl(180, 100%, 85%);
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer page {
|
||||||
|
body {
|
||||||
|
background: hsl(180, 100%, 95%);
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
justify-self: center;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
padding: 4rem 0;
|
||||||
|
|
||||||
|
gap: 2rem;
|
||||||
|
|
||||||
|
.search {
|
||||||
|
max-width: 80ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background: hsl(180, 100%, 72%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card a {
|
||||||
|
color: color-mix(in srgb, var(--card-base-internal), #000 80%);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1024px) {
|
||||||
|
padding: 3rem 1rem;
|
||||||
|
gap: 3rem;
|
||||||
|
|
||||||
|
.card {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
@layer page {
|
||||||
|
body {
|
||||||
|
--card-base: color-mix(in lab, var(--guide-base), #fff 25%);
|
||||||
|
--zone-color: color-mix(in lab, var(--guide-base), #000 75%);
|
||||||
|
background: color-mix(in lab, var(--guide-base), #fff 90%);
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
--card-base: color-mix(in lab, var(--guide-base), #fff 50%);
|
||||||
|
|
||||||
|
max-width: calc(46rem + 2rem * 2);
|
||||||
|
justify-self: center;
|
||||||
|
padding: 3rem 2rem 2rem;
|
||||||
|
|
||||||
|
margin-top: 3rem;
|
||||||
|
margin-bottom: 6rem;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.metadata {
|
||||||
|
position: absolute;
|
||||||
|
top: -2px;
|
||||||
|
left: calc(100% + 2rem);
|
||||||
|
width: 15rem;
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
grid-auto-flow: row;
|
||||||
|
gap: 1rem;
|
||||||
|
|
||||||
|
justify-items: start;
|
||||||
|
|
||||||
|
.metadata-item {
|
||||||
|
background: var(--card-base);
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: auto auto;
|
||||||
|
justify-items: start;
|
||||||
|
gap: 0.25rem;
|
||||||
|
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
|
||||||
|
/* @include neo-brutalist-card($size: 3px); */
|
||||||
|
border: 3px solid #222;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 3px 3px 0 0 #222;
|
||||||
|
|
||||||
|
.tags {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1024px) {
|
||||||
|
box-shadow: none;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
max-width: none;
|
||||||
|
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 3rem 1rem 2rem;
|
||||||
|
|
||||||
|
.metadata {
|
||||||
|
position: static;
|
||||||
|
padding: 0;
|
||||||
|
width: auto;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
--card-base: color-mix(in lab, var(--guide-base), #fff 30%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
@layer page {
|
||||||
|
body {
|
||||||
|
--card-base: color-mix(in lab, var(--guide-base), #fff 25%);
|
||||||
|
--zone-color: color-mix(in lab, var(--guide-base), #000 75%);
|
||||||
|
background: color-mix(in lab, var(--guide-base), #fff 90%);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 > a {
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline 3px solid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
justify-self: center;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
padding: 5rem 2.5rem;
|
||||||
|
gap: 5rem;
|
||||||
|
|
||||||
|
@media screen and (max-width: 1024px) {
|
||||||
|
padding: 3rem 1rem;
|
||||||
|
gap: 3rem;
|
||||||
|
|
||||||
|
.card {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
grid-template-rows: auto 1fr auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,354 @@
|
|||||||
|
@layer page {
|
||||||
|
header:has(#header-menu-toggle:not(:checked)) .logo {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
min-height: calc(100vh - 6rem);
|
||||||
|
|
||||||
|
&:last-of-type {
|
||||||
|
min-height: calc(100vh - 10rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center; */
|
||||||
|
|
||||||
|
& {
|
||||||
|
display: grid;
|
||||||
|
grid-auto-flow: row;
|
||||||
|
justify-items: center;
|
||||||
|
align-content: start;
|
||||||
|
|
||||||
|
gap: 2rem;
|
||||||
|
|
||||||
|
scroll-snap-align: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > .title {
|
||||||
|
font-size: 48px;
|
||||||
|
padding-top: 4rem;
|
||||||
|
|
||||||
|
@media screen and (max-width: /* $screen-desktop-min */ 1024px) {
|
||||||
|
padding-top: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.zig-zag {
|
||||||
|
z-index: 5;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
bottom: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
section.principal {
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
|
min-height: calc(100vh - 7rem);
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
place-content: center;
|
||||||
|
|
||||||
|
gap: 4rem;
|
||||||
|
|
||||||
|
padding: 3rem 2rem 6rem;
|
||||||
|
|
||||||
|
background: var(--homepage-principal-bg);
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.circuit-layer {
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
z-index: 1;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& > .logo {
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
|
width: 32rem;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
/* filter: drop-shadow(6px 6px 0 var(--palette-black))
|
||||||
|
drop-shadow(4px 0 0 var(--palette-black)) drop-shadow(0 4px 0 var(--palette-black))
|
||||||
|
drop-shadow(-4px 0 0 var(--palette-black)) drop-shadow(0 -4px 0 var(--palette-black)); */
|
||||||
|
}
|
||||||
|
|
||||||
|
max-width: calc(100vw - 3rem);
|
||||||
|
@media screen and (max-width: /* $screen-desktop-min */ 1024px) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& > .whats-phc {
|
||||||
|
z-index: 2;
|
||||||
|
background: #e4c5ff;
|
||||||
|
|
||||||
|
--zone-color: color-mix(in lab, #e4c5ff, #000 75%);
|
||||||
|
|
||||||
|
max-width: 37rem;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: underline 2px solid;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
--zone-color: color-mix(in lab, #e4c5ff, #000 60%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span.highlighted {
|
||||||
|
background: color-mix(in lab, #e4c5ff, #000 10%);
|
||||||
|
cursor: default;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
padding: 0.125rem 0.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
section.news {
|
||||||
|
--card-base: color-mix(in lab, var(--news-base), #fff 25%);
|
||||||
|
--zone-color: color-mix(in lab, var(--news-base), #000 50%);
|
||||||
|
|
||||||
|
background: var(--homepage-news-bg);
|
||||||
|
|
||||||
|
gap: 3rem;
|
||||||
|
|
||||||
|
padding-bottom: 6rem;
|
||||||
|
|
||||||
|
& > .news-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 3rem;
|
||||||
|
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
padding: 0 3rem;
|
||||||
|
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
[role='button'] {
|
||||||
|
padding: 0.5rem 2rem;
|
||||||
|
|
||||||
|
&.primary {
|
||||||
|
background: #ffdd6e;
|
||||||
|
color: #000d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
section.projects {
|
||||||
|
background: var(--homepage-projects-bg);
|
||||||
|
|
||||||
|
padding-bottom: 6rem;
|
||||||
|
|
||||||
|
.project-list {
|
||||||
|
/* width: calc(20rem * 3 + 1.5rem * 2 + 6rem * 2);
|
||||||
|
max-width: calc(100vw - 2rem); */ /* HACK: capire come si propagano le width per bene */
|
||||||
|
|
||||||
|
max-width: calc(20rem * 3 + 1.5rem * 2 + 1rem * 2);
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
|
||||||
|
grid-auto-flow: dense;
|
||||||
|
|
||||||
|
gap: 1.5rem;
|
||||||
|
padding: 0 1rem;
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
grid-row: span var(--masonry-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
.project {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
/* background: #fcddff;
|
||||||
|
background: #ffa89c; */
|
||||||
|
background: var(--card-bg, var(--project-card-bg));
|
||||||
|
color: var(--card-fg, #000e);
|
||||||
|
|
||||||
|
/* @include neo-brutalist-card($size: 3px, $offset: 9px); */
|
||||||
|
border: 3px solid #222;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 9px 9px 0 0 #222;
|
||||||
|
|
||||||
|
padding: 1rem;
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
grid-template-rows: auto 1fr;
|
||||||
|
|
||||||
|
gap: 0.25rem 1rem;
|
||||||
|
|
||||||
|
transition: all 128ms ease-out;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 32px;
|
||||||
|
|
||||||
|
@media screen and (max-width: /* $screen-desktop-min */ 1024px) {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.image {
|
||||||
|
grid-row: span 2;
|
||||||
|
/* place-self: center; */
|
||||||
|
|
||||||
|
.box {
|
||||||
|
background: #0003;
|
||||||
|
border: 3px solid #0006;
|
||||||
|
border-radius: 6px;
|
||||||
|
width: 4rem;
|
||||||
|
height: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
object-fit: cover;
|
||||||
|
width: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* &.auto {
|
||||||
|
img {
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translate(0, -4px);
|
||||||
|
box-shadow: 9px 13px 0 0 #222;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: /* $screen-desktop-min */ 1024px) {
|
||||||
|
padding: 0 1rem;
|
||||||
|
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
|
||||||
|
.project {
|
||||||
|
padding: 0.8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
section.wanna-be-macchinista {
|
||||||
|
background: var(--homepage-macchinisti-bg);
|
||||||
|
color: #fdfdfd;
|
||||||
|
|
||||||
|
padding-bottom: 6rem;
|
||||||
|
|
||||||
|
.card {
|
||||||
|
max-width: 40rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .content {
|
||||||
|
/* @extend .text;
|
||||||
|
/* Placeholder: Assuming .text is a class with common text styles, you might want to define those styles directly here or in a separate CSS rule.
|
||||||
|
} */
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: /* $screen-desktop-min */ 1024px) {
|
||||||
|
main {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.principal {
|
||||||
|
padding: 3rem 0 6rem;
|
||||||
|
|
||||||
|
.whats-phc {
|
||||||
|
padding: 1.5rem;
|
||||||
|
|
||||||
|
margin: 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mobile-whats-phc-read-more {
|
||||||
|
&:checked ~ .text {
|
||||||
|
max-height: 7lh;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 3lh;
|
||||||
|
|
||||||
|
background: linear-gradient(to bottom, transparent, #e4c5ff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:checked) ~ * .button span:nth-child(1) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
&:checked ~ * .button span:nth-child(2) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
section.news {
|
||||||
|
& > .news-list {
|
||||||
|
padding: 0 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
section.projects {
|
||||||
|
.project-list {
|
||||||
|
padding: 0 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
section.wanna-be-macchinista {
|
||||||
|
.content {
|
||||||
|
padding: 0 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
padding: 1rem 1rem 4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
@layer page {
|
||||||
|
main {
|
||||||
|
justify-self: center;
|
||||||
|
background: linear-gradient(to top, #d5fbff, #ffd9d5);
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
padding: 4.5rem 3rem;
|
||||||
|
gap: 4.5rem;
|
||||||
|
|
||||||
|
@media screen and (max-width: 1024px) {
|
||||||
|
padding: 3rem 1rem;
|
||||||
|
gap: 3rem;
|
||||||
|
|
||||||
|
.card {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,190 @@
|
|||||||
|
@layer page {
|
||||||
|
body {
|
||||||
|
grid-template-columns: minmax(15rem, 2fr) 10fr;
|
||||||
|
|
||||||
|
@media screen and (max-width: 1400px) {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aside {
|
||||||
|
margin: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
|
||||||
|
/* @include neo-brutalist-card(); */
|
||||||
|
border: 3px solid #222;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 3px 3px 0 0 #222;
|
||||||
|
|
||||||
|
background: #f0f0f0;
|
||||||
|
|
||||||
|
align-self: start;
|
||||||
|
position: sticky;
|
||||||
|
top: 7rem;
|
||||||
|
height: calc(100dvh - 8rem - 6rem);
|
||||||
|
|
||||||
|
nav {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.25rem;
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.25rem;
|
||||||
|
|
||||||
|
li {
|
||||||
|
padding-left: calc((var(--depth) - 1) * 1rem);
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
|
||||||
|
transform: translate(-0.25rem, 0);
|
||||||
|
|
||||||
|
padding: 0.125rem 0.25rem;
|
||||||
|
border-radius: 0.125rem;
|
||||||
|
|
||||||
|
color: #444;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #00000018;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1400px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
justify-self: center;
|
||||||
|
|
||||||
|
@media screen and (min-width: /* $screen-desktop-min */ 1024px) {
|
||||||
|
padding: 3rem 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[data-language='astro'] {
|
||||||
|
--code-bg: #fff7ef;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
max-width: 46rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
margin: 2rem auto;
|
||||||
|
|
||||||
|
border: 2px dashed #ddd;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
&.large {
|
||||||
|
min-width: calc(100% - 4rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.large) {
|
||||||
|
& > .content {
|
||||||
|
display: grid;
|
||||||
|
place-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& > .content {
|
||||||
|
padding: 2rem;
|
||||||
|
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* label in the top left corner */
|
||||||
|
&::before {
|
||||||
|
content: 'Preview';
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
bottom: 100%;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
padding: 0.125rem 0.5rem;
|
||||||
|
|
||||||
|
background: #eee;
|
||||||
|
color: #000;
|
||||||
|
|
||||||
|
font-family: var(--font-display);
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
|
||||||
|
z-index: -1;
|
||||||
|
|
||||||
|
transform: translate(-2px, -4px);
|
||||||
|
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 64ms ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #bbb;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.palette {
|
||||||
|
margin: 2rem auto;
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto auto;
|
||||||
|
|
||||||
|
gap: 1rem;
|
||||||
|
|
||||||
|
place-content: center;
|
||||||
|
|
||||||
|
& > .color {
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
|
||||||
|
border: 2px solid #000;
|
||||||
|
box-shadow: 4px 4px 0 0 #000;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
& > .region {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
border: 2px solid #fff;
|
||||||
|
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& > .label {
|
||||||
|
display: grid;
|
||||||
|
align-content: center;
|
||||||
|
|
||||||
|
font-family: 'JetBrains Mono', var(--font-mono);
|
||||||
|
font-size: 16px;
|
||||||
|
|
||||||
|
user-select: all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
@layer page {
|
||||||
|
:root {
|
||||||
|
--card-base: color-mix(in lab, var(--news-base), #fff 25%);
|
||||||
|
--zone-color: color-mix(in lab, var(--news-base), #000 75%);
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: color-mix(in lab, var(--news-base), #fff 90%);
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
max-width: calc(46rem + 2rem * 2);
|
||||||
|
justify-self: center;
|
||||||
|
padding: 3rem 2rem 2rem;
|
||||||
|
|
||||||
|
margin-top: 3rem;
|
||||||
|
margin-bottom: 6rem;
|
||||||
|
|
||||||
|
@media screen and (max-width: 1024px) {
|
||||||
|
box-shadow: none;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
max-width: none;
|
||||||
|
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
@layer page {
|
||||||
|
:root {
|
||||||
|
--card-base: color-mix(in lab, var(--news-base), #fff 25%);
|
||||||
|
--zone-color: color-mix(in lab, var(--news-base), #000 75%);
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: color-mix(in lab, var(--news-base), #fff 90%);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 > a {
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline 3px solid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
justify-self: center;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
padding: 5rem;
|
||||||
|
gap: 5rem;
|
||||||
|
|
||||||
|
@media screen and (max-width: 1024px) {
|
||||||
|
padding: 3rem 1rem;
|
||||||
|
gap: 3rem;
|
||||||
|
|
||||||
|
.card {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
grid-template-rows: auto auto 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
:root {
|
||||||
|
--card-base: #e4c5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer page {
|
||||||
|
main {
|
||||||
|
justify-self: center;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
padding: 5rem 0;
|
||||||
|
gap: 3rem;
|
||||||
|
|
||||||
|
/* background horizontal linear gradient that is black in the center */
|
||||||
|
background: linear-gradient(
|
||||||
|
to right,
|
||||||
|
#ffe4c544 0%,
|
||||||
|
/* #ffe4c599 25%, */ #ffe4c5ff 50%,
|
||||||
|
/* #ffe4c599 75%, */ #ffe4c544 100%
|
||||||
|
);
|
||||||
|
|
||||||
|
@media screen and (max-width: 1024px) {
|
||||||
|
padding: 3rem 1rem;
|
||||||
|
gap: 3rem;
|
||||||
|
|
||||||
|
.card {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
:root {
|
||||||
|
--filter-bg-color: #ffd270;
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer page {
|
||||||
|
body {
|
||||||
|
background: #ffffe4;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
justify-self: center;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
padding: 5rem 0;
|
||||||
|
|
||||||
|
gap: 5rem;
|
||||||
|
|
||||||
|
max-width: 80ch;
|
||||||
|
|
||||||
|
.search-result {
|
||||||
|
background: #ffeabc;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background: #ffd270;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1024px) {
|
||||||
|
padding: 3rem 1rem;
|
||||||
|
gap: 3rem;
|
||||||
|
|
||||||
|
.card {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,37 +1,8 @@
|
|||||||
@function pow($number, $exponent) {
|
|
||||||
$value: 1;
|
|
||||||
|
|
||||||
@if $exponent > 0 {
|
|
||||||
@for $i from 1 through $exponent {
|
|
||||||
$value: $value * $number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@return $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin geometric-headings {
|
|
||||||
$base-font-size: 16px;
|
|
||||||
$heading-scale: 1.25;
|
|
||||||
|
|
||||||
@for $i from 1 through 5 {
|
|
||||||
$factor: pow($heading-scale, 5 - $i);
|
|
||||||
|
|
||||||
h#{$i} {
|
|
||||||
font-size: $base-font-size * $factor;
|
|
||||||
font-family: var(--font-display);
|
|
||||||
font-weight: 700;
|
|
||||||
margin-bottom: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
// p + h#{$i} {
|
|
||||||
// margin-top: 0.75rem * $factor;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@layer typography {
|
@layer typography {
|
||||||
@include geometric-headings;
|
:root {
|
||||||
|
--heading-base-size: 16px;
|
||||||
|
--heading-factor: 1.25;
|
||||||
|
}
|
||||||
|
|
||||||
strong {
|
strong {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@@ -45,9 +16,48 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: calc(var(--heading-base-size) * pow(var(--heading-factor), 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: calc(var(--heading-base-size) * pow(var(--heading-factor), 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: calc(var(--heading-base-size) * pow(var(--heading-factor), 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: calc(var(--heading-base-size) * pow(var(--heading-factor), 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
font-size: calc(var(--heading-base-size) * pow(var(--heading-factor), 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5 {
|
||||||
|
font-family: var(--font-display);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
.text {
|
.text {
|
||||||
// text-align: justify;
|
h1,
|
||||||
// hyphens: auto;
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5 {
|
||||||
|
font-family: var(--font-display);
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* text-align: justify;
|
||||||
|
hyphens: auto; */
|
||||||
|
|
||||||
&.center {
|
&.center {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -64,8 +74,8 @@
|
|||||||
pre,
|
pre,
|
||||||
code {
|
code {
|
||||||
background: color-mix(in lab, var(--card-base-internal, #ededed), #fff 35%) !important;
|
background: color-mix(in lab, var(--card-base-internal, #ededed), #fff 35%) !important;
|
||||||
// background: color-mix(in lab, var(--zone-color), #fff 75%) !important;
|
/* background: color-mix(in lab, var(--zone-color), #fff 75%) !important;
|
||||||
// background: var(--code-bg, #00000022) !important;
|
background: var(--code-bg, #00000022) !important; */
|
||||||
|
|
||||||
font-family: var(--font-mono);
|
font-family: var(--font-mono);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
@@ -77,12 +87,16 @@
|
|||||||
padding: 0.125rem 0.3rem;
|
padding: 0.125rem 0.3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p > code {
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
margin: 2rem auto;
|
margin: 2rem auto;
|
||||||
|
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
|
|
||||||
// width: 100%;
|
/* width: 100%; */
|
||||||
max-width: 80ch;
|
max-width: 80ch;
|
||||||
|
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
@@ -97,11 +111,6 @@
|
|||||||
code {
|
code {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
|
||||||
width: calc(100vw - 2rem);
|
|
||||||
max-width: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
@@ -109,26 +118,26 @@
|
|||||||
margin: var(--paragraph-margin, 1rem) auto;
|
margin: var(--paragraph-margin, 1rem) auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
// p + p {
|
/* p + p {
|
||||||
// margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// h1 + p,
|
h1 + p,
|
||||||
// h2 + p,
|
h2 + p,
|
||||||
// h3 + p,
|
h3 + p,
|
||||||
// h4 + p {
|
h4 + p {
|
||||||
// margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// p:has(+ h1, + h2, + h3, + h4) {
|
p:has(+ h1, + h2, + h3, + h4) {
|
||||||
// margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
// }
|
} */
|
||||||
|
|
||||||
p[align='center'] {
|
p[align='center'] {
|
||||||
margin: 1.5rem 0;
|
margin: 1.5rem 0;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
// background: color-mix(in hsl, var(--card-base-internal, #ededed), #fff 20%);
|
/* background: color-mix(in hsl, var(--card-base-internal, #ededed), #fff 20%); */
|
||||||
background: hsl(from var(--card-base-internal, #ededed) h calc(s + 10) calc(l - 10));
|
background: hsl(from var(--card-base-internal, #ededed) h calc(s + 10) calc(l - 10));
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
@@ -144,7 +153,10 @@
|
|||||||
width: 50ch;
|
width: 50ch;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
|
||||||
@include neo-brutalist-card(2px);
|
border: 2px solid #333;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
box-shadow: 0.25rem 0.25rem 0 0 #333;
|
||||||
|
/* background: color-mix(in lab, var(--card-base-internal, #ededed), #fff 20%); */
|
||||||
|
|
||||||
&.fill {
|
&.fill {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -177,7 +189,22 @@
|
|||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include geometric-headings;
|
/* @include geometric-headings; */
|
||||||
|
/* Inlined geometric-headings mixin */
|
||||||
|
/* @for $i from 1 through 5 {
|
||||||
|
$factor: pow($heading-scale, 5 - $i);
|
||||||
|
|
||||||
|
h#{$i} {
|
||||||
|
font-size: $base-font-size * $factor;
|
||||||
|
font-family: var(--font-display);
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* p + h#{$i} {
|
||||||
|
margin-top: 0.75rem * $factor;
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
@@ -191,7 +218,7 @@
|
|||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #333;
|
color: #333;
|
||||||
|
|
||||||
// HACK: Trick to fix anchor links with sticky header
|
/* HACK: Trick to fix anchor links with sticky header */
|
||||||
padding-top: 7rem;
|
padding-top: 7rem;
|
||||||
margin-top: -6.5rem;
|
margin-top: -6.5rem;
|
||||||
}
|
}
|
||||||
@@ -250,9 +277,17 @@
|
|||||||
border-top: 2px solid #0003;
|
border-top: 2px solid #0003;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: $screen-desktop-min) {
|
@media screen and (max-width: 1024px) {
|
||||||
& > * {
|
max-width: calc(100vw - 2rem);
|
||||||
margin: 0 0.75rem;
|
|
||||||
|
pre {
|
||||||
|
margin: 1rem 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
max-width: none;
|
||||||
|
margin: 3rem auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user