/*
  ahultsch.com — base styles
  Reads all colors/sizes/spacing from tokens.css. Do not hardcode values
  here — add a new token instead if something is missing.
*/

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

html {
  color-scheme: dark;
  /* Prevent iOS Safari from auto-boosting text size in narrow columns,
     which can push fixed-width content past its container. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

html[data-theme="light"] {
  color-scheme: light;
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  -webkit-font-smoothing: antialiased;
}

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

a {
  color: inherit;
  text-decoration: none;
}

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

/* ---------------------------------------------------------------- */
/* Header / Navigation                                               */
/* ---------------------------------------------------------------- */

.site-header {
  border-bottom: 1px solid var(--color-border);
  position: sticky;
  top: 0;
  background: var(--color-bg);
  z-index: 10;
}

.site-header .site-container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-4);
}

.site-logo {
  font-family: var(--font-mono);
  font-size: var(--text-lg);
  font-weight: 600;
  letter-spacing: -0.02em;
}

.site-logo span {
  color: var(--color-accent);
}

.main-nav {
  display: flex;
  align-items: center;
  gap: var(--space-6);
}

.main-nav ul {
  list-style: none;
  display: flex;
  gap: var(--space-5);
  margin: 0;
  padding: 0;
}

.main-nav a {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  transition: color var(--transition-fast);
}

.main-nav a:hover,
.main-nav a[aria-current="page"] {
  color: var(--color-text);
}

.nav-toggle {
  display: none;
}

/* Theme toggle: a circle, half black / half white */
.theme-toggle {
  width: 1.75rem;
  height: 1.75rem;
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border);
  background: linear-gradient(90deg, #0e1013 50%, #ffffff 50%);
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  transition: transform var(--transition-fast);
}

.theme-toggle:hover {
  transform: scale(1.08);
}

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

/* ---------------------------------------------------------------- */
/* Hero                                                              */
/* ---------------------------------------------------------------- */

.hero {
  padding-block: var(--space-8) var(--space-6);
}

.hero h1 {
  font-size: var(--text-3xl);
  line-height: var(--leading-tight);
  margin: 0 0 var(--space-4);
  max-width: 40ch;
}

.hero p {
  color: var(--color-text-muted);
  font-size: var(--text-lg);
  max-width: 55ch;
  margin: 0;
}

/* ---------------------------------------------------------------- */
/* Projects controls: filter tabs + view toggle                      */
/* ---------------------------------------------------------------- */

.projects-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}

.filter-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  list-style: none;
  margin: 0;
  padding: 0;
}

.filter-tabs button {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  background: transparent;
  border: 1px solid var(--color-border);
  color: var(--color-text-muted);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-full);
  cursor: pointer;
  transition: all var(--transition-fast);
}

.filter-tabs button:hover {
  color: var(--color-text);
  border-color: var(--color-text-muted);
}

.filter-tabs button[aria-pressed="true"] {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-accent-contrast);
}

.view-toggle {
  display: flex;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.view-toggle button {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  background: transparent;
  border: none;
  color: var(--color-text-muted);
  padding: var(--space-2) var(--space-4);
  cursor: pointer;
  transition: all var(--transition-fast);
}

.view-toggle button + button {
  border-left: 1px solid var(--color-border);
}

.view-toggle button[aria-pressed="true"] {
  background: var(--color-bg-elevated);
  color: var(--color-text);
}

/* ---------------------------------------------------------------- */
/* Grid view                                                         */
/* ---------------------------------------------------------------- */

.projects-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--space-5);
  padding: 0;
  margin: 0 0 var(--space-9);
  list-style: none;
}

.project-card {
  display: block;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-bg-alt);
  overflow: hidden;
  transition: border-color var(--transition-base), transform var(--transition-base);
}

.project-card:hover,
.project-card:focus-within {
  border-color: var(--color-accent);
  transform: translateY(-2px);
}

/* Wrapper so the status badge can sit on top of the tile image. */
.project-media {
  position: relative;
}

.project-card .project-image {
  aspect-ratio: 16 / 10;
  width: 100%;
  object-fit: cover;
  background: var(--color-bg-elevated);
  border-bottom: 1px solid var(--color-border);
}

/* ---------------------------------------------------------------- */
/* Project status badge (Stable / Active / Paused)                   */
/* ---------------------------------------------------------------- */

.project-status {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  /* line-height: 1 keeps the pill tight around the label, so the
     symmetric padding above and below is what actually decides the
     height. Deliberately NO hand-tuned optical offset here: how far
     the capitals sit from the line box centre depends on the font's
     own ascent/descent, so a fixed nudge that looks centred in one
     font is visibly wrong in another (ui-monospace resolves to SF Mono
     on Apple devices and to something else elsewhere). Plain centring
     is the only thing that behaves consistently across all of them. */
  line-height: 1;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  background: var(--color-status-bg);
  white-space: nowrap;
}

/* The coloured dot carries the status; the label stays readable. */
.project-status::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: var(--radius-full);
  background: currentColor;
  flex-shrink: 0;
}

.project-media .project-status {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
}

/* Class names come from the status text, lowercased and hyphenated
   (see statusMarkup in js/main.js): "In Progress" -> .status-in-progress */
.status-stable {
  color: var(--color-status-stable);
}

.status-in-progress {
  color: var(--color-status-in-progress);
}

.status-on-hold {
  color: var(--color-status-on-hold);
}

