/* =========================================================
   giannivitale.com – styles
   Mobile-first: base styles are for phones, then
   @media (min-width: ...) blocks add tablet/desktop layout.
   Every colour, font size, weight, line height, spacing,
   radius and shadow is a design token in :root below –
   change it once here and it updates everywhere.
   ========================================================= */

/* ---------- Fonts (self-hosted) ---------- */
@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 400 700;
  font-display: optional; /* preloaded on every page; if it is late, the matched fallback stays for that view: no swap, CLS 0 */
  src: url("../fonts/montserrat-latin.woff2") format("woff2");
}
/* Arial resized to Montserrat's metrics, so text doesn't reflow (CLS) when the web font arrives */
@font-face {
  font-family: "Montserrat Fallback";
  src: local("Arial"), local("ArialMT"), local("Arimo"), local("Liberation Sans"), local("Helvetica"), local("Roboto");
  size-adjust: 113.39%;
  ascent-override: 85.79%;
  descent-override: 22.25%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Lora";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/lora-400-latin.woff2") format("woff2");
}

/* ---------- Design tokens ---------- */
:root {
  /* Colour – brand palette (navy / light blue / cream) */
  --color-navy: #2b5385;        /* main brand blue (buttons, links) – 7.8:1 on white */
  --color-navy-dark: #1d3a5f;   /* hover, active, text on light-blue panels – 11.5:1 on white */
  --color-sky: #9cc6e7;         /* light blue accent (reserved, not used yet) */
  --color-sky-pale: #e3f0fa;    /* form, skills and hover panels */
  --color-cream: #f8f9f1;       /* cream section + footer background */
  --color-white: #ffffff;

  /* Colour – text */
  --color-text: #323232;        /* body text – 12.8:1 on white */
  --color-text-muted: #4a5563;  /* secondary text – 6.5:1 even on sky-pale */
  --color-text-strong: #000000; /* emphasised words in the hero */
  --color-ink: #1f2d3d;         /* form labels – 12.1:1 on sky-pale */
  --color-placeholder: #5f6b7a; /* input placeholder – 5.4:1 on white */
  --color-error: #b3261e;       /* validation errors – 5.6:1 on sky-pale */

  /* Colour – UI */
  --color-border: #e6e9ee;      /* hairline dividers and card borders (decorative) */
  --color-border-input: #6a86a3;/* form field outline – 3.3:1 on sky-pale (WCAG 1.4.11) */
  --color-focus: #ad6d0b;       /* keyboard focus ring (amber) – ≥3.6:1 on white, cream, sky-pale */
  --color-surface-header: rgba(255, 255, 255, .96);
  --color-surface-glass: rgba(255, 255, 255, .85);
  --color-bg: #ffffff;          /* page background */
  --color-surface: #ffffff;     /* cards, inputs, menus */
  --color-accent: #2b5385;      /* filled buttons, stats bar, skip link */
  --color-accent-hover: #1d3a5f;
  --color-on-accent: #ffffff;   /* text on --color-accent – 7.8:1 */
  --color-divider: #cfd6df;
  --color-success: #23804a;     /* availability dot */
  --color-whatsapp: #128c7e;    /* WhatsApp glyph only (never text) – 3.6:1 on sky-pale */
  --wave-image: url("../images/wave-background-960.webp");

  /* Typography – families and weights */
  --font-sans: "Montserrat", "Montserrat Fallback", system-ui, -apple-system, "Segoe UI", Arial, sans-serif;
  --font-serif: "Lora", Georgia, serif;
  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;

  /* Typography – type scale (rem, 1rem = 16px) */
  --fs-xs: .8rem;                         /* 12.8px  skill chips */
  --fs-sm: .875rem;                       /* 14px    small print, tags, errors */
  --fs-base: 1rem;                        /* 16px    body, buttons, inputs, labels */
  --fs-md: 1.125rem;                      /* 18px    hero lead, mobile menu */
  --fs-lg: 1.25rem;                       /* 20px    h3 */
  --fs-stat: 2.25rem;                     /* 36px    bio stats figures */
  --fs-h2: clamp(1.9rem, 5vw, 2.6rem);    /* 30.4 → 41.6px fluid */
  --fs-h1: clamp(2.4rem, 8vw, 4rem);      /* 38.4 → 64px fluid */

  /* Typography – line heights */
  --lh-tight: 1.1;
  --lh-snug: 1.2;
  --lh-normal: 1.4;
  --lh-body: 1.65;

  /* Spacing – 4px grid (number = multiples of 4px) */
  --space-1: .25rem;    /*  4px */
  --space-1-5: .375rem; /*  6px */
  --space-2: .5rem;     /*  8px */
  --space-2-5: .625rem; /* 10px */
  --space-3: .75rem;    /* 12px */
  --space-4: 1rem;      /* 16px */
  --space-5: 1.25rem;   /* 20px */
  --space-6: 1.5rem;    /* 24px */
  --space-7: 1.75rem;   /* 28px */
  --space-8: 2rem;      /* 32px */
  --space-10: 2.5rem;   /* 40px */
  --space-12: 3rem;     /* 48px */
  --space-14: 3.5rem;   /* 56px */
  --space-16: 4rem;     /* 64px */
  --space-18: 4.5rem;   /* 72px */
  --space-22: 5.5rem;   /* 88px */
  /* Fluid section rhythm (Gianni, 3 Nov 2026: less scrolling on phones/tablets) */
  --section-pad: clamp(3rem, 1rem + 4.5vw, 5.5rem);   /* 48px @390 → 51 @768 → 62 @1024 → 81 @1440 */
  --hero-pad-top: clamp(2rem, 1rem + 3vw, 3.5rem);
  --hero-pad-bottom: clamp(2.5rem, 1rem + 4vw, 4.5rem);
  --col-gap: clamp(2rem, 1rem + 3vw, 4rem);

  /* Radius */
  --radius-xs: 2px;     /* hamburger bars */
  --radius-sm: 8px;     /* focus ring, skip link, nav links */
  --radius-md: 12px;    /* inputs, thumbnails, menu button */
  --radius-lg: 16px;    /* buttons, cards, stats, skill chips */
  --radius-xl: 24px;    /* photos and large panels */
  --radius-round: 50%;

  /* Shadow */
  --shadow-md: 0 12px 24px rgba(0, 0, 0, .08);

  /* Layout */
  --container: 1120px;
  --header-h: 72px;
  --tap-target: 48px;
  --border-thin: 1px;
  --border-thick: 2px;
  --focus-ring: 3px;
}

