/* Shared card base */
.card {
  padding: 16px 20px;
  border: 1px solid var(--surface1);
  border-radius: 6px;
  transition: border-color 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease;
}

@media (hover: hover) {
  .card:hover {
    border-color: var(--surface2);
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  }
}

/* Education */
.edu-entry {
  margin-bottom: 24px;
}

.edu-entry .degree {
  color: var(--blue);
  font-weight: 600;
  margin-bottom: 4px;
}

.edu-entry .school {
  color: var(--yellow);
}

.edu-entry .year {
  color: var(--overlay1);
  font-size: 0.85rem;
}

.edu-entry .detail {
  color: var(--subtext0);
  font-size: 0.9rem;
  margin-top: 8px;
  padding-left: 16px;
  border-left: 2px solid var(--surface0);
  line-height: 1.6;
}

/* Experience - card style */
.history-entry {
  margin-bottom: 24px;
}

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

.history-content .role {
  color: var(--green);
  font-weight: 600;
  font-size: 1.0rem;
}

.history-content .company {
  color: var(--peach);
}

.history-content .period {
  color: var(--overlay1);
  font-size: 0.85rem;
  margin-top: 2px;
}

/* Reading measure. These paragraphs previously had no cap at all, so they ran
   the full width of the frame at ~94 characters per line. Comfortable is
   45-75. The cap lives on the text, never on the frame, so the layout around
   it stays free to use the full width. */
.history-content .desc {
  color: var(--subtext0);
  font-size: 0.9rem;
  line-height: 1.9;
  margin-top: 2px;
  max-width: 72ch;
}

/* Bullets hang: the marker (dash plus icon) sits in the indent and every
   wrapped line lines up under the first word, not under the dash. Without the
   hang, a two-line bullet has its continuation starting in the same column as
   the next bullet's marker, which is what made the list hard to scan.

   Keyed off the marker itself, not off :not(.sub-head): the undisclosed role
   is a plain paragraph with no dash, and giving it a hanging indent pulled its
   first line 2.9em left of the rest of itself. */
.history-content .desc:has(.desc-dash) {
  padding-left: 2.9em;
  text-indent: -2.9em;
}

/* A marker, not content: dimmer than the text it introduces. */
.desc-dash {
  color: var(--overlay0);
}

/* A single capped text column inside a 1052px card left 400px of void, which
   reads as a layout bug rather than as whitespace. The bullet lines flow into
   two columns instead, so the card fills the frame AND each line stays about
   56 characters -- shorter than it was before the frame was widened.

   Only the <div> blocks of bullets flow. Every DIRECT <p> child (the role
   line, the date, and the "Technical Contributions" style sub-headings) spans
   both columns, which also means an entry made only of direct paragraphs --
   the undisclosed role -- stays a single column with no special-casing. */
@media (min-width: 900px) {
  .history-content {
    columns: 2;
    column-gap: 44px;
  }

  /* An entry with no bullets is a single running sentence, and splitting a
     sentence into two columns forces the reader down the left half and back up
     to the right, which is worse than any amount of empty space. Those entries
     stay one continuous column; they still fill the card because the 72ch cap
     is lifted below. */
  .history-content:not(:has(.desc-dash)) {
    columns: initial;
  }

  /* Spanning is for the HEADINGS only: the role line, the date, and the
     "Technical Contributions" style sub-heads. A lone description paragraph
     used to span too, which meant it kept its 72ch cap at full card width and
     left ~390px of void beside it. It now flows into the columns like
     everything else. */
  .history-content > p:not(.desc),
  .history-content > p.sub-head { column-span: all; }

  /* The column is the measure now, so the 72ch cap would only re-introduce a
     void inside each column. */
  .history-content .desc:not(.sub-head) { max-width: none; }

  /* Bullets must not split across the column break: half a bullet at the foot
     of one column and half at the head of the next reads as two bullets. A
     lone paragraph is deliberately NOT in this rule -- it is allowed to flow
     across both columns, which is the only way it fills the card. */
  .history-content div .desc { break-inside: avoid; }
}

/* CTF scoreboard */
.ctf-board {
  border: 1px solid var(--surface1);
  border-radius: 6px;
  overflow: hidden;
}

.ctf-row {
  display: flex;
  justify-content: space-between;
  padding: 10px 16px;
  border-bottom: 1px solid var(--surface0);
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  transition: background 0.2s ease;
}

