/*
  components.css
  Shared, reusable component styles used identically across every
  page. Scope is limited to components explicitly defined in the
  Design Specification §2 (Zone System) and §7 (Component Design
  Language): Zone System, Navigation Bar, Buttons, Cards, Tags/
  Badges, Section Eyebrow, Zone Label, Form Elements, Data Table,
  Progress Bar, Footer.

  Components not yet visually specified in the Design Specification
  (e.g. Modal, Timeline, Resume component) are intentionally NOT
  included here — building them now would mean inventing UI that
  hasn't been approved. They are deferred to Milestone 3, to be
  built once their visual treatment is confirmed, reusing these
  same tokens.

  No page-specific layout belongs here (see pages/*.css).
  Depends on: tokens.css.
*/

/* ============================================================
   ZONE SYSTEM (spec §2)
   Applied to <section> wrappers. Purely a background/border
   treatment — carries no layout implication.
   ============================================================ */
.zone-editorial {
  background: var(--color-bg-page);
}

.zone-mission-control {
  background: var(--color-bg-surface);
}

.zone-editorial + .zone-mission-control,
.zone-mission-control + .zone-editorial {
  border-top: 0.5px solid var(--color-zone-divider);
}

/* ============================================================
   PAGE CONTAINER (Milestone 3.1 — Global Layout Component)
   The shared page shell every route uses: header, main content
   area that grows to fill remaining height, footer pinned to
   the bottom on short-content pages. Layout only — no visual
   styling of its own beyond flex structure.
   ============================================================ */
.page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.page__main {
  flex: 1 0 auto;
}

/* ============================================================
   NAVIGATION BAR (spec §7)
   ------------------------------------------------------------
   AMENDED in Milestone 3.1 (approved change): the Milestone 2
   placeholder assumed two separate markup blocks (a desktop
   `.nav__links` row and a distinct `.nav__overlay` copy of the
   same links), which would have forced duplicated link markup.
   Replaced with a single `<nav>`/`<ul>` link list that CSS
   repositions between "off-canvas overlay" (mobile) and
   "inline row" (tablet+) — one source of markup, two layouts.
   All other component rules in this file are unchanged.
   ============================================================ */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  height: var(--nav-height);
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: #0F0F0F;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 0.5px solid var(--color-border-default);
  padding-inline: var(--page-padding-x-mobile);
}

@media (min-width: 768px) {
  .site-header {
    padding-inline: var(--page-padding-x);
  }
}

.site-header__logo {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 700;
  letter-spacing: -0.5px;
  color: var(--color-text-primary);
}

.site-header__logo-dot {
  color: var(--color-accent-500);
}

/* Hamburger trigger — hidden at tablet+, a real <button> so it
   is natively keyboard-operable without extra JS wiring. */
.site-header__toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  background: transparent;
}

@media (min-width: 768px) {
  .site-header__toggle {
    display: none;
  }
}

.site-header__toggle-icon,
.site-header__toggle-icon::before,
.site-header__toggle-icon::after {
  display: block;
  width: 20px;
  height: 2px;
  background: var(--color-text-primary);
  border-radius: 1px;
}
.site-header__toggle-icon {
  position: relative;
}
.site-header__toggle-icon::before,
.site-header__toggle-icon::after {
  content: '';
  position: absolute;
  left: 0;
}
.site-header__toggle-icon::before { top: -6px; }
.site-header__toggle-icon::after  { top: 6px; }

/* The single nav panel: off-canvas full-screen overlay on mobile,
   inline row at tablet+. Toggled via [data-open] set by nav.js. */
.nav {
  position: fixed;
  top: var(--nav-height);
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 99;
  background: #111111;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--duration-base) var(--ease-out);
}

.nav[data-open="true"] {
  visibility: visible;
  opacity: 1;
}

.nav__list {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-6);
}