/* ---------- Reset / base ---------- */
*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-padding-top: calc(var(--header-h) + var(--space-2)); }

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  color: var(--color-text);
  background: var(--color-bg);
}

img { max-width: 100%; height: auto; display: block; }
picture { display: block; }

h1, h2, h3 { line-height: var(--lh-snug); margin: 0 0 .6em; color: var(--color-text); font-weight: var(--fw-bold); }
h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-lg); }
p  { margin: 0 0 1em; }
ul { margin: 0; padding: 0; list-style: none; }
figure { margin: 0; }

a { color: var(--color-navy); text-underline-offset: 3px; }
a:hover { color: var(--color-navy-dark); }

/* Visible keyboard focus everywhere */
:focus-visible {
  outline: var(--focus-ring) solid var(--color-focus);
  outline-offset: var(--focus-ring);
  border-radius: var(--radius-sm);
}

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}

.sprite { display: none; }

.skip-link {
  position: absolute; left: var(--space-4); top: -100px; z-index: 100;
  background: var(--color-accent); color: var(--color-on-accent);
  padding: var(--space-2-5) var(--space-4); border-radius: var(--radius-sm); font-weight: var(--fw-semibold);
}
.skip-link:focus { top: var(--space-4); color: var(--color-on-accent); }

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--space-5);
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--tap-target);
  padding: var(--space-3) var(--space-6);
  border: var(--border-thick) solid var(--color-accent);
  border-radius: var(--radius-lg);
  background: var(--color-accent);
  color: var(--color-on-accent);
  font: var(--fw-medium) var(--fs-base)/var(--lh-snug) var(--font-sans);
  letter-spacing: .04em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
}
.btn:hover { background: var(--color-accent-hover); border-color: var(--color-accent-hover); color: var(--color-on-accent); }
.btn--wide { width: 100%; }

@media (prefers-reduced-motion: no-preference) {
  .btn { transition: background-color .2s ease, border-color .2s ease, transform .2s ease; }
  .btn:hover { transform: translateY(-2px); }
}

/* ---------- Header + navigation ---------- */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: var(--color-surface-header);
  border-bottom: var(--border-thin) solid var(--color-border);
}
.header-inner {
  display: flex; align-items: center; justify-content: space-between;
  height: var(--header-h);
  position: relative;
}
.brand { margin-inline-end: auto; }
.brand img { width: 56px; height: 56px; }

