/*
  ============================================================
  FILE OVERVIEW: css/styles.css, the SHARED look and layout for every page of the site
  ============================================================
  It lives in the css folder; each page links it as "css/styles.css".
  All three pages (index.html, about.html, and projects.html) link this one
  file, so the whole site looks the same, and a style only has to be changed
  in one place. Rules for parts that are only on one page (like the skill
  cards on about.html) simply have nothing to style on the other pages.

  CSS (Cascading Style Sheets) controls how the page looks: colors,
  fonts, spacing, and layout. Each "rule" has two parts:
    - a selector (WHICH elements to style, e.g. "nav ul")
    - declarations inside { } (HOW to style them, e.g. "color: red;")
  Comments like this one, between slash-star and star-slash, are
  skipped by the browser. They're notes for whoever reads the code.

  Sections in this file, from top to bottom:
    1. Color palette (variables), with light and dark versions
    2. Base page setup (body, fonts, centering)
    3. Headings and text
    4. Header (clocks, name, tagline, photo)
   4b. Theme slide switch (top right)
    5. Navigation bar (flexbox), including the highlighted current-page link
    6. Main sections (spacing, and the open/close heading rows with arrows)
    7. Skills (grid, the level badge, the click-to-edit name, the skill count, and the filter buttons)
   7b. Skills Manager (with its level dropdown), project list, the red X delete buttons,
       and drag-to-reorder grips
    8. Contact form (inputs, focus states, buttons, character counts, red email)
    9. Footer
   10. Responsive layout: the @media block for screens 768px and wider
   11. Tablet tweaks: the @media block for screens 768px to 1023px only

  MOBILE FIRST: sections 1-9 style the page for phones. Sections 10 and 11
  at the very bottom adjust it for bigger screens, using two breakpoints:
    - under 768px          = phone   (sections 1-9 only)
    - 768px to 1023px      = tablet  (sections 1-9, plus 10, plus 11)
    - 1024px and wider     = desktop (sections 1-9, plus 10)

  About "rem": 1rem = the browser's base font size (usually 16px).
  Using rem for spacing means everything grows or shrinks together
  if someone raises their browser's text size.
*/


/* ===== 1. COLOR PALETTE =====
   :root means "the whole page." The names starting with -- are
   "custom properties" (variables): a color is defined once here and
   reused everywhere with var(--name). To change a color across the
   whole site, you only change it in this one spot.
   Three main colors are used, as planned, plus one "error" red that only
   appears to warn about a mistake (the email address while it isn't valid yet).
   color-scheme: light tells the browser to draw its own built-in parts
   (scrollbars, the dropdown menu, the checkbox) in their light style. */
:root {
  --color-background: #f7f6f3; /* warm off-white for the page background */
  --color-text: #1f2328;       /* near-black for body text (softer on the eyes than pure #000000) */
  --color-accent: #2f5d8a;     /* calm blue for headings, links, and highlights */
  --color-error: #b42318;      /* deep red for mistakes (easy to read on the light background) */
  color-scheme: light;

  /* SHADOW: used to make cards look slightly raised off the page.
     It isn't a fourth palette color. It's a see-through version of the near-black text color.
     rgb(31 35 40 / 0.08) = red 31, green 35, blue 40 (the same as #1f2328), at 8% strength.
     The two shadows are stacked: a tight one right under the card, and a wide soft one around it. */
  --shadow: 0 1px 2px rgb(31 35 40 / 0.08), 0 4px 12px rgb(31 35 40 / 0.08);
  /* A slightly stronger shadow, for when the mouse is over a skill card. */
  --shadow-hover: 0 2px 4px rgb(31 35 40 / 0.1), 0 8px 20px rgb(31 35 40 / 0.12);
}

/* DARK THEME: the same color names, given dark-mode values.
   :root[data-theme="dark"] means "the <html> element, but only when it has
   data-theme="dark"." main.js adds that when dark mode is chosen.
   Because every rule below uses var(--color-...), swapping these values
   recolors the whole page at once.
   The accent is a lighter blue here, because the original dark blue would be
   hard to read on a dark background. */
:root[data-theme="dark"] {
  --color-background: #1a1d21; /* deep charcoal (softer than pure black) */
  --color-text: #e6e4df;       /* warm off-white text */
  --color-accent: #8db8e3;     /* light blue for headings, links, and highlights */
  --color-error: #ff8a80;      /* soft coral red for mistakes (a deep red would be too dark to read here) */
  color-scheme: dark;

  /* Dark-mode shadows: stronger and fully dark (black at 35-50%), because a faint
     shadow disappears against a dark background. */
  --shadow: 0 1px 2px rgb(0 0 0 / 0.35), 0 4px 12px rgb(0 0 0 / 0.35);
  --shadow-hover: 0 2px 4px rgb(0 0 0 / 0.4), 0 8px 20px rgb(0 0 0 / 0.5);
}
/* ===== END OF COLOR PALETTE ===== */


/* ===== 2. BASE PAGE SETUP ===== */

/* Makes width and height include padding and borders. Without this, adding
   padding to a full-width input would make it wider than its container.
   The * means "every element," and ::before/::after cover the extra bits CSS can add. */
*,
*::before,
*::after {
  box-sizing: border-box;
}

/* The body is the whole visible page.
   - font-family: a "system font stack." system-ui uses the computer's own built-in
     font (Segoe UI on Windows, San Francisco on Mac). If that's unavailable, the
     browser tries the next name in the list, ending with any sans-serif font.
     Nothing is downloaded, so text appears instantly.
   - font-size uses clamp() so the text grows smoothly from 16px on a phone to 18px on
     a desktop, with no breakpoints. See "FLUID FONT SIZES" in section 3 for how it works.
   - line-height 1.6 = space between lines, 1.6 times the text size, for easy reading.
   - MOBILE FIRST: these are the PHONE settings. Larger screens change them in the
     "RESPONSIVE LAYOUT" section at the bottom of this file.
   - margin: 0 = no extra space around the page, so it uses the full phone width.
   - padding = slim breathing room inside the edges (1rem left/right) so text never
     touches the screen edge. The top is taller (3.75rem) so the theme slide switch,
     which is pinned to the top-right corner, doesn't sit on top of my name. */