.nav__link {
  font-size: 24px;
  min-height: 48px;
  display: flex;
  align-items: center;
  color: var(--color-text-tertiary);
  transition: color var(--duration-fast) var(--ease-out);
}

.nav__link:hover {
  color: var(--color-accent-400);
}

/* Active page indicator — color change only, per spec (no
   underline, no background). aria-current="page" is both the
   accessible signal and the visual hook — never color alone. */
.nav__link[aria-current="page"] {
  color: var(--color-accent-400);
}

/* Close control inside the mobile overlay */
.nav__close {
  position: absolute;
  top: 16px;
  right: 16px;
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: var(--color-text-primary);
  font-size: 20px;
}

@media (min-width: 768px) {
  .nav {
    position: static;
    inset: auto;
    z-index: auto;
    background: none;
    flex-direction: row;
    visibility: visible;
    opacity: 1;
    transition: none;
  }
  .nav__list {
    flex-direction: row;
    gap: var(--space-6);
  }
  .nav__link {
    font-size: 13px;
    font-weight: 400;
    min-height: auto;
  }
  .nav__close {
    display: none;
  }
}

/* ============================================================
   BUTTONS (spec §7)
   ============================================================ */
.btn-primary,
.btn-secondary,
.btn-ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  border-radius: var(--radius-md);
  padding: 10px 22px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out);
}

.btn-primary {
  background: var(--color-accent-500);
  color: var(--color-text-primary);
  border: none;
}
.btn-primary:hover {
  background: var(--color-accent-600);
}
.btn-primary:focus-visible {
  outline: 2px solid var(--color-accent-500);
  outline-offset: 2px;
}

.btn-secondary {
  background: transparent;
  color: var(--color-accent-400);
  border: 0.5px solid var(--color-accent-500);
}
.btn-secondary:hover {
  background: var(--color-accent-bg);
}

.btn-ghost {
  background: transparent;
  color: var(--color-text-secondary);
  border: 0.5px solid var(--color-border-strong);
}
.btn-ghost:hover {
  border-color: var(--color-text-muted);
}

/* ============================================================
   CARDS (spec §7)
   ============================================================ */
.card {
  background: var(--color-bg-card);
  border: 0.5px solid var(--color-border-strong);
  border-radius: var(--radius-xl);
  padding: var(--space-6);
  transition: border-color var(--duration-fast) var(--ease-out);
}
.card:hover {
  border-color: #333333;
}

.card-featured {
  border-radius: var(--radius-3xl);
  overflow: hidden;
}

.card-featured .card-banner {
  background: linear-gradient(135deg, #1E1529 0%, #0F0A1E 60%, var(--color-bg-page) 100%);
  padding: 36px 32px;
  border-bottom: 0.5px solid var(--color-border-strong);
}

/* ============================================================
   TAGS / BADGES (spec §7)
   ============================================================ */
.tag {
  display: inline-block;
  background: var(--color-accent-tag-bg);
  color: var(--color-accent-400);
  border-radius: var(--radius-sm);
  padding: 3px 8px;
  font-size: 11px;
  font-weight: 500;
}

.badge-ok      { background: var(--color-status-ok-bg);    color: var(--color-status-ok); }
.badge-warn    { background: var(--color-status-warn-bg);  color: var(--color-status-warn); }
.badge-alert   { background: var(--color-status-alert-bg); color: var(--color-status-alert); }
.badge-accent  { background: var(--color-accent-bg);       color: var(--color-accent-400); }
.badge-neutral {
  background: #1A1A1A;
  color: var(--color-text-disabled);
  border: 0.5px solid var(--color-border-default);
}

/* Status indicators must never rely on color alone (spec §10) —
   pair a badge with a visible text label in markup, e.g.:
   <span class="badge-ok">Active</span> */

/* ============================================================
   SECTION EYEBROW (spec §7)
   ============================================================ */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-accent-500);
}
.eyebrow::before {
  content: '';
  width: 24px;
  height: 1px;
  background: var(--color-accent-500);
  display: inline-block;
  flex-shrink: 0;
}

