/* ---------------------------------------------------------------------------
   David Wünsche portfolio — single stylesheet, no dependencies

   Two themes share one set of tokens. The palette is lifted from
   blog.wincak.name: a near-black page, flat panels and a burnt-orange accent.
   `data-theme` is set on <html> before first paint (see the inline script in
   index.html), so there is never a flash of the wrong theme.
   --------------------------------------------------------------------------- */

:root {
  --maxw: 56rem;
  --radius: 8px;
  --gap: 1.25rem;
  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
    "Liberation Mono", monospace;
}

/* Dark is the signature look, matching the blog. */
[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0f0f0f;
  --card: #1d1d1d;
  --fg: #dddddd;
  --muted: #918e91;
  --accent: #e4741f;
  --accent-hover: #ff8c3d;
  --accent-text: #e4741f;
  --accent-fg: #16110c;
  --border: #2c2c2c;
  --header-bg: #000000;
}

/* Light keeps the same hue but darkens it so links stay readable on white. */
[data-theme="light"] {
  color-scheme: light;
  --bg: #f7f7f5;
  --card: #ffffff;
  --fg: #1a1a1a;
  --muted: #5c5c5c;
  --accent: #c25a10;
  --accent-hover: #a04a0a;
  --accent-text: #b3540e;
  --accent-fg: #ffffff;
  --border: #dcdcdc;
  --header-bg: #ffffff;
}

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

html {
  scroll-behavior: smooth;
  /* offset for the sticky header when jumping to an anchor */
  scroll-padding-top: 5rem;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  font-size: clamp(1rem, 0.96rem + 0.2vw, 1.0625rem);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Hide everything until the correct language has been applied (see index.html). */
html.i18n-pending body {
  visibility: hidden;
}

h1, h2, h3 {
  line-height: 1.2;
  margin: 0 0 0.6em;
  letter-spacing: -0.015em;
}

h1 {
  font-size: clamp(2.25rem, 1.6rem + 3vw, 3.5rem);
}

h2 {
  font-size: clamp(1.5rem, 1.25rem + 1.2vw, 2rem);
}

h3 {
  font-size: 1.075rem;
}

p {
  margin: 0 0 1rem;
}

a {
  color: var(--accent-text);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  transition: color 0.15s ease;
}

a:hover {
  color: var(--accent-hover);
  text-decoration-thickness: 2px;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

.container {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: 1.25rem;
}

.section {
  margin-bottom: 1rem;
}

/* Every section is a flat panel with an accent-underlined title, following the
   single-column card stack used by starkly.tech. */
.section,
.hero {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: clamp(1.25rem, 3vw, 2rem);
}

/* The hero has no heading of its own: the name and role live in the persistent
   header, so the tagline is promoted to the panel's headline. */
.section > h2,
.hero > .lede {
  padding-bottom: 0.6rem;
  border-bottom: 2px solid var(--accent);
  margin-bottom: 1.1rem;
}

.section > h2 {
  font-size: clamp(1.25rem, 1.1rem + 0.8vw, 1.6rem);
}

.hero > .lede {
  font-size: clamp(1.35rem, 1.1rem + 1.3vw, 1.9rem);
}

/* Trailing block inside a panel should not add extra space. */
.section > :last-child,
.hero > :last-child {
  margin-bottom: 0;
}

.muted {
  color: var(--muted);
}

.prose {
  max-width: 46rem;
}

/* --- skip link ----------------------------------------------------------- */

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--accent);
  color: var(--accent-fg);
  padding: 0.6rem 1rem;
  border-radius: 0 0 var(--radius) 0;
  text-decoration: none;
}

.skip-link:focus {
  left: 0;
}

/* --- header -------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--header-bg) 88%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--border);
}

.header-inner {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  min-height: 3.75rem;
}

.brand {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  min-width: 0;
}

.brand-name {
  margin: 0;
  font-size: 1.35rem;
  line-height: 1.1;
  letter-spacing: -0.02em;
  white-space: nowrap;
}

.brand-name a {
  color: var(--fg);
  text-decoration: none;
}

.brand-sep {
  color: var(--muted);
}

.brand-role {
  margin: 0;
  font-family: var(--mono);
  font-size: 0.8125rem;
  color: var(--muted);
}

/* Shrink the name/role pair so it still fits one line beside the controls on
   narrow screens, rather than wrapping the name. */
@media (max-width: 34rem) {
  .brand {
    gap: 0.45rem;
  }

  .brand-name {
    font-size: 1.15rem;
  }

  .brand-role {
    font-size: 0.7rem;
  }
}

/* Language switcher and theme toggle sit together at the end of the header. */
.header-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-left: auto;
}
.lang-switch {
  display: flex;
  gap: 0.25rem;
  padding: 0.2rem;
  border: 1px solid var(--border);
  border-radius: 999px;
}

.lang-btn {
  font: inherit;
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1;
  padding: 0.35rem 0.6rem;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}