body {
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: clamp(1rem, 0.93rem + 0.31vw, 1.125rem);
  line-height: 1.6;
  color: var(--color-text);
  background-color: var(--color-background);
  margin: 0;
  padding: 3.75rem 1rem 2rem;
}

/* SMOOTH SCROLLING: when a nav link is clicked, the page glides down to its section
   instead of jumping there instantly. "html" is the whole page, which is what scrolls. */
html {
  scroll-behavior: smooth;
}

/* For people who turned on "reduce motion" in their computer settings, go back to the
   instant jump, since a gliding page can make some people feel dizzy. */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

/* Images never grow wider than their container (important on small phone screens).
   height: auto keeps the picture's shape from getting squished. */
img {
  max-width: 100%;
  height: auto;
}
/* ===== END OF BASE PAGE SETUP ===== */


/* ===== 3. HEADINGS AND TEXT ===== */

/* FLUID FONT SIZES WITH clamp()
   Instead of jumping between fixed sizes at breakpoints, the main text sizes on this
   page grow smoothly as the screen gets wider. They use clamp(), which takes 3 values:

       clamp( SMALLEST , PREFERRED , LARGEST )

   - SMALLEST: the size never goes below this (used on small phones).
   - LARGEST:  the size never goes above this (used on big screens).
   - PREFERRED: the size in between, which changes with the screen width.
     It's written like "1.42rem + 2.47vw":
       * "vw" means "viewport width": 1vw = 1% of the browser window's width.
         So the vw part grows as the window gets wider.
       * The rem part is a fixed starting amount. Mixing rem in means the text
         still grows if someone turns up their browser's text size (an
         accessibility setting), which pure vw sizes would ignore.

   The numbers are worked out so each size is at its SMALLEST on a 375px-wide phone
   and reaches its LARGEST on a 1024px-wide screen, growing evenly in between:

       Text            Phone (375px)     Desktop (1024px and wider)
       Body text       1rem    (16px)    1.125rem (18px)
       My name (h1)    2rem    (32px)    3rem     (48px)
       Headings (h2)   1.375rem (22px)   1.75rem  (28px)
       Tagline         1.1rem  (17.6px)  1.3rem   (20.8px)
*/

/* All headings use the accent color and a tighter line-height
   (big text looks too spread out at 1.6). */
h1,
h2 {
  color: var(--color-accent);
  line-height: 1.2;
}

/* The page title (my name): large and bold, with no gap above it.
   Fluid size: 2rem on phones, growing smoothly to 3rem on desktops (see FLUID FONT SIZES above). */
h1 {
  font-size: clamp(2rem, 1.42rem + 2.47vw, 3rem);
  margin: 0 0 0.5rem;
}

/* Section headings. Each one sits inside its section's clickable heading row
   (see "OPEN/CLOSE SECTIONS" in section 6, which also draws the line underneath).
   margin: 0 removes the heading's built-in space, so it lines up with the arrow.
   Fluid size: 1.375rem on phones, growing smoothly to 1.75rem on desktops. */
h2 {
  font-size: clamp(1.375rem, 1.16rem + 0.92vw, 1.75rem);
  margin: 0;
}

/* Paragraphs: remove the default top gap and keep a gap below, so spacing is predictable. */
p {
  margin: 0 0 1rem;
}

/* Links use the accent color. */
a {
  color: var(--color-accent);
}
/* ===== END OF HEADINGS AND TEXT ===== */


/* ===== 4. HEADER (clocks, name, tagline, photo) ===== */

/* Centers everything in the header and adds space below it.
   container-type: inline-size lets the clocks rule below measure the header's own
   width (the same trick the nav uses), so the clocks can stack when space runs out. */
header {
  text-align: center;
  margin-bottom: 2rem;
  container-type: inline-size;
}

/* THE TWO CLOCKS: one line, centered, above my name.
   - display: flex puts the two clocks side by side.
   - justify-content: center keeps the pair in the middle; align-items: center lines
     them up with each other.
   - gap: 2rem of space between the two clocks keeps them clearly separate.
   - font-size 0.8rem keeps them small and quiet, so my name stays the main focus.
   - font-variant-numeric: tabular-nums gives every digit the same width, so the clocks
     don't wiggle sideways when the numbers change (a "1" is normally narrower than an "8").
   - opacity 0.85 softens them a little, like the tagline.
   This rule is more specific than "header p" (a class beats a plain tag), so the
   tagline's bigger font size doesn't apply here. */
.clocks {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 2rem;
  margin: 0 0 1rem;
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
  opacity: 0.85;
}

/* Each clock: its label sits above its time (flex-direction: column). */
.clock {
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* The small labels ("Local time" / "My time (PDT)"): in capital letters with a little
   extra spacing between letters, and in the accent color, so they read as labels. */
.clock-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-accent);
}

/* VERY NARROW SCREENS: when the header is under 20rem (320px) wide, the two clocks
   no longer fit side by side, so they stack (flex-direction: column), one above the other. */
@container (max-width: 20rem) {
  .clocks {
    flex-direction: column;
    gap: 0.4rem;
  }
}

/* The tagline: slightly larger and a little faded, so the name stands out more.
   "header p" means "only paragraphs inside the header."
   Fluid size: 1.1rem on phones, growing smoothly to 1.3rem on desktops. */
header p {
  font-size: clamp(1.1rem, 0.98rem + 0.49vw, 1.3rem);
  opacity: 0.8;
}