.nav-toggle {
  display: none; /* shown only when JS is available (below) */
  width: var(--tap-target); height: var(--tap-target);
  border: 0; border-radius: var(--radius-md);
  background: transparent; cursor: pointer;
  align-items: center; justify-content: center;
}
.nav-toggle-bar,
.nav-toggle-bar::before,
.nav-toggle-bar::after {
  display: block; width: 26px; height: 3px;
  background: var(--color-navy); border-radius: var(--radius-xs);
  position: relative; content: "";
}
.nav-toggle-bar::before { position: absolute; top: calc(-1 * var(--space-2)); }
.nav-toggle-bar::after  { position: absolute; top: var(--space-2); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar { background: transparent; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar::before { top: 0; transform: rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar::after  { top: 0; transform: rotate(-45deg); }

.site-nav { display: flex; align-items: center; gap: var(--space-2); }
.site-nav ul { display: flex; gap: var(--space-1); flex-wrap: wrap; }
.site-nav a {
  display: block; padding: var(--space-2-5) var(--space-3);
  color: var(--color-text); font-weight: var(--fw-semibold); text-decoration: none; border-radius: var(--radius-sm);
}
.site-nav a:hover { color: var(--color-navy); background: var(--color-sky-pale); }

/* Mobile menu (phones, JS on): a dropdown panel that overlays the page,
   so opening it never shifts the layout. */
@media (max-width: 767px) {
  .js .nav-toggle { display: inline-flex; }
  .js .site-nav {
    position: absolute; top: 100%; left: 0; right: 0;
    background: var(--color-surface);
    border-bottom: var(--border-thin) solid var(--color-border);
    box-shadow: var(--shadow-md);
    display: none;
  }
  .js .site-nav.is-open { display: block; }
  .js .site-nav ul { flex-direction: column; padding: var(--space-2) var(--space-5) var(--space-4); }
  .js .site-nav a { padding: var(--space-3) var(--space-2); font-size: var(--fs-md); }
  /* without JS the links simply sit in the header row */
  .site-nav a { padding: var(--space-2) var(--space-1-5); font-size: var(--fs-sm); }
  html:not(.js) .site-header { position: static; } /* no-JS phones: links wrap, so don't pin a tall header */
  html:not(.js) .header-inner { height: auto; min-height: var(--header-h); flex-wrap: wrap; padding-block: var(--space-2); }
  html:not(.js) .site-nav { flex-wrap: wrap; gap: 0; }
}

/* ---------- Header icon buttons: language globe + theme (Gianni, 3 Nov 2026) ----------
   Desktop: Bio · Portfolio · Skills · Contacts, then a small globe (opens the
   EN/IT/ES dropdown, js/main.js §1c), then a round theme button (§1b).
   Both are 32px circles (hit area >= 24px) in the site's blues; no chevron.
   Phones: the languages are a row inside the burger menu, led by the same
   globe; the theme button sits next to the burger. No JS: a plain row of language codes. */
.lang-menu { position: relative;
  --globe-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M3 12h18'/%3E%3Cpath d='M12 3c2.5 2.6 3.8 5.6 3.8 9s-1.3 6.4-3.8 9c-2.5-2.6-3.8-5.6-3.8-9S9.5 5.6 12 3z'/%3E%3C/svg%3E"); }
.lang-menu-btn { display: none; } /* without JS the plain list below is shown instead */
.js .lang-menu-btn,
.js .theme-toggle {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 32px; height: 32px; padding: 0;
  border: 0; border-radius: 50%;
  background: var(--color-sky-pale); color: var(--color-navy);
  cursor: pointer;
}
.js .lang-menu-btn:hover,
.js .lang-menu-btn[aria-expanded="true"],
.js .theme-toggle:hover { box-shadow: inset 0 0 0 1.5px var(--color-navy); }
.lang-menu-btn svg,
.theme-icon { width: 18px; height: 18px; flex: none; }

/* the list of languages */
.site-nav .lang-menu-list { gap: 0; align-items: center; flex-wrap: nowrap; }
.site-nav .lang-menu-list a { padding-inline: var(--space-2); font-size: var(--fs-sm); }
.site-nav .lang-menu-list a[aria-current] { color: var(--color-navy); }
.lang-menu-code { font-weight: var(--fw-semibold); letter-spacing: .04em; min-width: 2ch; }

@media (min-width: 768px) {
  .js .site-nav .lang-menu-list {
    display: none;
    position: absolute; top: calc(100% + var(--space-1-5)); right: 0; z-index: 60;
    flex-direction: column; align-items: stretch;
    min-width: 11rem; padding: var(--space-1-5);
    background: var(--color-surface);
    border: 1px solid var(--color-border); border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
  }
  .js .lang-menu.is-open .lang-menu-list { display: flex; }
  .js .site-nav .lang-menu-list a {
    display: flex; gap: var(--space-3); align-items: center;
    padding: var(--space-2-5) var(--space-3); font-size: var(--fs-sm);
  }
  .js .site-nav .lang-menu-list a[aria-current]::after { content: "✓"; content: "✓" / ""; margin-inline-start: auto; }
  .lang-menu-name { font-weight: 400; }
}

/* phones (inside the burger menu): no dropdown, just a row of languages */
@media (max-width: 767px) {
  .js .lang-menu-btn { display: none; }
  .js .site-nav .lang-menu-list {
    display: flex; flex-direction: row; flex-wrap: wrap; flex: 1 1 auto; min-width: 0; padding: 0;
  }
  /* the same small blue globe as on desktop, as a label at the start of the row
     (decorative: a pale circle + the globe drawn with a CSS mask, colours follow the theme) */
  .js .site-nav .lang-menu {
    display: flex; align-items: center;
    padding: var(--space-2) var(--space-3) var(--space-4) calc(var(--space-5) + 32px);
    border-top: var(--border-thin) solid var(--color-border);
  }
  .js .site-nav .lang-menu::before,
  .js .site-nav .lang-menu::after {
    content: ""; position: absolute; left: var(--space-5); top: 50%;
    width: 32px; height: 32px; margin-top: calc((var(--space-2) - var(--space-4)) / 2 - 16px);
  }
  .js .site-nav .lang-menu::before { border-radius: 50%; background: var(--color-sky-pale); }
  .js .site-nav .lang-menu::after {
    background: var(--color-navy);
    -webkit-mask: var(--globe-mask) center / 18px 18px no-repeat;
            mask: var(--globe-mask) center / 18px 18px no-repeat;
  }
  .js .site-nav .lang-menu-list a { padding: var(--space-3) var(--space-2-5); font-size: var(--fs-md); }
  .lang-menu-code { display: none; }
}
/* no JS: the links sit in the header row, codes only */
html:not(.js) .lang-menu-name { display: none; }

/* ---------- Hero ---------- */
.hero { padding: var(--hero-pad-top) 0 var(--hero-pad-bottom); }
.hero-inner { display: grid; gap: var(--space-8); }
.hero-lead { font-size: var(--fs-md); max-width: 32ch; }
.hero-lead strong { color: var(--color-text-strong); }
/* "Available for freelance work" badge (H) */
.availability {
  display: inline-flex; align-items: center; gap: var(--space-2);
  margin: 0 0 var(--space-6); padding: var(--space-1-5) var(--space-4);
  font-size: var(--fs-sm); font-weight: var(--fw-semibold); line-height: var(--lh-snug);
  color: var(--color-navy-dark); background: var(--color-sky-pale);
  border: var(--border-thin) solid var(--color-border-input); border-radius: 999px;
}
.availability::before {
  content: ""; flex: none; width: 10px; height: 10px; border-radius: var(--radius-round);
  background: var(--color-success); box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-success) 25%, transparent);
}
.hero-buttons { display: grid; gap: var(--space-4); margin-top: var(--space-7); }
.hero-buttons .btn { width: 100%; }
/* phones ≥360px: the four buttons as a 2×2 grid (same 48px tap height, half the stack) */
@media (min-width: 360px) and (max-width: 899.98px) {
  .hero-buttons { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
  .hero-buttons .btn { padding-inline: var(--space-3); }
}
.hero-media img {
  width: 100%; max-width: 420px; margin-inline: auto;
  border-radius: var(--radius-xl);
}

/* ---------- Social icons ---------- */
.social { display: flex; gap: var(--space-2); justify-content: center; }
.social a {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--tap-target); height: var(--tap-target); border-radius: var(--radius-round);
  color: var(--color-navy);
}
.social a:hover { background: var(--color-sky-pale); color: var(--color-navy-dark); }
.icon { width: 24px; height: 24px; fill: currentColor; }
.social--hero { justify-content: space-around; }

/* ---------- Contacts: direct email (replaces the social icons, which stay in the footer) ---------- */
.contact-direct { margin-top: var(--space-6); color: var(--color-text-muted); }
.contact-email { margin-top: var(--space-3); }
.contact-email a {
  display: inline-flex; align-items: center; gap: var(--space-2-5);
  min-height: var(--tap-target); padding: var(--space-2) var(--space-5);
  font-size: var(--fs-md); font-weight: var(--fw-semibold); line-height: var(--lh-snug);
  color: var(--color-navy-dark); background: var(--color-sky-pale);
  border: var(--border-thin) solid var(--color-border-input); border-radius: 999px;
  text-decoration: none; overflow-wrap: anywhere;
  transition: background-color .15s ease, color .15s ease;
}
/* no underline at rest: the pill shape, border and icon already mark it as a link (it is not inline in text) */
.contact-email a span { text-decoration: underline 2px transparent; text-underline-offset: 4px; transition: text-decoration-color .15s ease; }
.contact-email a:hover,
.contact-email a:focus-visible { color: var(--color-on-accent); background: var(--color-accent); border-color: var(--color-accent); }
/* non-colour cue on hover and keyboard focus: the underline appears */
.contact-email a:hover span,
.contact-email a:focus-visible span { text-decoration-color: currentColor; }
/* keyboard focus: the site's amber ring (3px, offset 3px) */
.contact-email a:focus-visible { outline: var(--focus-ring) solid var(--color-focus); outline-offset: var(--focus-ring); }
.contact-email-icon { flex: none; width: 22px; height: 22px; }
/* email + WhatsApp: stacked, equal width (the text column is too narrow for two pills side by side);
   full-width on phones for big tap targets */
.contact-actions { display: inline-grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-3); margin-top: var(--space-3); max-width: 100%; }
.contact-actions .contact-email { margin: 0; }
.contact-actions .contact-email a { display: flex; width: 100%; justify-content: center; }
.contact-wa-icon { width: 20px; height: 20px; color: var(--color-whatsapp); transition: color .15s ease; }
.contact-whatsapp a:hover .contact-wa-icon,
.contact-whatsapp a:focus-visible .contact-wa-icon { color: currentColor; }
@media (max-width: 599px) { .contact-actions { display: grid; } }
@media (prefers-reduced-motion: reduce) { .contact-email a, .contact-email a span, .contact-wa-icon { transition: none; } }

/* ---------- Sections ---------- */
.section { padding: var(--section-pad) 0; }
.section--tint { background: var(--color-cream); }
.section-lead { max-width: 60ch; color: var(--color-text-muted); }
.two-col { display: grid; gap: var(--col-gap); align-items: center; }
.prose p { max-width: 60ch; }

/* Bio card with stats (compact, Gianni 3 Nov 2026).
   The text comes first in the DOM and on screen at every width.
   Phones: a short row under the text, square illustration + stats panel side by side.
   ≥768px: square illustration beside the text, stats bar over its dark bottom wave. */
.bio-card {
  position: relative; width: 100%; max-width: 480px; margin-inline: auto;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); align-items: center;
}
.bio-card img { border-radius: var(--radius-xl); width: 100%; height: auto; aspect-ratio: 1; object-fit: cover; }
.stats {
  display: flex; flex-direction: column; justify-content: center; gap: var(--space-3); margin: 0;
  height: 100%; padding: var(--space-3) var(--space-4);
  background: var(--color-accent); color: var(--color-on-accent);
  border-radius: var(--radius-xl);
}
.stats div { display: flex; flex-direction: column-reverse; }
.stats dt { font-size: var(--fs-sm); line-height: var(--lh-snug); }
.stats dd { margin: 0; font: var(--fw-regular) var(--fs-stat)/var(--lh-tight) var(--font-serif); }
@media (min-width: 768px) {
  .bio-card { display: block; max-width: 400px; }
  .stats {
    position: absolute; left: var(--space-4); right: var(--space-4); bottom: var(--space-4);
    height: auto; flex-direction: row; justify-content: flex-start; gap: var(--space-4) var(--space-6); flex-wrap: wrap;
    padding: var(--space-4) var(--space-5); border-radius: var(--radius-lg);
  }
}
/* tablets 768–899px: Bio side by side (text column + a narrower square) instead of one long column */
@media (min-width: 768px) and (max-width: 899.98px) {
  #bio .two-col { grid-template-columns: minmax(0, 1fr) clamp(240px, 36vw, 320px); }
  /* the square is too narrow for the stats bar on top: it sits just below instead */
  #bio .stats { position: static; flex-wrap: nowrap; margin-top: var(--space-3); padding: var(--space-3) var(--space-4); gap: var(--space-4); border-radius: var(--radius-lg); }
  #bio .stats div { flex: 1 1 0; }
  #bio .stats dd { font-size: 1.875rem; }
}

