/* Shared theme tokens, base layout primitives, accent treatment, dividers,
   micro-interactions, dark/light toggle button, and scroll-reveal animation.
   Included by every page so appearance and behaviour stay identical site-wide
   without needing to be hand-synced across pages. */

:root{
  --bg:#0b1220;
  --text:#e8eefc;
  --muted:#b8c4e6;
  --link:#9cc2ff;
  --border:rgba(255,255,255,.10);
  --shadow:0 10px 30px rgba(0,0,0,.35);
  --shadow-hover:0 16px 40px rgba(0,0,0,.45);
  --card-bg:linear-gradient(180deg,rgba(255,255,255,.05),rgba(255,255,255,.03));
  --inset-bg:rgba(0,0,0,.12);
  --avatar-bg:rgba(0,0,0,.2);
  --accent:#2dd4bf;
  --accent-rgb:45,212,191;
}

/* Dark is the default for every new visitor; light only applies once explicitly chosen and stored */
:root[data-theme="light"]{
  --bg:#f4f7fc;
  --text:#0f172a;
  --muted:#48536b;
  --link:#1d5fd6;
  --border:rgba(15,23,42,.14);
  --shadow:0 10px 30px rgba(15,23,42,.12);
  --shadow-hover:0 16px 40px rgba(15,23,42,.18);
  --card-bg:linear-gradient(180deg,#ffffff,#f3f6fc);
  --inset-bg:rgba(15,23,42,.05);
  --avatar-bg:rgba(15,23,42,.08);
  --accent:#0f766e;
  --accent-rgb:15,118,110;
}

body{
  margin:0;
  font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,"Apple Color Emoji","Segoe UI Emoji";
  background:
    radial-gradient(1200px 700px at 20% -10%, rgba(156,194,255,.25), transparent 55%),
    radial-gradient(900px 600px at 90% 10%, rgba(148,255,214,.12), transparent 50%),
    radial-gradient(800px 420px at 50% 0%, rgba(var(--accent-rgb),.10), transparent 60%),
    var(--bg);
  color:var(--text);
  line-height:1.6;
}

/* Faint drifting circuit-board texture, fixed behind all content on every
   page. A single tile repeats via mask-image over background-color:var(--text),
   so it's theme-aware (light tint on dark backgrounds, dark tint on light)
   rather than a single fixed colour that would vanish in one theme. Drifting
   exactly one tile width/height (120px) loops seamlessly. */
.bg-pattern{
  position:fixed;
  inset:0;
  z-index:-1;
  opacity:.05;
  pointer-events:none;
  background-color:var(--text);
  -webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'%3E%3Cg fill='none' stroke='%23fff' stroke-width='1.2'%3E%3Cpath d='M0 30 H45 M45 30 V60 M45 60 H120'/%3E%3Cpath d='M0 90 H30 M30 90 V15 M30 15 H90 M90 15 V0'/%3E%3C/g%3E%3Cg fill='%23fff'%3E%3Ccircle cx='45' cy='30' r='2.5'/%3E%3Ccircle cx='45' cy='60' r='2.5'/%3E%3Ccircle cx='30' cy='90' r='2.5'/%3E%3Ccircle cx='30' cy='15' r='2.5'/%3E%3Ccircle cx='90' cy='15' r='2.5'/%3E%3C/g%3E%3C/svg%3E");
  mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'%3E%3Cg fill='none' stroke='%23fff' stroke-width='1.2'%3E%3Cpath d='M0 30 H45 M45 30 V60 M45 60 H120'/%3E%3Cpath d='M0 90 H30 M30 90 V15 M30 15 H90 M90 15 V0'/%3E%3C/g%3E%3Cg fill='%23fff'%3E%3Ccircle cx='45' cy='30' r='2.5'/%3E%3Ccircle cx='45' cy='60' r='2.5'/%3E%3Ccircle cx='30' cy='90' r='2.5'/%3E%3Ccircle cx='30' cy='15' r='2.5'/%3E%3Ccircle cx='90' cy='15' r='2.5'/%3E%3C/g%3E%3C/svg%3E");
  -webkit-mask-size:120px 120px;
  mask-size:120px 120px;
  -webkit-mask-repeat:repeat;
  mask-repeat:repeat;
}

@media (prefers-reduced-motion: no-preference){
  .bg-pattern{
    animation:bg-drift 100s linear infinite;
  }
}

@keyframes bg-drift{
  from{
    -webkit-mask-position:0 0;
    mask-position:0 0;
  }
  to{
    -webkit-mask-position:120px 120px;
    mask-position:120px 120px;
  }
}

a{
  color:var(--link);
  text-decoration:underline;
  text-decoration-color:transparent;
  text-underline-offset:3px;
}

@media (prefers-reduced-motion: no-preference){
  a{
    transition:color 180ms ease-out, text-decoration-color 180ms ease-out;
  }
}

a:hover,
a:active{
  color:var(--accent);
  text-decoration-color:var(--accent);
}

.nav-left{
  border-bottom:2px solid var(--accent);
  padding-bottom:8px;
}

h2{
  display:flex;
  align-items:center;
  gap:8px;
  margin:0 0 10px;
  font-size:18px;
  letter-spacing:0.2px;
}

h2::before{
  content:"";
  flex:0 0 auto;
  width:10px;
  height:10px;
  border-radius:3px;
  background:var(--accent);
}

/* Glassmorphism: the tint reuses --bg itself rather than a different
   colour, so the WCAG contrast relationship between text and card
   background is preserved by construction — blending a colour with
   itself changes nothing. Disabled below 700px (falls back to the
   solid --card-bg gradient) since backdrop-filter is a known mobile
   Safari/Chrome performance risk with this many cards on one page. */
.card{
  background:rgba(11,18,32,.68);
  border:1px solid var(--border);
  border-radius:var(--radius);
  box-shadow:var(--shadow);
  padding:22px;
  backdrop-filter:blur(12px);
  -webkit-backdrop-filter:blur(12px);
}

:root[data-theme="light"] .card{
  background:rgba(244,247,252,.74);
}

@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .card{
    background:var(--card-bg);
  }
}