/* The profile photo: border-radius 50% turns the square into a circle,
   and the border adds an accent-colored ring around it. */
header img {
  border-radius: 50%;
  border: 4px solid var(--color-accent);
  margin-top: 0.5rem;
}
/* ===== END OF HEADER ===== */


/* ===== 4b. THEME SLIDE SWITCH (top right) ===== */

/* THE TRACK: the pill-shaped outline the knob slides along.
   - position: fixed pins it to the screen, so it stays in the top-right corner
     even while scrolling. top/right set how far it sits from those edges.
   - width/height plus border-radius 999px (a very large rounding) make a pill shape.
   - padding: 0 removes the built-in padding buttons have, so the pieces inside line up exactly.
   - z-index: 10 keeps it on top of any page content that scrolls underneath it.
   - It uses the page's own colors and a thin 1px outline, so it blends in quietly
     and switches along with the theme. */
#theme-toggle {
  position: fixed;
  top: 1rem;
  right: 1rem;
  z-index: 10;
  width: 3.25rem;
  height: 1.75rem;
  padding: 0;
  background-color: var(--color-background);
  border: 1px solid var(--color-accent);
  border-radius: 999px;
  cursor: pointer;
}

/* THE SUN AND MOON ICONS: both sit inside the track, one at each end.
   - position: absolute places each one at an exact spot inside the track
     (the track's own "position: fixed" makes it the reference point).
   - top: 50% plus translateY(-50%) centers them up-and-down.
   - width/height match the knob, so each icon sits exactly where the knob stops.
   - display: grid with place-items: center puts the emoji in the middle of that spot.
   - z-index: 1 keeps the icons on top of the knob, so the knob shows behind its icon.
   - opacity: 0.45 fades them, since the inactive one should stay in the background.
   - transition fades the brightness smoothly when the theme changes. */
.theme-icon {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 1;
  width: 1.375rem;
  height: 1.375rem;
  display: grid;
  place-items: center;
  font-size: 0.75rem;
  line-height: 1;
  opacity: 0.45;
  transition: opacity 0.2s ease;
}

/* The sun goes at the left end, the moon at the right end (0.125rem in from each edge). */
.theme-sun {
  left: 0.125rem;
}
.theme-moon {
  right: 0.125rem;
}

/* THE KNOB: the round marker that slides to the active side.
   - It starts on the left, behind the sun (light theme).
   - Its fill is a soft, see-through version of the accent color: color-mix blends
     30% accent with 70% transparent, so it's visible without being loud.
   - transition makes it glide over 0.2 seconds instead of jumping. */
.theme-knob {
  position: absolute;
  top: 50%;
  left: 0.125rem;
  transform: translateY(-50%);
  width: 1.375rem;
  height: 1.375rem;
  border-radius: 50%;
  background-color: color-mix(in srgb, var(--color-accent) 30%, transparent);
  transition: transform 0.2s ease;
}

/* LIGHT THEME (aria-checked="false"): the sun is the active icon, so it's shown at full strength.
   [aria-checked="false"] means "only when the switch has aria-checked set to false."
   main.js sets that value. */
#theme-toggle[aria-checked="false"] .theme-sun {
  opacity: 1;
}

/* DARK THEME (aria-checked="true"): the moon is shown at full strength, and the knob
   slides right by 1.5rem so it sits behind the moon.
   translate(1.5rem, -50%) = move 1.5rem to the right, and keep it centered up-and-down. */
#theme-toggle[aria-checked="true"] .theme-moon {
  opacity: 1;
}
#theme-toggle[aria-checked="true"] .theme-knob {
  transform: translate(1.5rem, -50%);
}

/* On hover, the outline gets a little thicker, so it's clear the switch reacts. */
#theme-toggle:hover {
  box-shadow: 0 0 0 1px var(--color-accent);
}

/* Keyboard focus ring (shown when someone reaches the switch with the Tab key). */
#theme-toggle:focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 3px;
}

/* For people who turned on "reduce motion" in their computer settings: the knob
   jumps straight to its new side instead of sliding. */
@media (prefers-reduced-motion: reduce) {
  .theme-knob,
  .theme-icon {
    transition: none;
  }
}
/* ===== END OF THEME SLIDE SWITCH ===== */


/* ===== 5. NAVIGATION (flexbox) ===== */

/* The nav bar, at the top of every page: thin lines above and below frame the links,
   with space around them.
   container-type: inline-size turns the nav into a "container": the rules below can
   then measure the NAV's own width (not the whole screen's) and react to it. That's
   what lets the links squeeze together and then stack at exactly the right moment. */
nav {
  border-top: 1px solid var(--color-accent);
  border-bottom: 1px solid var(--color-accent);
  padding: 0.75rem 0;
  margin-bottom: 3rem;
  container-type: inline-size;
}

/* The list of links, laid out with flexbox, in one horizontal row at every size
   (until the nav gets too narrow; see the next rule).
   - display: flex with flex-direction: row puts the links side by side.
   - justify-content: center keeps the row in the middle.
   - align-items: center lines the links up neatly across the row.
   - list-style: none removes the bullet points, and margin/padding 0 removes the
     default indent that lists have.
   - gap: the space between links SHRINKS SMOOTHLY as the nav gets narrower:
       clamp(0rem, 25cqi - 4.5rem, 1rem)
     * "cqi" = "container query inline": 1cqi = 1% of the nav's width.
     * So the middle value grows and shrinks with the nav's width. The numbers are
       worked out so the gap is a full 1rem (16px) when the nav is 352px wide or
       wider, then shrinks evenly to 0 at 288px wide.
     * clamp() keeps it between 0 (never negative) and 1rem (never bigger).
     Each link also has its own padding (see "nav a" below), so even at gap 0 the
     words still have a little breathing room and never touch. */