/* Portfolio */
.projects { display: grid; gap: var(--space-6); margin-top: var(--space-8); }
.project-card {
  background: var(--color-surface);
  border: var(--border-thin) solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  display: flex; flex-direction: column;
}
.project-card p { color: var(--color-text-muted); }
.project-thumb {
  aspect-ratio: 16 / 10;
  display: grid; place-items: center;
  margin-bottom: var(--space-4);
  border-radius: var(--radius-md);
  background: var(--color-sky-pale) var(--wave-image) center / cover no-repeat;
  color: var(--color-navy-dark); font-weight: var(--fw-semibold);
}
.project-card--placeholder { border-style: dashed; border-color: var(--color-navy); }
.project-tags { font-size: var(--fs-sm); font-weight: var(--fw-semibold); margin: 0; }
.project-shot {
  display: block; width: 100%; height: auto;
  aspect-ratio: 16 / 10; object-fit: cover; object-position: top center;
  margin-bottom: var(--space-4);
  border: var(--border-thin) solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-sky-pale);
}
/* Links pinned to the bottom of each card (12px minimum gap above them) */
.project-links { margin-top: auto; padding-top: var(--space-3); }

/* Skills */
.skills-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-4);
  padding: var(--space-5);
  border-radius: var(--radius-xl);
  background: var(--color-sky-pale) var(--wave-image) center bottom / cover no-repeat;
}
.skills-grid li {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-1-5);
  text-align: center;
  font-size: var(--fs-xs); font-weight: var(--fw-semibold); line-height: var(--lh-snug);
  color: var(--color-navy-dark);
  background: var(--color-surface-glass);
  border-radius: var(--radius-lg); padding: var(--space-2-5) var(--space-1);
}
.skills-grid img { width: 64px; height: 64px; border-radius: var(--radius-round); }
#skills .btn { margin-top: var(--space-2); }