.lang-btn[aria-pressed="true"] {
  background: var(--fg);
  color: var(--bg);
}

/* --- theme toggle -------------------------------------------------------- */

.theme-toggle {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
}

.theme-toggle input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

.toggle-track {
  position: relative;
  display: block;
  width: 3.25rem;
  height: 1.6rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--fg) 14%, transparent);
  border: 1px solid var(--border);
  transition: background-color 0.25s ease;
}

.toggle-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 1.15rem;
  height: 1.15rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.65rem;
  line-height: 1;
  border-radius: 50%;
  background: var(--card);
  box-shadow: 0 1px 3px rgb(0 0 0 / 0.35);
  transition: transform 0.25s ease;
}

.theme-toggle input:checked + .toggle-track .toggle-thumb {
  transform: translateX(1.6rem);
}

.theme-toggle input:focus-visible + .toggle-track {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* --- hero ---------------------------------------------------------------- */

.hero {
  margin-bottom: 1rem;
  margin-top: 1rem;
}

.hero .muted {
  max-width: 42rem;
}

.cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 1.5rem;
  margin-bottom: 0;
}

.btn {
  display: inline-block;
  padding: 0.65rem 1.15rem;
  border-radius: 999px;
  font-size: 0.9375rem;
  font-weight: 600;
  text-decoration: none;
  border: 1px solid transparent;
  transition: transform 0.12s ease, opacity 0.12s ease;
}

.btn:hover {
  transform: translateY(-1px);
}

.btn-primary {
  background: var(--accent);
  color: var(--accent-fg);
}

.btn-ghost {
  border-color: var(--border);
  color: var(--fg);
}

/* --- project entries ------------------------------------------------------
   With the images gone, all six projects live inside one "Projects" panel as
   With the images gone, all six projects live inside one "Projects" panel as
   plain titled entries, the way starkly.tech presents its selected work. */

.entries {
  list-style: none;
  margin: 0;
  padding: 0;
}

.entry + .entry {
  margin-top: 1.75rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--border);
}

.entry h3 {
  font-size: 1.075rem;
  margin-bottom: 0.5rem;
}

.entry p {
  margin-bottom: 0.75rem;
  font-size: 0.9375rem;
}

.entry p:last-child {
  margin-bottom: 0;
}

/* Year range under an entry heading, in the mono face, following starkly.tech.
   It is a <div>, not a <p>, so the `.entry p` rule does not reach it. */
.period {
  color: var(--muted);
  font-size: 0.9rem;
  font-family: var(--mono);
  margin-bottom: 0.6rem;
}

/* --- cards --------------------------------------------------------------- */

.grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
}

/* Four service cards read best as a tidy 2x2 rather than 3+1. */
.card-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (max-width: 34rem) {
  .card-grid {
    grid-template-columns: 1fr;
  }
}

.card {
  background: color-mix(in srgb, var(--fg) 5%, transparent);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.25rem;
}

.card h3 {
  margin-bottom: 0.4rem;
  font-size: 1rem;
}

.card p {
  color: var(--muted);
  margin-bottom: 0.75rem;
  font-size: 0.9375rem;
}

.card > :last-child {
  margin-bottom: 0;
}

/* Technical skills — labelled lists rather than a pill cloud. Each `.skill-group`
   is an <h3> label over a compact <ul>, so a buyer scans "Yocto" under
   "Embedded Linux" instead of hunting through a wall of tags. */
.skill-groups {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.skill-label {
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.35rem;
}

.skill-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  font-size: 0.9375rem;
}

/* A quiet marker instead of a bullet, so the items read as a list without the
   visual noise of pills. */
.skill-list li {
  padding-left: 1rem;
  position: relative;
}

.skill-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 0.3rem;
  height: 1px;
  background: var(--border);
}

.pill-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.pill-list li {
  font-family: var(--mono);
  font-size: 0.8125rem;
  color: var(--fg);
  background: color-mix(in srgb, var(--fg) 7%, transparent);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.3rem 0.8rem;
}

/* A pill that is honest about being a work in progress (e.g. "Exploring: Rust"). */
.pill-list li.pill-muted {
  color: var(--muted);
  background: transparent;
  border-style: dashed;
}

/* --- contact ------------------------------------------------------------- */

.contact-list {
  list-style: none;
  margin: 1.25rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
  font-size: 0.9375rem;
}

.contact-list a {
  font-family: var(--mono);
  font-size: 0.875rem;
}

/* --- contact list icons --------------------------------------------------- */

.contact-list a {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
}

.contact-icon {
  width: 1em;
  height: 1em;
  flex: none;
}

/* --- footer -------------------------------------------------------------- */

.site-footer {
  border-top: 1px solid var(--border);
  padding-block: 1.5rem;
  font-size: 0.875rem;
}

.site-footer p {
  margin: 0;
}

/* --- motion -------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}