nav ul {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  gap: clamp(0rem, 25cqi - 4.5rem, 1rem);
  list-style: none;
  margin: 0;
  padding: 0;
}

/* WHEN THE LINKS NO LONGER FIT SIDE BY SIDE: stack them, one above the other.
   @container works like @media, but it checks the nav's width instead of the screen's.
   The four links need about 270px in a row, so once the nav is narrower than 18rem
   (288px), they're about to overlap. At that point they switch to a column
   (flex-direction: column), centered, with a small 0.5rem gap between them.
   On a phone with this page's side padding, that happens on screens about 320px wide or narrower. */
@container (max-width: 18rem) {
  nav ul {
    flex-direction: column;
    gap: 0.5rem;
  }
}

/* The nav links: normal weight, no underline, with a little padding so they're easier to tap.
   display: inline-grid is part of the "no shifting" trick explained just below. */
nav a {
  display: inline-grid;
  font-weight: 400;
  text-decoration: none;
  padding: 0.25rem 0.5rem;
}

/* THE "NO SHIFTING" TRICK: bold letters are wider than normal ones, so a word that turns
   bold on hover would get wider and push the other links sideways.
   To prevent that, ::after adds an invisible bold copy of the word (taken from the
   link's data-text in each page's HTML) underneath the real one.
   - content: attr(data-text) = use the data-text value as the copy's text.
   - visibility: hidden and height: 0 = the copy is invisible and takes no height,
     but it still takes up its full bold WIDTH.
   Because the link is an inline-grid, the real word and the copy share one column,
   which is always as wide as the bold version. So the link's width never changes. */
nav a::after {
  content: attr(data-text);
  font-weight: 700;
  visibility: hidden;
  height: 0;
  overflow: hidden;
}

/* When the mouse is over a link, or it's reached with the Tab key (:focus-visible),
   the word turns bold as a hint that it's clickable. No underline. */
nav a:hover,
nav a:focus-visible {
  font-weight: 700;
}

/* THE CURRENT PAGE'S LINK: highlighted so you can see which page you're on.
   Each page marks its own link with aria-current="page" in its HTML, and
   [aria-current="page"] means "only the link that has that."
   - It's filled with the accent color, with the text in the background color (like the
     active filter button), and bold.
   - border-radius rounds the corners of the filled area, so it looks like a soft tab.
   Its own bold version is already the width saved by the "no shifting" trick above,
   so the highlighted link doesn't push the others sideways. */
nav a[aria-current="page"] {
  font-weight: 700;
  color: var(--color-background);
  background-color: var(--color-accent);
  border-radius: 0.375rem;
}
/* ===== END OF NAVIGATION ===== */


/* ===== 6. MAIN SECTIONS ===== */

/* The page's sections. "main section" means "sections inside <main>."
   - margin-bottom: space below every section, so the headings don't crowd each other
     when the sections are closed.
   - scroll-margin-top: leaves 1.5rem of space above a section when a link jumps
     to it, so its heading doesn't sit pressed against the very top edge of the screen. */
main section {
  margin-bottom: 2rem;
  scroll-margin-top: 1.5rem;
}

/* OPEN/CLOSE SECTIONS
   Each section's content is inside a <details> box, and its heading row is the box's
   <summary>: the part that's always visible and opens or closes the box when clicked.

   THE HEADING ROW (summary):
   - display: flex puts the heading on the left and the arrow on the right;
     justify-content: space-between pushes them to opposite ends;
     align-items: center lines the arrow up with the middle of the heading.
   - list-style: none removes the browser's own small triangle marker, since we draw
     our own arrow. (::-webkit-details-marker below does the same for Safari.)
   - border-bottom draws the thin accent line under each heading.
   - cursor: pointer shows the "hand" mouse pointer, a hint that it's clickable. */
summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  list-style: none;
  padding-bottom: 0.5rem;
  border-bottom: 2px solid var(--color-accent);
  cursor: pointer;
}
summary::-webkit-details-marker {
  display: none;
}

/* While a box is open, leave space between its heading row and the content below.
   details[open] means "a <details> box that has the open attribute," and the ">"
   means "the summary directly inside it." */
details[open] > summary {
  margin-bottom: 1rem;
}

/* Keyboard focus ring for the heading row (when reached with the Tab key). */
summary:focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 4px;
  border-radius: 0.25rem;
}

/* THE ARROW: a small "v" shape drawn with CSS instead of an image.
   It's a tiny square showing only two of its borders (right and bottom), turned 45
   degrees with rotate(45deg), so the two borders form a downward-pointing arrow.
   - flex-shrink: 0 stops the arrow from being squeezed when the heading is long.
   - margin-right gives it a little room from the edge, since turning it makes it
     slightly wider than its box.
   - transition makes it turn smoothly (0.2 seconds) when the box opens or closes. */
.section-arrow {
  flex-shrink: 0;
  width: 0.6rem;
  height: 0.6rem;
  margin-right: 0.35rem;
  border-right: 2px solid var(--color-accent);
  border-bottom: 2px solid var(--color-accent);
  transform: rotate(45deg);
  transition: transform 0.2s ease;
}

/* When the box is open, the arrow flips to point up (rotate -135 degrees), as a hint
   that clicking again will close it. */
details[open] > summary .section-arrow {
  transform: rotate(-135deg);
}

/* For people who turned on "reduce motion": the arrow flips instantly. */
@media (prefers-reduced-motion: reduce) {
  .section-arrow {
    transition: none;
  }
}
/* ===== END OF MAIN SECTIONS ===== */


/* ===== 7. SKILLS (grid) ===== */