/* Contact form */
/* The fields sit on a solid sky-pale panel; the wave artwork only shows in
   the bottom band behind the Send button (--form-wave-band), fading in
   below the textarea. Pure background change: no size or layout impact. */
.contact-form {
  --form-wave-band: 7.75rem; /* bottom padding + status line + button + gaps */
  background:
    linear-gradient(to bottom,
      var(--color-sky-pale) calc(100% - var(--form-wave-band)),
      transparent calc(100% - var(--form-wave-band) + var(--space-8))),
    var(--wave-image) center bottom / 100% auto no-repeat,
    var(--color-sky-pale);
  border-radius: var(--radius-xl);
  padding: var(--space-6);
  display: grid; gap: var(--space-4);
}
.form-note { font-size: var(--fs-sm); color: var(--color-text-muted); margin: 0; }
.field-row { display: grid; gap: var(--space-4); }
.field { display: grid; gap: var(--space-1-5); }
.field label { font-weight: var(--fw-semibold); font-size: var(--fs-base); color: var(--color-ink); }
.field input,
.field textarea {
  width: 100%;
  font: var(--fw-regular) var(--fs-base)/var(--lh-normal) var(--font-sans);
  color: var(--color-text);
  background: var(--color-surface);
  border: var(--border-thick) solid var(--color-border-input);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
}
.field textarea { resize: vertical; min-height: 140px; }
.field input::placeholder,
.field textarea::placeholder { color: var(--color-placeholder); opacity: 1; }
.field input:focus-visible,
.field textarea:focus-visible { border-color: var(--color-navy); outline-offset: 1px; }
.field [aria-invalid="true"] { border-color: var(--color-error); }
.field-error { color: var(--color-error); font-size: var(--fs-sm); font-weight: var(--fw-semibold); margin: 0; }
.form-status { margin: 0; font-weight: var(--fw-semibold); color: var(--color-navy-dark); min-height: 1.5em; }
/* Status text lands on the wave band, so give it a solid backing (inline padding only = no height change) */
.form-status:not(:empty) { justify-self: start; padding-inline: var(--space-3); background: var(--color-surface); border-radius: var(--radius-sm); }