/* ============================================================
   ZONE LABEL (mission control sections) (spec §7)
   ============================================================ */
.zone-label {
  display: block;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin-bottom: 8px;
}

/* ============================================================
   FORM ELEMENTS (spec §7)
   ============================================================ */
.field input,
.field textarea,
.field select {
  background: var(--color-bg-input);
  border: 0.5px solid var(--color-border-strong);
  border-radius: var(--radius-lg);
  padding: 10px 14px;
  font-size: 13px;
  color: var(--color-text-primary);
  font-family: var(--font-body);
  width: 100%;
  min-height: 44px;
  outline: none;
  transition: border-color var(--duration-fast) var(--ease-out),
              background var(--duration-fast) var(--ease-out);
}
.field textarea {
  min-height: 110px;
  resize: vertical;
}
.field input:focus,
.field textarea:focus,
.field select:focus {
  border-color: var(--color-accent-500);
  background: #16101F;
}
.field label {
  display: inline-block;
  margin-bottom: var(--space-2);
  font-size: 11px;
  font-weight: 500;
  color: var(--color-text-tertiary);
  letter-spacing: 0.04em;
}

/* Every input must have an associated <label for="..."> in markup
   (spec §10) — enforced at the HTML authoring stage, not by CSS. */

/* ============================================================
   DATA TABLE — CTF writeups (spec §7)
   Native <table> markup, not CSS-grid divs, for reliable
   cross-browser rendering and correct table semantics.
   ============================================================ */
.data-table {
  width: 100%;
  border-collapse: collapse;
  border: 0.5px solid #1E1E1E;
  border-radius: var(--radius-xl);
  overflow: hidden;
}
.data-table thead tr {
  background: #0A0A0A;
}
.data-table thead th {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-text-disabled);
  padding: 10px 16px;
  text-align: left;
  border-bottom: 0.5px solid #1E1E1E;
  white-space: nowrap;
}
.data-table tbody tr {
  background: var(--color-bg-page);
  border-bottom: 0.5px solid var(--color-border-subtle);
  transition: background var(--duration-fast);
}
.data-table tbody tr:last-child {
  border-bottom: none;
}
.data-table tbody tr:hover {
  background: var(--color-bg-card);
}
.data-table tbody td {
  padding: 13px 16px;
  font-size: 12px;
  color: var(--color-text-secondary);
  vertical-align: middle;
}

/* ============================================================
   PROGRESS BAR (spec §7)
   ============================================================ */
.progress-track {
  background: var(--color-bg-hover);
  border-radius: 2px;
  height: 3px;
  width: 100%;
}
.progress-fill {
  height: 3px;
  border-radius: 2px;
  background: var(--color-accent-500);
  /* Width is set as --progress-value on the element by render-progress.js
     so JS never writes a bare pixel/percent as a presentational inline value. */
  width: var(--progress-value, 0%);
  transition: width var(--duration-slow) var(--ease-out);
}

/* ============================================================
   FOOTER (spec §7)
   ============================================================ */
.footer {
  background: #0A0A0A;
  border-top: 0.5px solid var(--color-border-subtle);
  padding: 20px var(--page-padding-x-mobile);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  align-items: flex-start;
}