/* The skills list, laid out with CSS grid. "#skills ul" means "the list inside the
   element with id="skills"" (the # means id).
   - display: grid arranges the items into rows and columns.
   - grid-template-columns: 1fr = one column that fills the full width ("1fr" = one
     equal share of the space). These are the PHONE settings (mobile first), so the
     skills sit in a single column, one card per row. The "RESPONSIVE LAYOUT" section
     at the bottom of this file adds more columns on larger screens.
   - gap: space between the boxes, both across and down.
   - list-style/padding: remove the bullets and default indent. */
#skills ul {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Each skill becomes a small raised card (main.js builds these from its "skills" array):
   an accent-colored outline, rounded corners, padding inside, and centered text.
   - display: flex with flex-direction: column stacks the skill's name above its level
     badge, and align-items: center centers them; gap puts a little space between.
   - position: relative lets the grip handle and the red X delete button (section 7b) sit in
     the card's top corners, and the extra left/right padding (2.5rem) keeps the text clear of
     them while staying centered.
   - box-shadow uses the --shadow value from the palette section to lift it off the page.
   - transition makes the hover change below happen smoothly over 0.2 seconds instead of jumping. */
#skills li {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  border: 1px solid var(--color-accent);
  border-radius: 0.5rem;
  padding: 1rem 2.5rem;
  text-align: center;
  font-weight: 500;
  box-shadow: var(--shadow);
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}

/* THE LEVEL BADGE under each skill's name ("learning", "practicing", or "confident").
   A small pill shape: tiny capital letters with a little letter spacing, in the accent
   color, inside a rounded outline (border-radius: 999px rounds the ends fully).
   The three levels look different, so they can be told apart at a glance. Each card's
   data-level (set by main.js) picks the look. [data-level="learning"] means "a card
   whose data-level is learning." The badges get more "filled in" as the level goes up: */
.skill-level {
  padding: 0.1rem 0.6rem;
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-accent);
  border: 1px solid var(--color-accent);
  border-radius: 999px;
}

/* Learning: a dashed outline, like something still being sketched in. */
#skills li[data-level="learning"] .skill-level {
  border-style: dashed;
}

/* Practicing: the plain solid outline from the rule above (nothing to change). */

/* Confident: filled in with the accent color, with the text in the background color. */
#skills li[data-level="confident"] .skill-level {
  background-color: var(--color-accent);
  color: var(--color-background);
}

/* THE CLICKABLE SKILL NAME (main.js makes it a button, so it can be clicked to edit).
   It's styled to look like the plain text it replaced: no button border or background,
   the page's font and text color (inherit = "use the same as the card").
   cursor: text shows the I-shaped "typing" pointer, a hint that the text can be edited. */
.skill-name {
  padding: 0.1rem 0.35rem;
  font: inherit;
  color: inherit;
  background: transparent;
  border: none;
  border-radius: 0.25rem;
  cursor: text;
}

/* On hover, a dotted underline appears under the name, as a hint that it's clickable. */
.skill-name:hover {
  text-decoration: underline dotted;
  text-underline-offset: 0.2em;
}

/* Keyboard focus ring for the name (Tab to it, then press Enter to edit). */
.skill-name:focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 2px;
}

/* THE EDIT BOX that replaces the name while it's being edited. It's centered like the
   name, uses the page's font and colors, and has an accent outline so it's clearly a
   box you're typing in. width: 100% lets it use the card's full width (minus its padding). */
.skill-name-input {
  width: 100%;
  padding: 0.25rem 0.5rem;
  font: inherit;
  text-align: center;
  color: var(--color-text);
  background-color: var(--color-background);
  border: 1px solid var(--color-accent);
  border-radius: 0.375rem;
}

/* Focus ring for the edit box, matching the form boxes. */
.skill-name-input:focus {
  outline: 3px solid var(--color-accent);
  outline-offset: 2px;
}

/* THE SKILL COUNT in the heading, e.g. the "(2/5)" in "Skills (2/5)" (shown/total): bold,
   matching the word "Skills" (font-weight 700 = bold). */
#skill-count {
  font-weight: 700;
}

/* THE FILTER BUTTONS (All, Learning, Practicing, Confident) above the skills list.
   - display: flex puts them in a row; flex-wrap: wrap lets them move onto a second line
     on narrow phone screens; gap spaces them evenly.
   - margin-bottom leaves space between the buttons and the skill cards. */
.skill-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1rem;
}

/* Each filter button: a small pill (border-radius 999px rounds the ends fully), outlined
   in the accent color, with see-through background. cursor: pointer shows the "hand". */
.filter-button {
  padding: 0.35rem 0.95rem;
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--color-accent);
  background: transparent;
  border: 1px solid var(--color-accent);
  border-radius: 999px;
  cursor: pointer;
}

/* On hover, a faint accent tint shows the button reacts. color-mix blends 15% accent
   with transparent, for a very light fill. */
.filter-button:hover {
  background-color: color-mix(in srgb, var(--color-accent) 15%, transparent);
}

/* THE ACTIVE FILTER: filled with the accent color, with the text in the background color,
   so it clearly stands out from the others. [aria-pressed="true"] means "the button whose
   aria-pressed is true" (main.js sets that on the clicked button). This rule comes after
   the hover rule, so the active button keeps its full color even with the mouse over it. */
.filter-button[aria-pressed="true"] {
  background-color: var(--color-accent);
  color: var(--color-background);
}

/* Keyboard focus ring for the filter buttons. */
.filter-button:focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 2px;
}

/* WHEN A FILTER MATCHES NO SKILLS (for example "Learning" when every skill is confident),
   show a note that says so, instead of the "No skills yet" note (section 7b). main.js
   puts the active filter on the list as data-filter, so this applies to every filter
   except "all". It's more specific than the "No skills yet" rule, so it wins. */
#skill-list:not([data-filter="all"]):not(:has(li))::before {
  content: "No skills at this level yet.";
}