/* Without JavaScript the form can't build the email: hide Send, the <noscript> note shows the address */
html:not(.js) .contact-form button[type="submit"] { display: none; }
.form-noscript { margin: 0; padding: var(--space-3) var(--space-4); background: var(--color-surface); border-radius: var(--radius-md); font-weight: var(--fw-semibold); }
.form-noscript a { color: var(--color-navy); overflow-wrap: anywhere; }
.form-privacy { margin: 0; font-size: var(--fs-sm); color: var(--color-text-muted); }
.form-privacy a { color: var(--color-navy); font-weight: var(--fw-semibold); overflow-wrap: anywhere; }

/* Footer */
.site-footer { background: var(--color-cream); padding: var(--space-8) 0; border-top: var(--border-thin) solid var(--color-border); }
.footer-inner { display: grid; gap: var(--space-4); justify-items: center; text-align: center; }
.footer-inner p { margin: 0; color: var(--color-text-muted); font-size: var(--fs-sm); }

.footer-inner p a { color: var(--color-navy); font-weight: var(--fw-semibold); }

/* ---------- Privacy page (privacy.html) ---------- */
.legal { max-width: 50rem; } /* ≈ 75ch of Montserrat, in rem so the width does not change when the web font swaps in (CLS 0) */
.legal h1 { font-size: var(--fs-h2); line-height: var(--lh-snug); }
.legal h2,
.legal h3 { font-size: var(--fs-lg); line-height: var(--lh-snug); margin-top: var(--space-10); }
.legal .legal-updated { color: var(--color-text-muted); font-size: var(--fs-sm); }
.legal ul { padding-left: var(--space-6); }
.legal li + li { margin-top: var(--space-2); }
.legal a { color: var(--color-navy); overflow-wrap: anywhere; }
.table-wrap { overflow-x: auto; margin: var(--space-4) 0; border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-md); }
.legal table { width: 100%; min-width: 34rem; border-collapse: collapse; font-size: var(--fs-sm); line-height: var(--lh-normal); }
.legal th,
.legal td { text-align: left; vertical-align: top; padding: var(--space-3) var(--space-4); border-bottom: var(--border-thin) solid var(--color-border); }
.legal thead th { background: var(--color-sky-pale); color: var(--color-ink); }
.legal tbody tr:last-child td { border-bottom: 0; }
/* Phones: each table row becomes a labelled card (data-label on every <td>).
   The markup stays a real <table>; js/main.js §2b re-adds the ARIA table roles
   because some browsers (Safari) drop them when table elements get display:block. */