@media (min-width: 768px) {
  .footer {
    padding: 20px var(--page-padding-x);
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
}

.footer__copyright {
  font-size: 11px;
  color: var(--color-text-disabled);
}

.footer__links {
  display: flex;
  gap: var(--space-4);
}

.footer__links a {
  font-size: 11px;
  color: var(--color-text-muted);
  transition: color var(--duration-fast) var(--ease-out);
}
.footer__links a:hover {
  color: var(--color-text-secondary);
}

/* ============================================================
   MILESTONE 3.2 — CORE UI ELEMENTS
   Additive only — nothing above this line was changed. Existing
   .tag / .badge-* / .eyebrow (already approved) are reused as-is,
   not duplicated. Everything below extends the same tokens.
   ============================================================ */

/* ------------------------------------------------------------
   ICON BUTTON
   Always pair with a visually-hidden text label or aria-label in
   markup — an icon alone is never an accessible name.
   ------------------------------------------------------------ */
.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  border-radius: var(--radius-md);
  background: transparent;
  border: 0.5px solid var(--color-border-strong);
  color: var(--color-text-secondary);
  transition: border-color var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out);
}
.btn-icon:hover {
  border-color: var(--color-text-muted);
  color: var(--color-text-primary);
}
.btn-icon svg,
.btn-icon img {
  width: 18px;
  height: 18px;
}

/* Accent variant — for a single emphasized icon action per view */
.btn-icon--accent {
  border-color: var(--color-accent-500);
  color: var(--color-accent-400);
}
.btn-icon--accent:hover {
  background: var(--color-accent-bg);
}

/* ------------------------------------------------------------
   PILL (generic neutral pill container — version tags, filter
   pills, misc small labels that are neither a status nor a tech
   tag). Distinct from .tag (rectangular, accent) and .chip
   (pill-shaped, dismissible, interactive) below.
   ------------------------------------------------------------ */
.pill {
  display: inline-flex;
  align-items: center;
  padding: 4px 12px;
  border-radius: var(--radius-pill);
  background: var(--color-bg-hover);
  color: var(--color-text-secondary);
  border: 0.5px solid var(--color-border-strong);
  font-size: 11px;
  font-weight: 500;
}

/* ------------------------------------------------------------
   CHIP — pill-shaped, dismissible variant of a tag. Use for
   interactive/removable selections (e.g. an active filter);
   use the existing .tag for static, non-removable labels.
   Remove control meets the WCAG 2.2 AA 24×24px minimum target
   size even though its visual icon is smaller.
   ------------------------------------------------------------ */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  background: var(--color-accent-tag-bg);
  color: var(--color-accent-400);
  border-radius: var(--radius-pill);
  padding-block: 4px;
  padding-inline: var(--space-3) 4px;
  font-size: 11px;
  font-weight: 500;
}

.chip__remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  min-height: 24px;
  border-radius: 50%;
  color: currentColor;
  background: transparent;
  transition: background var(--duration-fast) var(--ease-out);
}
.chip__remove:hover {
  background: rgba(255, 255, 255, 0.08);
}
.chip__remove svg {
  width: 10px;
  height: 10px;
}

/* ------------------------------------------------------------
   STATUS LABEL — inline dot + text status indicator. Distinct
   from .badge-* (a filled pill-of-color label used inside cards/
   tables) — this is the lightweight inline form used in running
   text or list rows. Text is always present; color is never the
   only signal.
   ------------------------------------------------------------ */
.status-label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 12px;
  font-weight: 500;
  color: var(--color-text-secondary);
}

.status-label__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-status-neutral);
  flex-shrink: 0;
}

.status-label--ok       { color: var(--color-status-ok); }
.status-label--warn     { color: var(--color-status-warn); }
.status-label--alert    { color: var(--color-status-alert); }
.status-label--accent   { color: var(--color-accent-400); }

.status-label--ok    .status-label__dot { background: var(--color-status-ok); }
.status-label--warn  .status-label__dot { background: var(--color-status-warn); }
.status-label--alert .status-label__dot { background: var(--color-status-alert); }
.status-label--accent .status-label__dot { background: var(--color-accent-500); }

/* ------------------------------------------------------------
   SECTION TITLE — the recurring eyebrow + heading + subcopy
   pattern used at the top of nearly every page section. Compose
   with the existing .eyebrow class above a .section-title block;
   not duplicated here.
   ------------------------------------------------------------ */