/* When the mouse is over a skill card OR a project card, it rises a little:
   translateY(-2px) moves it up 2 pixels, and the shadow grows to match.
   The comma means "this rule applies to both," so the two kinds of card always
   move the same way. (The project cards are styled in section 7b.) */
#skills li:hover,
.project-list li:hover {
  box-shadow: var(--shadow-hover);
  transform: translateY(-2px);
}

/* Some people turn on "reduce motion" in their computer settings because movement
   bothers them. This media query respects that, for both kinds of card: no sliding,
   just the shadow change. */
@media (prefers-reduced-motion: reduce) {
  #skills li,
  .project-list li {
    transition: none;
  }
  #skills li:hover,
  .project-list li:hover {
    transform: none;
  }
}
/* ===== END OF SKILLS ===== */


/* ===== 7b. SKILLS MANAGER, PROJECTS, DELETE BUTTONS, AND DRAG GRIPS ===== */

/* THE TWO "ADD" FORMS (Skills Manager and Add a project). They already get the card look
   (border, rounded corners, shadow) from the general "form" rule in section 8.
   This adds space below them, so they stand apart from the list underneath. */
.manager {
  margin-bottom: 1.5rem;
}

/* Each add form's small heading ("Skills Manager", "Add a project"):
   smaller than the section heading, in the accent color. */
.manager h3 {
  margin: 0 0 1rem;
  font-size: 1.1rem;
  color: var(--color-accent);
}

/* NAME AND DESCRIPTION SIDE BY SIDE (the project form).
   - display: flex puts the two boxes next to each other.
   - flex-wrap: wrap lets the description move under the name when there isn't room
     (on phones).
   - Each box starts at 12rem wide (flex-basis) and grows to share the spare room;
     flex-grow: 2 on the description gives it twice as much spare room as the name,
     since descriptions are longer.
   - The bottom-margin rule makes sure both boxes keep the same space underneath,
     even though one of them is the last paragraph in its row (section 8 removes the
     space under a form's last paragraph). */
.field-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0 1rem;
}
.field-row p {
  flex: 1 1 12rem;
  min-width: 0;
}
.field-row p:last-child {
  flex-grow: 2;
}

/* In the Skills Manager it's the other way around: the skill name box (first) gets the
   extra room, and the short Level dropdown (last) stays narrower. */
#skill-form .field-row p:first-child {
  flex-grow: 2;
}
#skill-form .field-row p:last-child {
  flex-grow: 1;
}
.manager .field-row p {
  margin-bottom: 1.25rem;
}

/* THE PROJECTS LIST: one card per project, stacked with a 1rem gap.
   list-style/margin/padding remove the bullets and default indent. */
.project-list {
  display: grid;
  gap: 1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Each project card: styled the same way as the skill cards (section 7): accent outline,
   rounded corners, the same soft shadow, and the same smooth rise-and-bigger-shadow on
   hover (that hover rule is shared with the skill cards in section 7).
   - position: relative lets the grip handle and delete button sit in its top corners.
   - The extra left and right padding (2.75rem) keeps the text from running under them.
   - transition makes the hover rise happen smoothly over 0.2 seconds, like the skill cards. */
.project-list li {
  position: relative;
  padding: 1rem 2.75rem;
  border: 1px solid var(--color-accent);
  border-radius: 0.5rem;
  box-shadow: var(--shadow);
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}

/* The project's name in bold, on its own line (display: block), above the description. */
.project-list strong {
  display: block;
  margin-bottom: 0.25rem;
}

/* The description: no extra space under it, so the card ends evenly. */
.project-list p {
  margin: 0;
}

/* A project's screenshot (from the images folder), under its description.
   - display: block puts it on its own line, and width: 100% with height: auto makes it
     fill the card's width while keeping its shape.
   - margin-top leaves a little space under the description.
   - The thin accent border and rounded corners frame it like the cards themselves. */
.project-list img {
  display: block;
  width: 100%;
  height: auto;
  margin-top: 0.75rem;
  border: 1px solid var(--color-accent);
  border-radius: 0.375rem;
}

/* EMPTY LISTS: when every item has been deleted, show a short note instead of nothing.
   :has(li) means "contains a list item," so :not(:has(li)) means "has no items left."
   ::before adds text from CSS (content: "...") at the start of the list. */
#skill-list:not(:has(li))::before {
  content: "No skills yet. Add one above.";
  opacity: 0.7;
}
.project-list:not(:has(li))::before {
  content: "No projects yet. Add one above.";
  opacity: 0.7;
}

/* THE RED X DELETE BUTTON on every skill and project.
   The button shows the "✗" character (added by main.js) in the error red, with no
   border or background, so only the X itself is visible.
   - position: absolute with top/right pins it to the card's top-right corner.
   - width/height make a small square to click (1.75rem, about 28px).
   - display: grid with place-items: center puts the X in the middle of that square.
   - font-size makes the X a bit bigger than the text around it.
   - color comes from --color-error, so it's deep red in light mode and soft coral in dark.
   - transition makes the hover effect below happen smoothly. */
.delete-button {
  position: absolute;
  top: 0.35rem;
  right: 0.35rem;
  width: 1.75rem;
  height: 1.75rem;
  display: grid;
  place-items: center;
  padding: 0;
  font: inherit;
  font-size: 1.3rem;
  font-weight: 700;
  line-height: 1;
  color: var(--color-error);
  background: transparent;
  border: none;
  border-radius: 0.25rem;
  cursor: pointer;
  transition: transform 0.15s ease;
}

/* On hover, the X grows a little (scale 1.2) and tilts slightly (rotate 8 degrees),
   a playful "this will delete it" signal. */
.delete-button:hover {
  transform: scale(1.2) rotate(8deg);
}

/* Keyboard focus ring (shown when the button is reached with the Tab key). */
.delete-button:focus-visible {
  outline: 3px solid var(--color-error);
  outline-offset: 1px;
}