@media (max-width: 599.98px) {
  .table-wrap:has(.table-stack) { border: 0; border-radius: 0; overflow: visible; }
  .legal .table-stack { min-width: 0; }
  .legal .table-stack thead { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
  .legal .table-stack,
  .legal .table-stack tbody,
  .legal .table-stack tr,
  .legal .table-stack td { display: block; }
  .legal .table-stack tr { border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface); }
  .legal .table-stack tr + tr { margin-top: var(--space-3); }
  .legal .table-stack td { padding: var(--space-3) var(--space-4); }
  .legal .table-stack tbody tr:last-child td { border-bottom: var(--border-thin) solid var(--color-border); }
  .legal .table-stack tr td:last-child { border-bottom: 0; }
  .legal .table-stack td[data-label]::before {
    content: attr(data-label);
    content: attr(data-label) / ""; /* visual only: screen readers announce the real column header */
    display: block; margin-bottom: var(--space-1);
    color: var(--color-ink); font-weight: var(--fw-semibold);
    font-size: var(--fs-xs); letter-spacing: .02em; text-transform: uppercase;
  }
}
/* Text that must be completed before go-live */

/* ---------- Tablet ---------- */
@media (min-width: 600px) {
  .field-row { grid-template-columns: 1fr 1fr; }
  .projects { grid-template-columns: repeat(2, 1fr); }
  .skills-grid { grid-template-columns: repeat(4, 1fr); }
  .btn--wide { width: auto; }
  .contact-form .btn--wide { width: auto; justify-self: end; min-width: 180px; }
}

/* ---------- Tablet portrait + desktop: hero side by side ---------- */
@media (min-width: 768px) {
  .hero-inner {
    grid-template-columns: 300px minmax(0, 1fr);
    grid-template-areas: "media text" "social text";
    column-gap: var(--col-gap); row-gap: var(--space-4); align-items: center;
  }
  .hero-text { grid-area: text; }
  .hero-media { grid-area: media; }
  .social--hero { grid-area: social; }
}
@media (min-width: 768px) and (max-width: 899.98px) {
  .hero h1 { font-size: clamp(2.4rem, 5.5vw, 3.1rem); }
}