.section-title {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.section-title__heading {
  font-family: var(--font-display);
  font-size: var(--text-h2-size);
  font-weight: var(--text-h2-weight);
  letter-spacing: var(--text-h2-tracking);
  line-height: var(--text-h2-leading);
  color: var(--color-text-primary);
}

.section-title__subcopy {
  font-size: var(--text-body-lg-size);
  font-weight: var(--text-body-lg-weight);
  line-height: var(--text-body-lg-leading);
  color: var(--color-text-secondary);
  max-width: var(--max-width-text);
}

/* ------------------------------------------------------------
   DIVIDER — thematic break. Use the semantic <hr class="divider">
   rather than a styled <div>, so it carries the correct implicit
   role for assistive technology.
   ------------------------------------------------------------ */
.divider {
  border: 0;
  height: 1px;
  background: var(--color-border-default);
  margin-block: var(--space-8);
}
.divider--sm { margin-block: var(--space-4); }
.divider--lg { margin-block: var(--space-12); }

/* ============================================================
   MILESTONE 3.3 — CARD ELEMENTS
   Additive only. Reuses .card / .card-featured / .card-banner
   from Milestone 2 (unchanged) — this block adds the internal
   pieces (title, description, outcomes, meta, header, footer)
   and the Technology Badge List + Empty State Card variants.
   ============================================================ */

.card__title {
  font-family: var(--font-display);
  font-size: var(--text-h3-size);
  font-weight: var(--text-h3-weight);
  letter-spacing: var(--text-h3-tracking);
  line-height: var(--text-h3-leading);
  color: var(--color-text-primary);
}

.card__description {
  margin-top: var(--space-3);
  font-size: var(--text-body-lg-size);
  line-height: var(--text-body-lg-leading);
  color: var(--color-text-secondary);
}

.card__meta-text {
  margin-top: var(--space-2);
  font-size: 12px;
  color: var(--color-text-tertiary);
}

/* Header row pairing a title with a trailing badge (Lab/Cert cards) */
.card__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
}

/* Meta row of small accent badges under a featured card's title */
.card__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

/* Bullet-style outcomes list, marked with an accent dash rather
   than a default disc (list-style is already reset globally). */
.card__outcomes {
  margin-top: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.card__outcomes li {
  position: relative;
  padding-left: var(--space-4);
  font-size: var(--text-body-size);
  color: var(--color-text-secondary);
  line-height: var(--text-body-leading);
}
.card__outcomes li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 6px;
  height: 1px;
  background: var(--color-accent-500);
}

.card__body {
  padding: var(--space-6);
}

/* Card Footer — shared outbound-link row, used by Project and
   Featured Project cards, and (independently) by Certification
   cards for a single "Verify credential" link. */