/* For people who turned on "reduce motion": no grow-and-tilt on hover. */
@media (prefers-reduced-motion: reduce) {
  .delete-button {
    transition: none;
  }
  .delete-button:hover {
    transform: none;
  }
}
/* THE GRIP HANDLE ("⠿", added by main.js) in each card's top-left corner, used to drag
   the card into a new order. It mirrors the delete button in the opposite corner.
   - cursor: grab shows an open-hand mouse pointer, a hint that it can be picked up.
   - touch-action: none tells phones and tablets that a finger pressing the grip is
     dragging the card, not scrolling the page. It's only on the small grip, so swiping
     anywhere else on the page still scrolls normally.
   - opacity 0.7 keeps it quiet until the mouse is over it. */
.drag-handle {
  position: absolute;
  top: 0.35rem;
  left: 0.35rem;
  width: 1.75rem;
  height: 1.75rem;
  display: grid;
  place-items: center;
  padding: 0;
  font: inherit;
  font-size: 1.1rem;
  line-height: 1;
  color: var(--color-accent);
  background: transparent;
  border: none;
  border-radius: 0.25rem;
  cursor: grab;
  touch-action: none;
  opacity: 0.7;
}

/* On hover the grip shows at full strength. */
.drag-handle:hover {
  opacity: 1;
}

/* Keyboard focus ring for the grip (where the arrow keys move the card). */
.drag-handle:focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 1px;
  opacity: 1;
}

/* THE CARD BEING DRAGGED: see-through, with a dashed outline, so it's clear which card
   is moving. (main.js adds the "dragging" class while the card is held.) */
.dragging {
  opacity: 0.55;
  outline: 2px dashed var(--color-accent);
  outline-offset: 2px;
}

/* WHILE ANY DRAG IS HAPPENING (main.js puts "is-dragging" on the <html> element):
   - the mouse pointer is a closed "grabbing" hand everywhere on the page, and
   - user-select: none stops text on the page from getting highlighted by accident. */
.is-dragging,
.is-dragging * {
  cursor: grabbing;
  user-select: none;
}
/* ===== END OF SKILLS MANAGER, PROJECTS, DELETE BUTTONS, AND DRAG GRIPS ===== */


/* ===== 8. CONTACT FORM ===== */

/* Each field's paragraph gets space below it, so the fields don't feel cramped. */
form p {
  margin-bottom: 1.25rem;
}

/* The whole form becomes one raised card: padding inside so the fields
   don't touch the edges, a thin border, rounded corners, and the same soft
   shadow as the skill cards. */
form {
  padding: 1.75rem;
  border: 1px solid var(--color-accent);
  border-radius: 0.75rem;
  box-shadow: var(--shadow);
}

/* Removes the extra gap under the last row (the buttons), so the space at the
   bottom of the card matches the space at the top. */
form p:last-child {
  margin-bottom: 0;
}

/* Labels sit on their own line above their field (display: block), in bold. */
form label {
  display: block;
  font-weight: 600;
  margin-bottom: 0.4rem;
}

/* The text boxes, dropdown, and message box.
   input[type="text"] means "inputs whose type is text," and so on.
   The checkbox isn't in this list on purpose, because a full-width checkbox would look wrong.
   - width: 100% = full width of the form.
   - padding = comfortable space inside the box around the text.
   - font: inherit = use the page's font (form fields don't do this by default).
   - border / border-radius = a thin outline with slightly rounded corners. */
form input[type="text"],
form input[type="email"],
form input[type="tel"],
form select,
form textarea {
  width: 100%;
  padding: 0.75rem 1rem;
  font: inherit;
  color: var(--color-text);
  background-color: var(--color-background);
  border: 1px solid var(--color-text);
  border-radius: 0.375rem;
}

/* The message box:
   - resize: vertical lets it be made taller or shorter, but not wider (which would break the layout).
   - display: block removes a small built-in gap that browsers leave under a textarea
     (they treat it like a word sitting on a line of text, with room left for letters like
     "g" and "y" that hang below the line). Without this, its character count would sit
     lower than the counts under the other boxes. */
form textarea {
  resize: vertical;
  display: block;
}

/* Placeholder hint text: faded, so it's clearly a hint and not something already typed.
   opacity 0.65 is as faded as it can be while staying easy to read: it keeps a contrast
   ratio of at least 4.5 to 1 against the background in both themes (4.8 in light mode,
   6.3 in dark), which is the readability guideline for normal-size text. */
form textarea::placeholder {
  color: var(--color-text);
  opacity: 0.65;
}

/* CHARACTER COUNTS: the small numbers under each text box, on the right side.
   - display: block puts each counter on its own line, right under its box.
   - text-align: right lines it up with the box's right edge.
   - font-variant-numeric: tabular-nums gives every digit the same width, so the
     number doesn't wiggle as it changes.
   - opacity 0.7 keeps it quiet but still readable (contrast stays above 4.5 to 1). */
.char-count {
  display: block;
  margin-top: 0.25rem;
  text-align: right;
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  opacity: 0.7;
}

/* RED EMAIL TEXT: while the email box holds something that isn't a proper email address
   yet, its text is red. :invalid means "a form box whose current value breaks its rules"
   (here, type="email" plus the pattern in index.html's contact form). As soon as the address is complete,
   e.g. name@example.com, it's no longer :invalid and the text goes back to normal.
   An empty box technically counts as :invalid too (it's required), but with no text in it
   there's nothing to turn red.
   #email (an id) is more specific than the "form input[type="email"]" rule above, so
   this color wins. */
#email:invalid {
  color: var(--color-error);
}