/* ---------- Desktop ---------- */
@media (min-width: 900px) {
  .hero-inner { grid-template-columns: 420px minmax(0, 1fr); row-gap: var(--space-6); }
  .hero-buttons { grid-template-columns: repeat(2, minmax(0, 220px)); }
  .two-col { grid-template-columns: 1fr 1fr; }
  .two-col--reverse .prose { order: 2; }
  .projects { grid-template-columns: repeat(3, 1fr); }
  .footer-inner { grid-template-columns: 1fr auto 1fr; text-align: left; } /* empty 3rd column keeps the copyright centred */
  .footer-inner .social { justify-self: start; }
}

/* ---------- Reduced motion: switch off any animation ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---------- Dark theme (F) ----------
   html[data-theme] is set before first paint by the inline head script
   (saved choice in localStorage, otherwise prefers-color-scheme).
   Without JS the media query below applies the same palette.
   KEEP THE TWO PALETTES BELOW IN SYNC. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --color-navy: #9cc6e7;        /* links / text accents – 10.6:1 on bg */
  --color-navy-dark: #d3e6f7;   /* hover + text on panels */
  --color-sky-pale: #1b2a3d;    /* panels */
  --color-cream: #141b25;       /* tinted sections + footer */
  --color-bg: #0f141b;
  --color-surface: #18212d;
  --color-text: #e3e7ed;
  --color-text-muted: #b3bdcb;
  --color-text-strong: #ffffff;
  --color-ink: #e6edf5;
  --color-placeholder: #97a3b3;
  --color-error: #ffb4ab;
  --color-border: #2a3646;
  --color-border-input: #7f97b2;
  --color-focus: #f2b75b;
  --color-surface-header: rgba(15, 20, 27, .96);
  --color-surface-glass: rgba(15, 20, 27, .82);
  --color-accent: #3a68a3;      /* white text 5.5:1 */
  --color-accent-hover: #2b5385;
  --color-divider: #3a4757;
  --color-success: #4cc27a;
  --color-whatsapp: #25d366;    /* WhatsApp brand green – 7.3:1 on dark panels */
  --shadow-md: 0 12px 24px rgba(0, 0, 0, .45);
  --wave-image: url("../images/wave-background-dark-960.webp");
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    color-scheme: dark;
    --color-navy: #9cc6e7;        /* links / text accents – 10.6:1 on bg */
    --color-navy-dark: #d3e6f7;   /* hover + text on panels */
    --color-sky-pale: #1b2a3d;    /* panels */
    --color-cream: #141b25;       /* tinted sections + footer */
    --color-bg: #0f141b;
    --color-surface: #18212d;
    --color-text: #e3e7ed;
    --color-text-muted: #b3bdcb;
    --color-text-strong: #ffffff;
    --color-ink: #e6edf5;
    --color-placeholder: #97a3b3;
    --color-error: #ffb4ab;
    --color-border: #2a3646;
    --color-border-input: #7f97b2;
    --color-focus: #f2b75b;
    --color-surface-header: rgba(15, 20, 27, .96);
    --color-surface-glass: rgba(15, 20, 27, .82);
    --color-accent: #3a68a3;      /* white text 5.5:1 */
    --color-accent-hover: #2b5385;
    --color-divider: #3a4757;
    --color-success: #4cc27a;
    --color-whatsapp: #25d366;
    --shadow-md: 0 12px 24px rgba(0, 0, 0, .45);
    --wave-image: url("../images/wave-background-dark-960.webp");
  }
}
:root[data-theme="light"] { color-scheme: light; }
/* the GV logo and the illustrations have light artwork: give them soft
   rounded edges so they sit on the dark page as cards */
:root[data-theme="dark"] .brand img { border-radius: var(--radius-md); }
@media (prefers-color-scheme: dark) { :root:not([data-theme]) .brand img { border-radius: var(--radius-md); } }

/* Theme button (JS only: it needs script to work). Shows the sun in light mode
   and the moon in dark mode; the icon follows <html data-theme> (set before
   first paint), so it never flashes. Base look shared with the globe, above. */
.theme-toggle { display: none; }
.js .theme-toggle { margin-inline-start: var(--space-2); }
.theme-icon--moon,
:root[data-theme="dark"] .theme-icon--sun { display: none; }
:root[data-theme="dark"] .theme-icon--moon { display: block; }
@media (max-width: 767px) {
  /* phones: the theme button stays in the header, next to the hamburger */
  .js .theme-toggle { order: 2; margin-inline-end: var(--space-2); }
  .js .nav-toggle { order: 3; }
}