@media (hover: hover) {
  .ctf-row:hover {
    background: color-mix(in srgb, var(--surface0) 50%, transparent);
  }
}

.ctf-row:last-child {
  border-bottom: none;
}

.ctf-row:nth-child(odd) {
  background: color-mix(in srgb, var(--surface0) 30%, transparent);
}

.ctf-platform {
  color: var(--blue);
  font-weight: 600;
  min-width: 140px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.ctf-rank {
  color: var(--yellow);
}

.ctf-badge {
  padding: 2px 10px;
  border-radius: 4px;
  font-size: 0.8rem;
  font-weight: 600;
}

/* Only the variants the markup uses. gold (yellow) and peach existed too,
   unreferenced; add a colour back here the day a badge needs it. */
.ctf-badge.green { background: color-mix(in srgb, var(--green) 15%, transparent); color: var(--green); }
.ctf-badge.blue { background: color-mix(in srgb, var(--blue) 15%, transparent); color: var(--blue); }

/* Certifications - clear style */
.cert-entry {
  margin-bottom: 16px;
  padding: 12px 16px;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  flex-wrap: wrap;
}

.cert-info {
  flex: 1;
  min-width: 0;
}

.cert-name {
  color: var(--blue);
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 8px;
}

.cert-name .icon {
  color: var(--blue);
}

/* 96ch, not the 72ch used for long-form text. These are one or two line
   blurbs, and the return-sweep cost of a long line is paid per line break --
   it barely registers over two lines, while a 72ch cap inside a full-width
   card strands the Verified badge on its own out at the right edge. */
.cert-full {
  color: var(--text);
  font-size: 0.9rem;
  margin-top: 2px;
  max-width: 96ch;
}

.cert-issuer {
  color: var(--overlay1);
  font-size: 0.78rem;
  margin-top: 4px;
}

.cert-verified {
  color: var(--green);
  font-size: 0.78rem;
  font-weight: 600;
  white-space: nowrap;
  display: flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
  padding-top: 2px;
}

.cert-verified .icon {
  color: var(--green);
  width: 14px;
  height: 14px;
}

/* Conferences */
.conf-entry {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 0;
  border-bottom: 1px solid var(--surface0);
}
.conf-entry:last-child { border-bottom: none; }
.conf-name {
  color: var(--text);
  font-weight: 600;
}
.conf-detail {
  color: var(--subtext1);
  font-size: 0.88rem;
}

/* Testimonials - PR review style */
.review-comment {
  border: 1px solid var(--surface1);
  border-radius: 8px;
  margin-bottom: 20px;
  overflow: hidden;
}

.review-header {
  background: var(--surface0);
  padding: 10px 16px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 0.85rem;
}

.review-author {
  color: var(--blue);
  font-weight: 600;
}

.review-badge {
  color: var(--green);
  font-size: 0.75rem;
  padding: 2px 8px;
  border: 1px solid var(--green);
  border-radius: 12px;
}

.review-body {
  padding: 16px;
  color: var(--subtext1);
  font-size: 0.9rem;
  line-height: 1.8;
}

.review-role {
  color: var(--overlay1);
  font-size: 0.82rem;
  margin-top: 8px;
}

/* Contact */
.contact-row {
  display: flex;
  gap: 12px;
  margin: 6px 0;
  align-items: baseline;
}

.contact-label {
  color: var(--pink);
  min-width: 120px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.contact-value a {
  color: var(--blue);
  position: relative;
}

.contact-value a::after {
  content: '';
  position: absolute;
  bottom: -2px;
  left: 0;
  width: 0;
  height: 1px;
  background: var(--lavender);
  transition: width 0.3s ease;
}

.contact-value a:hover {
  text-decoration: none;
}

.contact-value a:hover::after {
  width: 100%;
}

/* About Me */
.about-layout {
  display: flex;
  gap: 24px;
  align-items: flex-start;
}

.about-avatar {
  border-radius: 50%;
  flex-shrink: 0;
}

/* 90ch, not the 72ch used for long-form text: this is a three-line intro sitting
   beside the avatar, and the return-sweep cost of a longer line is paid per
   break. Three breaks do not justify leaving 326px of the card empty. */
.about-text {
  color: var(--subtext1);
  font-size: 0.9rem;
  line-height: 1.8;
  max-width: 90ch;
}

/* NOT `.flag`: that class already means a command-line flag in the prompt
   lines (`--group-directories-first`), and sizing those to 1.15em with a ring
   around them mangles three prompts elsewhere on the page.

   Inline SVG rather than the regional-indicator emoji: on Windows those render
   as the bare letters "FR" and "GB" in a box, and a CV is read on Windows more
   often than not. The hairline ring keeps the white band of the French flag
   from dissolving into a light background. */
.lang-flag {
  width: 1.15em;
  height: auto;
  vertical-align: -0.16em;
  border-radius: 1px;
  box-shadow: 0 0 0 1px var(--surface1);
  margin: 0 1px;
}

.noscript-hero {
  padding: 24px 0;
}

.noscript-hero p {
  margin: 8px 0;
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .section { opacity: 1; transform: none; }
  .section .stagger { opacity: 1; transform: none; }
  #hero-typing .line { opacity: 1; }
  .scroll-progress { transition: none; }
  html { scroll-behavior: auto; }
}

/* Personal interests ──────────────────────────────────────────
   Split layout: what I do on the left, what I read on the right. The real
   division in this content is doing versus reading, so the layout says that
   rather than treating six unlike things as one long list. Chosen from five
   options; the rest are archived in docs/design-previews/hobbies-options.html. */

/* Accent per row, set once and read by the icon and the name. Scoped to this
   section so the short names cannot collide with anything else on the page,
   the way an unscoped `.flag` already did once. */
.hobbies-split .c-peach  { --c: var(--peach); }
.hobbies-split .c-teal   { --c: var(--teal); }
.hobbies-split .c-mauve  { --c: var(--mauve); }
.hobbies-split .c-green  { --c: var(--green); }
.hobbies-split .c-yellow { --c: var(--yellow); }

.hobbies-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 26px;
}

@media (min-width: 900px) {
  .hobbies-split {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 0 44px;
  }
}

.hob-list {
  list-style: none;
  display: grid;
  gap: 14px;
  align-content: start;
}

/* Two columns: a fixed one for the icon so the names line up, and the rest for
   the text. The detail line starts in the text column, not under the icon. */
.hob-row {
  display: grid;
  grid-template-columns: 1.4em minmax(0, 1fr);
  gap: 2px 10px;
  align-items: start;
}

.hob-icon { color: var(--c); line-height: 1.7; }
.hob-name { color: var(--c); font-weight: 600; font-size: 0.9rem; }

.hob-detail {
  grid-column: 2;
  color: var(--subtext0);
  font-size: 0.83rem;
}

/* The rule is a divider between the two halves, so it belongs to the right
   half and disappears with it when the layout stacks. */
.hob-reading { padding-top: 2px; }

@media (min-width: 900px) {
  .hob-reading {
    border-left: 1px solid var(--surface0);
    padding-left: 44px;
    margin-left: -44px;
  }
}

@media (max-width: 899px) {
  .hob-reading {
    border-top: 1px solid var(--surface0);
    padding-top: 22px;
  }
}

.hob-head {
  color: var(--c);
  font-weight: 600;
  font-size: 0.9rem;
  display: flex;
  align-items: center;
  gap: 8px;
}

.hob-genre {
  color: var(--overlay1);
  font-size: 0.8rem;
  margin-top: 3px;
}

.hob-books {
  list-style: none;
  margin-top: 10px;
  font-size: 0.84rem;
  display: grid;
  gap: 3px;
}

/* Title left, author right, so the authors form their own column instead of
   trailing each title at a different position. */
.hob-books li {
  display: flex;
  justify-content: space-between;
  gap: 14px;
}

.hob-books .bk-title { color: var(--text); }
.hob-books .bk-author { color: var(--overlay1); }

/* The panel lists five titles; /reading has 73. Written as the command that
   page actually runs, so the link reads as continuing the `cat ~/hobbies.yml`
   session rather than as a button bolted onto it. --c comes from the .c-yellow
   on .hob-reading, so the verb picks up the panel's own accent. */
.hob-more {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  margin-top: 14px;
  font-size: 0.8rem;
  text-decoration: none;
}

.hob-more-cmd  { color: var(--c); }
.hob-more-arg  { color: var(--subtext0); }
.hob-more-hint { color: var(--overlay0); }

.hob-more-caret {
  width: 13px;
  height: 13px;
  color: var(--c);
  align-self: center;
  transition: transform 0.2s ease;
}

@media (hover: hover) {
  .hob-more:hover .hob-more-arg { color: var(--text); }
  .hob-more:hover .hob-more-caret { transform: translateX(3px); }
}