.card__footer {
  margin-top: var(--space-6);
  padding-top: var(--space-4);
  border-top: 0.5px solid var(--color-border-subtle);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

.card__footer-link {
  font-size: 12px;
  font-weight: 500;
  color: var(--color-accent-400);
  transition: color var(--duration-fast) var(--ease-out);
}
.card__footer-link:hover {
  color: var(--color-accent-500);
}

/* Technology Badge List — row of .tag pills (list semantics for AT,
   visually a flex-wrap row with no bullets/list styling). */
.tech-badge-list {
  margin-top: var(--space-4);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* Empty State Card — shown in place of a card grid/list with no
   records yet (e.g. no in-progress certifications). Visually
   distinct from a populated card: dashed border, no hover state,
   centered text. */
.card--empty {
  border: 1px dashed var(--color-border-strong);
  border-radius: var(--radius-xl);
  padding: var(--space-12) var(--space-6);
  text-align: center;
  background: transparent;
}
.card--empty__text {
  font-size: var(--text-body-size);
  color: var(--color-text-tertiary);
}

/* ============================================================
   MILESTONE 3.4 — CONTENT COMPONENTS
   Additive only — nothing above this line was changed. Several
   of these (Timeline, Experience/Education Block, Skills Grid,
   Platform Statistics, Learning Path, FAQ Accordion, Code Block,
   Callout Box) have no visual treatment in the Design Specification
   (§7 only covers Nav/Buttons/Cards/Tags/Eyebrow/Zone Label/Forms/
   Table/Progress Bar/Footer). Built here extrapolating from the
   existing token language — flagged for your review the same way
   Milestone 3.2's Chip/Status Label/Pill were.
   Progress Bar's *base* track/fill classes already exist from
   Milestone 2 and are reused unmodified; only a labeled wrapper is
   added here.
   ============================================================ */

/* ------------------------------------------------------------
   TIMELINE (generic) — vertical connector used by Experience
   Block, Education Block, and (via its own composition) Learning
   Path. Not itself tied to any one content type.
   ------------------------------------------------------------ */
.timeline {
  display: flex;
  flex-direction: column;
}

.timeline__item {
  position: relative;
  padding-left: var(--space-8);
  padding-bottom: var(--space-8);
  margin-left: 6px;
  border-left: 1px solid var(--color-border-default);
}
.timeline__item:last-child {
  border-left-color: transparent;
  padding-bottom: 0;
}

.timeline__marker {
  position: absolute;
  left: -6.5px;
  top: 2px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--color-accent-500);
  border: 2px solid var(--color-bg-page);
}
.timeline__marker--ok      { background: var(--color-status-ok); }
.timeline__marker--warn    { background: var(--color-status-warn); }
.timeline__marker--neutral { background: var(--color-status-neutral); }

/* ------------------------------------------------------------
   EXPERIENCE BLOCK / EDUCATION BLOCK — content rendered inside a
   .timeline__item. Shared typography rules are grouped by comma
   rather than repeated.
   ------------------------------------------------------------ */
.experience-block__role,
.education-block__degree {
  font-family: var(--font-display);
  font-size: var(--text-h3-size);
  font-weight: var(--text-h3-weight);
  letter-spacing: var(--text-h3-tracking);
  line-height: var(--text-h3-leading);
  color: var(--color-text-primary);
}

.experience-block__org,
.education-block__institution {
  margin-top: var(--space-1);
  font-size: 13px;
  font-weight: 500;
  color: var(--color-accent-400);
}

.experience-block__dates,
.education-block__dates {
  margin-top: var(--space-1);
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--color-text-tertiary);
}

.experience-block__description,
.education-block__description {
  margin-top: var(--space-3);
  font-size: var(--text-body-lg-size);
  line-height: var(--text-body-lg-leading);
  color: var(--color-text-secondary);
}

/* Experience highlights reuse the existing dash-bullet list style
   from Card Elements (Milestone 3.3) rather than duplicating it —
   apply the .card__outcomes class directly in markup. */

/* ------------------------------------------------------------
   SKILLS GRID
   ------------------------------------------------------------ */
.skills-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
}
@media (min-width: 768px) {
  .skills-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .skills-grid { grid-template-columns: repeat(3, 1fr); }
}

.skills-grid__category {
  display: block;
  margin-bottom: var(--space-3);
  font-size: var(--text-label-size);
  font-weight: var(--text-label-weight);
  letter-spacing: var(--text-label-tracking);
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* Skill items reuse .tech-badge-list (Milestone 3.3) directly. */

/* ------------------------------------------------------------
   PLATFORM STATISTICS — wraps .card (Milestone 2, unchanged)
   ------------------------------------------------------------ */
.platform-stats__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.platform-stats__handle {
  font-size: 12px;
  color: var(--color-text-tertiary);
}

.platform-stats__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-4);
  text-align: center;
}

.platform-stats__value {
  font-family: var(--font-mono);
  font-size: var(--text-h2-size);
  font-weight: 600;
  color: var(--color-text-primary);
}