/* FOCUS STATES: what a field looks like when it's active (clicked into, or reached
   with the Tab key). A clear focus state shows people, especially keyboard users,
   exactly where they are in the form.
   - border-color switches to the accent color.
   - outline draws a thick accent ring around the box, and outline-offset leaves a
     small gap between the box and the ring. */
form input:focus,
form select:focus,
form textarea:focus {
  border-color: var(--color-accent);
  outline: 3px solid var(--color-accent);
  outline-offset: 2px;
}

/* The checkbox row: the label sits next to the box on the same line (display: inline),
   in normal weight, instead of on its own line like the other labels.
   input[type="checkbox"] + label means "the label right after a checkbox." */
form input[type="checkbox"] + label {
  display: inline;
  font-weight: normal;
  margin-left: 0.4rem;
}

/* Makes the checkbox a bit bigger and colors its tick mark with the accent color. */
form input[type="checkbox"] {
  width: 1.1rem;
  height: 1.1rem;
  accent-color: var(--color-accent);
  vertical-align: middle;
}

/* Both buttons: shared size, font, and shape.
   cursor: pointer shows the "hand" mouse pointer, a hint that it's clickable. */
form button {
  font: inherit;
  font-weight: 600;
  padding: 0.75rem 1.5rem;
  border: 2px solid var(--color-accent);
  border-radius: 0.375rem;
  cursor: pointer;
}

/* "Send message" is the main action, so it's a solid accent-colored button. */
form button[type="submit"] {
  background-color: var(--color-accent);
  color: var(--color-background);
  margin-right: 0.75rem;
}

/* "Reset" is a secondary action, so it's only outlined. Making it look less important
   lowers the chance someone clicks it by mistake and loses what they typed. */
form button[type="reset"] {
  background-color: transparent;
  color: var(--color-accent);
}

/* When the mouse is over a button, it fades slightly to show it will react. */
form button:hover {
  opacity: 0.85;
}

/* Keyboard focus ring for buttons and links. :focus-visible only shows the ring when
   someone uses the keyboard (Tab key), not on every mouse click. */
form button:focus-visible,
a:focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 3px;
}
/* ===== END OF CONTACT FORM ===== */


/* ===== 9. FOOTER ===== */

/* The footer: a thin line above it, centered smaller text, and space to separate it from the content. */
footer {
  border-top: 1px solid var(--color-accent);
  margin-top: 3rem;
  padding-top: 1.5rem;
  text-align: center;
  font-size: 0.9rem;
  opacity: 0.8;
}
/* ===== END OF FOOTER ===== */


/* ===== 10. RESPONSIVE LAYOUT: TABLETS AND DESKTOPS (768px and wider) =====
   This file is written "MOBILE FIRST": every rule above is the PHONE version of the
   page. This block then changes a few things for bigger screens.

   @media (min-width: 768px) is a "media query." The rules inside it only apply when
   the browser window is at least 768 pixels wide (about the width of a tablet held
   upright). Below 768px, the browser ignores this whole block and the phone styles
   above are used as-is.

   Because this block comes LAST in the file, its rules win over the matching
   phone rules above them (in CSS, when two rules conflict, the later one wins). */
@media (min-width: 768px) {

  /* PAGE WIDTH: re-centers the page in a comfortable reading column.
     - max-width 65ch = never wider than about 65 characters ("ch" = the width of the
       "0" character), so lines don't get too long to read comfortably.
     - margin: 0 auto = "auto" on the left and right splits the leftover space evenly,
       which centers the page horizontally.
     - padding = roomier edges than on phones (3rem top/bottom, 1.5rem left/right). */
  body {
    max-width: 65ch;
    margin: 0 auto;
    padding: 3rem 1.5rem;
  }

  /* SKILLS: from one column to as many as fit (2-3 on a tablet or computer).
     repeat(auto-fit, minmax(12rem, 1fr)) means: make as many columns as will fit,
     where each column is at least 12rem wide and they share the leftover space
     equally. */
  #skills ul {
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  }
}
/* ===== END OF RESPONSIVE LAYOUT ===== */


/* ===== 11. TABLET TWEAKS (768px to 1023px only) =====
   The second breakpoint is at 1024px. Tablets get everything from section 10 (the
   centered page and the skills grid), plus the touch-friendly tweaks below.
   At 1024px and wider (laptops and desktops, usually used with a mouse), this block
   switches off again.

   "(min-width: 768px) and (max-width: 1023px)" means BOTH must be true: the window is
   at least 768px wide AND at most 1023px wide. That range is "tablet size."

   Why these tweaks: tablets are tapped with a finger, which is much less precise than
   a mouse pointer. A common guideline is that anything tappable should be at least
   44px (2.75rem) tall, so these rules give the small controls more room. */
@media (min-width: 768px) and (max-width: 1023px) {

  /* NAV LINKS: bigger tap areas. More padding around each word makes the clickable
     area larger, and the gap shrinks a little to keep the row about the same width. */
  nav ul {
    gap: 0.5rem;
  }
  nav a {
    padding: 0.625rem 1rem;
  }

  /* FORM FIELDS: a minimum height of 3rem (48px) makes each box an easy target for a
     finger. min-height means "at least this tall," so the message box can still be taller. */
  form input[type="text"],
  form input[type="email"],
  form input[type="tel"],
  form select,
  form textarea {
    min-height: 3rem;
  }

  /* CHECKBOX: a bigger box that's easier to tick with a finger. */
  form input[type="checkbox"] {
    width: 1.4rem;
    height: 1.4rem;
  }

  /* THEME SLIDE SWITCH: 20% bigger, so it's easier to tap.
     scale(1.2) enlarges it, and transform-origin: top right makes it grow from its
     top-right corner, so it stays tucked into the same corner instead of drifting. */
  #theme-toggle {
    transform: scale(1.2);
    transform-origin: top right;
  }
}
/* ===== END OF TABLET TWEAKS ===== */