.project-card .project-body {
  padding: var(--space-4) var(--space-5) var(--space-5);
}

.project-card h3 {
  margin: 0 0 var(--space-2);
  font-size: var(--text-lg);
}

.project-card p {
  margin: 0 0 var(--space-4);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

/* One chip per part — a single-part project just shows one. */
.project-parts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.part-chip {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--color-accent);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  padding: var(--space-1) var(--space-3);
  transition: border-color var(--transition-fast), color var(--transition-fast);
}

a.part-chip:hover {
  border-color: var(--color-accent);
}

/* ---------------------------------------------------------------- */
/* List / index view                                                 */
/* ---------------------------------------------------------------- */

/* On narrow screens the table is wider than the viewport; it scrolls
   inside this wrapper so the page itself never scrolls sideways. */
.projects-list-wrap {
  overflow-x: auto;
}

.projects-list {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: var(--space-9);
}

.projects-list thead th {
  text-align: left;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: var(--space-3) var(--space-3);
  border-bottom: 1px solid var(--color-border);
}

.projects-list tbody tr {
  border-bottom: 1px solid var(--color-border);
  transition: background var(--transition-fast);
}

.projects-list tbody tr:hover {
  background: var(--color-bg-alt);
}

.projects-list tbody .cell-link {
  display: block;
  padding: var(--space-4) var(--space-3);
}

/* Secondary "Repo" link inline next to the category cell's main link.
   A wrapper div (not the <td> itself) takes the flex layout, so the
   cell keeps normal table layout for column alignment. */
.category-cell-inner {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.projects-list .col-no {
  font-family: var(--font-mono);
  color: var(--color-text-muted);
  width: 3rem;
}

.projects-list .col-category {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-accent);
  white-space: nowrap;
}

.projects-list .col-project {
  font-weight: 600;
}

/* Status gets its own column so the badges line up regardless of how
   long the project names are. width: 1% + nowrap makes the column
   shrink to fit its content. No background here — unlike on a tile,
   the badge isn't sitting on top of an image. */
.projects-list .col-status {
  width: 1%;
  white-space: nowrap;
}

.projects-list .project-status {
  background: transparent;
  font-weight: 400;
}

.projects-list .col-description {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

[hidden] {
  display: none !important;
}

/* ---------------------------------------------------------------- */
/* Generic content pages (about / contact / legal)                   */
/* ---------------------------------------------------------------- */

.page-content {
  padding-block: var(--space-7) var(--space-9);
  max-width: 65ch;
}

.page-content h1 {
  font-size: var(--text-2xl);
  margin-bottom: var(--space-5);
}

.page-content h2 {
  font-size: var(--text-lg);
  margin-top: var(--space-7);
}

.page-content p {
  color: var(--color-text-muted);
}

.page-content a {
  color: var(--color-accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.contact-links {
  list-style: none;
  padding: 0;
  margin: var(--space-5) 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.contact-links a {
  font-family: var(--font-mono);
  font-size: var(--text-lg);
  color: var(--color-text);
  text-decoration: none;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  display: block;
  max-width: 100%;
  overflow-wrap: anywhere;
  word-break: break-word;
  transition: border-color var(--transition-fast), color var(--transition-fast);
}

.contact-links a:hover {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

/* ---------------------------------------------------------------- */
/* Bug report page                                                    */
/* ---------------------------------------------------------------- */

.bug-list {
  list-style: none;
  margin: var(--space-5) 0 var(--space-9);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.bug-list a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  transition: border-color var(--transition-fast);
}

.bug-list a:hover {
  border-color: var(--color-accent);
}

.bug-list .bug-project-name {
  font-weight: 600;
}

.bug-list .bug-project-category {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* ---------------------------------------------------------------- */
/* Footer                                                             */
/* ---------------------------------------------------------------- */

.site-footer {
  border-top: 1px solid var(--color-border);
  margin-top: var(--space-8);
}

.site-footer .site-container {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding-block: var(--space-5);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.footer-links {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin: 0;
  padding: 0;
}

.footer-links a {
  color: var(--color-text-muted);
  transition: color var(--transition-fast);
}

.footer-links a:hover {
  color: var(--color-text);
}

/*
  Backlog placeholder (see spec §11 / §10): a future "Support / Buy me a
  coffee" link can be added to .footer-links as a plain <li><a> entry —
  no markup changes needed elsewhere.
*/

/* ---------------------------------------------------------------- */
/* Responsive                                                        */
/* ---------------------------------------------------------------- */

@media (max-width: 640px) {
  .site-header .site-container {
    flex-wrap: wrap;
  }

  .main-nav {
    order: 3;
    width: 100%;
  }

  .main-nav ul {
    gap: var(--space-4);
  }

  .hero h1 {
    font-size: var(--text-2xl);
  }

  .hero p {
    font-size: var(--text-base);
  }

  .projects-grid {
    grid-template-columns: 1fr;
  }

  .projects-list .col-description {
    display: none;
  }

  .contact-links a {
    font-size: var(--text-base);
  }

  .projects-controls {
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-3);
  }

  .filter-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    padding-bottom: var(--space-2);
    /* The tabs must not push the page wider than the viewport. Flex
       stretch alone doesn't constrain them here, so pin the width to
       the container and let the row scroll inside itself instead. */
    width: 100%;
    min-width: 0;
  }

  .view-toggle {
    align-self: flex-start;
  }
}