.platform-stats__label {
  margin-top: var(--space-1);
  font-size: var(--text-label-size);
  letter-spacing: var(--text-label-tracking);
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* ------------------------------------------------------------
   PROGRESS (labeled wrapper) — base .progress-track/.progress-fill
   are unchanged from Milestone 2; this adds the header row only.
   ------------------------------------------------------------ */
.progress__header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: var(--space-2);
}

.progress__label {
  font-size: 12px;
  color: var(--color-text-secondary);
}

.progress__percent {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--color-text-tertiary);
}

/* ------------------------------------------------------------
   FAQ ACCORDION — native <details>/<summary>, zero JS required;
   expand/collapse state and keyboard behavior are handled natively
   by the browser and exposed correctly to assistive technology.
   ------------------------------------------------------------ */
.faq-item {
  border-bottom: 0.5px solid var(--color-border-subtle);
}
.faq-item:last-child {
  border-bottom: none;
}

.faq-item__question {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding-block: var(--space-4);
  font-size: var(--text-body-lg-size);
  font-weight: 500;
  color: var(--color-text-primary);
  cursor: pointer;
  list-style: none;
}
.faq-item__question::-webkit-details-marker {
  display: none;
}
.faq-item__question::after {
  content: '';
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  border-right: 1.5px solid var(--color-text-tertiary);
  border-bottom: 1.5px solid var(--color-text-tertiary);
  transform: rotate(45deg);
  transition: transform var(--duration-fast) var(--ease-out);
}
.faq-item[open] .faq-item__question::after {
  transform: rotate(-135deg);
}

.faq-item__answer {
  padding-bottom: var(--space-4);
  font-size: var(--text-body-lg-size);
  line-height: var(--text-body-lg-leading);
  color: var(--color-text-secondary);
}

/* ------------------------------------------------------------
   CODE BLOCK
   ------------------------------------------------------------ */
.code-block {
  position: relative;
  background: var(--color-bg-input);
  border: 0.5px solid var(--color-border-strong);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  overflow-x: auto;
}
.code-block pre {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--text-mono-size);
  line-height: var(--text-mono-leading);
  color: var(--color-text-secondary);
  white-space: pre;
}
.code-block__copy {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
}

/* ------------------------------------------------------------
   RESUME SECTION — composite of Download row + Experience/
   Education timelines + Skills Grid (see render-resume.js).
   ------------------------------------------------------------ */
.resume-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
}

.resume-section__download-row {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
}

/* ------------------------------------------------------------
   CALLOUT BOX
   ------------------------------------------------------------ */
.callout {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-lg);
  border: 0.5px solid var(--color-border-strong);
  background: var(--color-bg-card);
  color: var(--color-text-secondary);
}
.callout__icon {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  color: currentColor;
}
.callout__content {
  font-size: var(--text-body-lg-size);
  line-height: var(--text-body-lg-leading);
}

.callout--info {
  border-color: var(--color-accent-500);
  background: var(--color-accent-bg);
}
.callout--info .callout__content { color: var(--color-accent-400); }

.callout--warning {
  border-color: var(--color-status-warn);
  background: var(--color-status-warn-bg);
}
.callout--warning .callout__content { color: var(--color-status-warn); }

.callout--danger {
  border-color: var(--color-status-alert);
  background: var(--color-status-alert-bg);
}
.callout--danger .callout__content { color: var(--color-status-alert); }

.callout--success {
  border-color: var(--color-status-ok);
  background: var(--color-status-ok-bg);
}
.callout--success .callout__content { color: var(--color-status-ok); }

/* ============================================================
   MILESTONE 3.5 — FORM COMPONENTS
   Additive only — nothing above this line was changed. Input/
   Textarea/Select base styles already exist from Milestone 2
   (.field input/textarea/select) and are reused unmodified below.
   No backend wiring — these are presentation + client-side
   validation only, per this milestone's explicit constraint.
   ============================================================ */