@media (max-width:700px){
  .card{
    background:var(--card-bg);
    backdrop-filter:none;
    -webkit-backdrop-filter:none;
  }
}

.item{
  padding:14px;
  border:1px solid var(--border);
  border-radius:14px;
  background:var(--inset-bg);
}

.btn{
  display:inline-flex;
  align-items:center;
  padding:12px 14px;
  border:1px solid rgba(var(--accent-rgb),.35);
  border-radius:12px;
  background:rgba(var(--accent-rgb),.14);
  color:var(--text);
  font-size:14px;
  text-decoration:none;
}

.btn:hover{
  background:rgba(var(--accent-rgb),.22);
  text-decoration:none;
}

@media (prefers-reduced-motion: no-preference){
  .btn{
    transition:transform 120ms ease-out;
  }

  .btn:active{
    transform:scale(0.97);
  }

  .item{
    transition:transform 180ms ease-out, box-shadow 180ms ease-out;
  }

  .item:hover{
    transform:translateY(-2px);
    box-shadow:var(--shadow-hover);
  }
}

/* Section divider: a single reusable curved-line SVG, referenced from each
   page's own hidden <svg><defs> gradient (id="divider-fade"). */
.divider{
  grid-column:1 / -1;
  width:100%;
  height:22px;
  color:var(--accent);
  opacity:.4;
}

.divider svg{
  width:100%;
  height:100%;
  display:block;
}

.divider path{
  fill:none;
  stroke-width:1.5;
  stroke-linecap:round;
  vector-effect:non-scaling-stroke;
}

@media (max-width:650px){
  .divider{
    height:14px;
  }
}

.theme-toggle{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  width:30px;
  height:30px;
  padding:0;
  border:1px solid var(--border);
  border-radius:999px;
  background:var(--inset-bg);
  color:var(--muted);
  cursor:pointer;
}

.theme-toggle:hover{
  color:var(--text);
}

.theme-toggle:focus-visible{
  outline:2px solid var(--link);
  outline-offset:2px;
}

.theme-toggle svg{
  width:16px;
  height:16px;
  display:block;
}

.theme-toggle .icon-sun{
  display:none;
}

:root[data-theme="light"] .theme-toggle .icon-moon{
  display:none;
}

:root[data-theme="light"] .theme-toggle .icon-sun{
  display:block;
}

/* Scroll-triggered fade-in: only applies when JS confirms IntersectionObserver
   support (html.js-reveal) and the user has no reduced-motion preference. */
@media (prefers-reduced-motion: no-preference){
  html.js-reveal .card{
    opacity:0;
    transform:translateY(14px);
    transition:opacity 350ms ease-out, transform 350ms ease-out;
    transition-delay:var(--reveal-delay,0ms);
  }

  html.js-reveal .card.is-visible{
    opacity:1;
    transform:translateY(0);
  }

  /* Hover lift: redefines transition+transform at matching specificity to the
     .is-visible rule above (same selector shape, later in source order) so it
     reliably wins on already-revealed cards instead of being silently
     overridden by the reveal system's own transition. */
  html.js-reveal .card:hover{
    transition:transform 180ms ease-out, box-shadow 180ms ease-out;
    transform:translateY(-3px);
    box-shadow:var(--shadow-hover);
  }
}