/* ------------------------------------------------------------
   CHECKBOX / RADIO — native inputs themed via `accent-color`
   rather than reconstructed with custom pseudo-elements. This
   keeps full native keyboard/AT semantics with minimal CSS.
   ------------------------------------------------------------ */
.checkbox,
.radio {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding-block: var(--space-1);
  font-size: 13px;
  color: var(--color-text-secondary);
  cursor: pointer;
}

.checkbox input[type="checkbox"],
.radio input[type="radio"] {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  accent-color: var(--color-accent-500);
  background: var(--color-bg-input);
  cursor: pointer;
}

/* ------------------------------------------------------------
   TOGGLE (switch) — native checkbox with role="switch" for
   correct assistive-technology naming, visually presented as a
   track + thumb. No JS required; state is driven entirely by
   the native :checked pseudo-class.
   ------------------------------------------------------------ */
.toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  cursor: pointer;
}

.toggle__input {
  position: absolute;
  width: 40px;
  height: 22px;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.toggle__track {
  position: relative;
  width: 40px;
  height: 22px;
  flex-shrink: 0;
  background: var(--color-bg-hover);
  border: 0.5px solid var(--color-border-strong);
  border-radius: var(--radius-pill);
  transition: background var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out);
}

.toggle__thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--color-text-secondary);
  transition: transform var(--duration-fast) var(--ease-out),
              background var(--duration-fast) var(--ease-out);
}

.toggle__input:checked + .toggle__track {
  background: var(--color-accent-bg);
  border-color: var(--color-accent-500);
}
.toggle__input:checked + .toggle__track .toggle__thumb {
  transform: translateX(18px);
  background: var(--color-accent-500);
}
.toggle__input:focus-visible + .toggle__track {
  outline: 2px solid var(--color-accent-500);
  outline-offset: 2px;
}

.toggle__label {
  font-size: 13px;
  color: var(--color-text-secondary);
}

/* ------------------------------------------------------------
   VALIDATION MESSAGE — paired with an input via aria-describedby
   and aria-invalid, wired in contact-form.js (not in CSS).
   ------------------------------------------------------------ */
.field--error input,
.field--error textarea,
.field--error select {
  border-color: var(--color-status-alert);
}

.field__message {
  display: block;
  margin-top: var(--space-2);
  font-size: 12px;
  color: var(--color-text-tertiary);
}
.field__message--error {
  color: var(--color-status-alert);
}

/* ------------------------------------------------------------
   BANNER — Success / Error, used for form submission feedback.
   Success uses role="status" (polite); Error uses role="alert"
   (assertive) — set in markup by render-form-feedback.js.
   ------------------------------------------------------------ */
.banner {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-lg);
  font-size: var(--text-body-lg-size);
  line-height: var(--text-body-lg-leading);
}

.banner--success {
  background: var(--color-status-ok-bg);
  border: 0.5px solid var(--color-status-ok);
  color: var(--color-status-ok);
}

.banner--error {
  background: var(--color-status-alert-bg);
  border: 0.5px solid var(--color-status-alert);
  color: var(--color-status-alert);
}

/* ------------------------------------------------------------
   LOADING SPINNER — used inside a submit button while a form
   submission is in flight. Under prefers-reduced-motion, the
   global base.css override already collapses this to a static
   ring (still visible as a loading indicator, just not spinning).
   ------------------------------------------------------------ */
.spinner {
  display: inline-block;
  width: 16px;
  height: 16px;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: var(--color-text-primary);
  border-radius: 50%;
  animation: spin 700ms linear infinite;
}
@keyframes spin {
  to { transform: rotate(360deg); }
}

/* ------------------------------------------------------------
   CONTACT FORM — layout wrapper only; fields inside reuse
   .field (Milestone 2) unmodified.
   ------------------------------------------------------------ */
.contact-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.contact-form__submit-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}