/*
 * refine.css — editorial polish layer.
 *
 * Loaded after styles.css, brand.css and role-fix.css. It handles four
 * things the earlier layers left open: display headings that ran to five
 * or six lines, unjustified body copy, project titles sitting flush
 * against their kicker, and the tools table still wearing the old palette.
 */

/* ============================================================
   1. Display headings
   ============================================================ */

/*
 * The headings were sized for a poster, not a page: "Research software
 * built around honest evidence." broke over six lines. Every display
 * size below is reduced and given a slightly looser leading, which reads
 * better once the type is no longer enormous.
 */

/*
 * The name runs on one line, in the body colour rather than the terracotta
 * accent, and is sized to fit the hero column without breaking.
 */
.hero-copy h1 {
  margin: 0.7rem 0 1.6rem;
  color: var(--text);
  /*
   * The page stops widening at 1440px but a raw vw does not, so above that
   * the name outgrew its grid track and ran under the portrait. The cap is
   * set from the widest the hero-copy column ever gets.
   */
  font-size: clamp(1.6rem, 5vw, 3.7rem);
  letter-spacing: -0.035em;
  line-height: 1.06;
  white-space: nowrap;
}

.hero-copy h1 span {
  color: inherit;
}

/*
 * brand.css paints these accent labels #a94f35, but its own
 * `main.content p` rule is more specific and repaints every one of them
 * that happens to be a paragraph. That is why "COMPANY FOCUS" and
 * "CURRENTLY" were terracotta (they are spans) while "COMPUTATIONAL
 * BIOLOGIST" and the section indices came out muted grey. Restore the
 * accent with enough specificity to survive.
 */
main.content p.eyebrow,
main.content p.section-index,
main.content p.company,
main.content p.proof-label,
main.content p.overview-lede + p.section-index,
.portfolio-home p.eyebrow,
.portfolio-page p.eyebrow,
.portfolio-home p.section-index,
.portfolio-page p.section-index,
.portfolio-page p.company,
.portfolio-home p.proof-label,
.portfolio-page p.proof-label {
  color: #a94f35;
}

.current-role h2 {
  max-width: 22ch;
  margin: 0.7rem 0 2.5rem;
  font-size: clamp(2rem, 3.1vw, 3rem);
  letter-spacing: -0.03em;
  line-height: 1.06;
}

.section-heading h2 {
  max-width: 26ch;
  font-size: clamp(2rem, 3.5vw, 3.4rem);
  letter-spacing: -0.03em;
  line-height: 1.08;
  text-wrap: balance;
}

.contact-panel h2 {
  max-width: 28ch;
  font-size: clamp(2rem, 3.6vw, 3.5rem);
  letter-spacing: -0.03em;
  line-height: 1.08;
  text-wrap: balance;
}

.compact-contact h2 {
  font-size: clamp(1.85rem, 3vw, 2.85rem);
}

.page-hero {
  padding-bottom: 4.5rem;
}

.page-hero h1 {
  max-width: 24ch;
  margin: 0.5rem 0 1.5rem;
  font-size: clamp(2.5rem, 4.8vw, 4.4rem);
  letter-spacing: -0.03em;
  line-height: 1.06;
  text-wrap: balance;
}

.about-intro h2 {
  font-size: clamp(1.85rem, 2.9vw, 2.8rem);
  line-height: 1.1;
}

.showcase-copy h2 {
  margin: 0 0 0.55rem;
  font-size: clamp(1.9rem, 3.1vw, 3rem);
  letter-spacing: -0.03em;
  line-height: 1.1;
}

.overview-title {
  font-size: clamp(1.6rem, 2.3vw, 2.15rem);
}

.timeline-item h3 {
  font-size: clamp(1.2rem, 1.8vw, 1.65rem);
}

/* These were the only role headings still set in the sans face. */
.experience-content h3,
.capability-list h3,
.education-grid h3 {
  font-family: var(--editorial);
  font-weight: 500;
}

.experience-content h3 {
  margin-bottom: 0.85rem;
  font-size: clamp(1.25rem, 2vw, 1.75rem);
}

.experience-content > p:not(.company) {
  max-width: 860px;
}

.capability-list h3 {
  font-size: 1.08rem;
}

.expertise-grid h3 {
  font-size: 1.32rem;
}

.expertise-grid article {
  min-height: 0;
}

.quarto-title-block .quarto-title > h1 {
  font-size: clamp(2.3rem, 4.4vw, 3.9rem);
  letter-spacing: -0.03em;
  line-height: 1.06;
}

/* The heading column no longer needs two thirds of the row. */
.section-heading {
  grid-template-columns: minmax(0, 1.15fr) minmax(260px, 0.85fr);
  gap: 2rem 5rem;
  margin-bottom: clamp(2.75rem, 5vw, 4.5rem);
}

.section-shell {
  padding-top: clamp(5rem, 8vw, 8rem);
}

@media (max-width: 820px) {
  /* The hero drops to one column here, so the name gets nearly the full
     page width. Sized off the viewport so it stays on one line. */
  .hero-copy h1 {
    font-size: clamp(1.5rem, 9.5vw, 4.5rem);
  }

  .section-heading h2,
  .contact-panel h2,
  .page-hero h1 {
    max-width: none;
  }
}

@media (max-width: 620px) {
  .current-role h2 {
    font-size: clamp(1.8rem, 8vw, 2.5rem);
  }

  .section-heading h2 {
    font-size: clamp(1.85rem, 8.5vw, 2.6rem);
  }

  .contact-panel h2 {
    font-size: clamp(1.85rem, 8.5vw, 2.6rem);
  }

  .page-hero h1 {
    font-size: clamp(1.95rem, 9vw, 2.7rem);
  }
}

/* ============================================================
   2. Justified body copy
   ============================================================ */

/*
 * Justification is applied to running prose only. Labels, mono eyebrows,
 * pills, stats and buttons keep their own alignment, since justifying a
 * two-word label does nothing but stretch it.
 *
 * Hyphenation is deliberately off. It closes the word gaps that
 * justification opens, but it broke words mid-line ("thera-peutics",
 * "pur-suing"), and a word split across two lines is harder to read than a
 * slightly looser line.
 */

.portfolio-home p,
.portfolio-page p,
.portfolio-home li,
.portfolio-page li,
main.content p,
main.content li,
.role-summary,
.hero-lead,
.proof-note,
blockquote p {
  hyphens: manual;
  overflow-wrap: break-word;
  text-align: justify;
  text-justify: inter-word;
}

/*
 * Below tablet widths the measure is too short to justify: without
 * hyphenation the gaps grow wide enough to pull the eye down the column
 * instead of along the line. Ragged right reads better there.
 */
@media (max-width: 900px) {
  .portfolio-home p,
  .portfolio-page p,
  .portfolio-home li,
  .portfolio-page li,
  main.content p,
  main.content li,
  .role-summary,
  .hero-lead,
  .proof-note,
  blockquote p {
    text-align: left;
  }
}

.eyebrow,
.section-index,
.fact-label,
.proof-label,
.company,
.project-kicker,
.availability-line,
.status-pill,
.tag-list,
.tag-list span,
.skill-tags,
.skill-tags li,
.metric-row,
.metric-row span,
.mini-facts,
.mini-facts span,
.timeline-date,
.timeline-place,
.proof-stat,
.proof-stat span,
.button,
.button-row,
.card-links,
.card-links a,
.text-link,
.capability-list p,
.education-grid p,
.education-grid span,
.portrait-wrap figcaption,
.nav-footer p,
.overview-table thead th,
.overview-table tbody th,
.overview-table tbody td,
.field-cell,
.publication-list li,
.publication-list span {
  hyphens: manual;
  text-align: left;
}

/*
 * Last-line orphans are the usual cost of justification. Slightly longer
 * measures and a touch more leading keep the rag under control.
 */
.portfolio-home p,
.portfolio-page p,
main.content p {
  line-height: 1.72;
}

/* ============================================================
   2b. Quarto's paragraph wrapper
   ============================================================ */

/*
 * Quarto wraps loose inline HTML in a paragraph. Where that HTML is the
 * whole content of a flex or grid container, the container ends up with a
 * single <p> child and its layout collapses: the eight metric rows stacked
 * into one 133px column instead of three, and the card links and button
 * rows lost their gaps, so "Case study" and "GitHub" ran together.
 *
 * display: contents removes the wrapper from the box tree and hands the
 * children back to the container as its own flex or grid items. It only
 * fires where the wrapper exists, so the markup stays valid either way.
 */
.metric-row > p,
.card-links > p,
.button-row > p,
.mini-facts > p,
.tag-list > p,
.role-list > p,
.skill-tags > p,
.role-facts > div > p,
.timeline-item > p,
.proof-stat > p {
  display: contents;
}

/* ============================================================
   3. Project titles and their kickers
   ============================================================ */

/*
 * The title sat directly on top of its uppercase kicker with no gap at
 * all. The topline above it also carried far more space than it needed,
 * so the whole title block now sits higher in the card.
 */

.card-topline {
  margin-bottom: clamp(1.4rem, 2.4vw, 2.1rem);
}

.project-card h3 {
  margin: 0 0 0.7rem;
  line-height: 1.2;
}

.project-card .project-kicker,
.showcase-copy .project-kicker {
  margin: 0 0 1.25rem;
  line-height: 1.5;
}

.showcase-copy h2 + .project-kicker {
  margin-top: 0.65rem;
}

.project-card > p:not(.project-kicker) {
  margin-top: 0;
}

.project-card,
.project-card-featured {
  min-height: 0;
}

.showcase-copy .card-topline {
  margin-bottom: clamp(1.2rem, 2vw, 1.8rem);
}

/* ============================================================
   4. Tools table
   ============================================================ */

/*
 * The palette variables are remapped in brand.css; these rules tune the
 * few places where the table needs its own value rather than a shared
 * one — the field column against the row hover, and the header band.
 */

.overview-table-wrap {
  border-color: var(--hairline);
}

.overview-table thead th {
  background: #efe6d8;
  color: #7e402f;
}

.field-cell {
  background: #f3ece0;
  color: #7e402f;
}

.overview-row:hover td {
  background: rgba(201, 101, 69, 0.055);
}

.overview-row:hover .field-cell {
  background: #efe4d4;
}

.skill-tags li {
  background: rgba(255, 255, 255, 0.55);
  border-color: var(--hairline);
  color: #5d574f;
}

.overview-row:hover .skill-tags li {
  border-color: rgba(201, 101, 69, 0.42);
  background: #fffdf8;
}

.tool-name::after {
  background: var(--signal);
}

.overview-table tbody th,
.overview-table tbody td,
.overview-table tbody tr:last-child th,
.overview-table tbody tr:last-child td {
  border-color: var(--hairline);
}

@media (max-width: 900px) {
  .overview-row::before {
    background: #f0e1d5;
    color: #7e402f;
  }
}

/* ============================================================
   5. Current-role card: company focus
   ============================================================ */

/*
 * "Antibody therapeutics for oncology and autoimmunity" kept collapsing
 * into a narrow ragged column: the label track ate the width, and balanced
 * wrapping then evened the lines out rather than letting the text run. The
 * value now sits under its own label and uses the full width of the panel,
 * exactly like the Role row below it, so it reads across instead of down.
 */

.current-role .role-facts > .company-focus {
  display: block;
  padding: 1.25rem 0 1.4rem;
}

.current-role .company-focus .fact-label {
  display: block;
  margin: 0 0 0.55rem;
  padding: 0;
}

.current-role .company-focus strong {
  display: block;
  width: 100%;
  max-width: none;
  font-size: 0.98rem;
  line-height: 1.5;
  hyphens: manual;
  text-wrap: wrap;
  white-space: normal !important;
}

/*
 * Stack the contract-period row too, so the date sits under its label the
 * same way Company focus and Role do, rather than beside it. role-fix.css
 * sets a two-column track outside any media query and wins on load order,
 * so the block display has to be reasserted here.
 */
.current-role .role-facts > div:first-child {
  display: block;
  padding: 1.25rem 0 1.4rem;
}

.current-role .role-facts > div:first-child .fact-label {
  display: block;
  margin: 0 0 0.55rem;
  padding: 0;
  white-space: nowrap;
}

.current-role .role-facts > div:first-child strong {
  display: block;
  font-size: 0.98rem;
  line-height: 1.5;
  white-space: nowrap;
}

/* ============================================================
   6. Portraits
   ============================================================ */

/* The homepage shows the speaking photograph, already cropped to the 3:4
   frame so the browser does not have to crop it again. */
.portrait-photo {
  background-image: url("assets/Rafael_Soler_Ortuno_speaking.webp") !important;
  background-position: center center !important;
  /* The lecture-room photograph is already flat, so the desaturation the
     studio portrait needed washes it out. */
  filter: saturate(0.95) contrast(1.06);
}

/* The experience page takes over the studio portrait. */
.about-photo {
  background-image: url("assets/Rafael_Soler_Ortuno_portrait.webp");
  background-position: center 20%;
}

/* ============================================================
   7. General polish
   ============================================================ */

.hero-personal {
  max-width: 640px;
  color: var(--muted);
  font-size: 0.97rem;
  line-height: 1.75;
}

.project-showcase {
  padding: clamp(2.5rem, 4.5vw, 4rem) 0;
}

.check-list li {
  line-height: 1.65;
}

.experience-content ul {
  gap: 0.75rem;
}

.experience-entry {
  padding: 2.25rem 0;
}

.publication-list a {
  font-size: 1.02rem;
}

/*
 * A word-shaped value such as NOT SUPPORTED does not fit the 90px numeric
 * column, so it wrapped and left its caption stranded halfway down. Wide
 * values stack instead.
 */
.proof-stat.proof-stat-wide {
  grid-template-columns: minmax(0, 1fr);
  gap: 0.4rem;
}

.proof-stat.proof-stat-wide strong {
  font-size: 1.45rem;
  letter-spacing: -0.01em;
  line-height: 1.15;
}

/* Manuscripts in preparation have no DOI to link, so the title is a span.
   It should still read as a title rather than as metadata. */
.publication-list li {
  grid-template-columns: 82px minmax(0, 1fr) 150px;
}

.publication-list .publication-title {
  color: var(--text);
  font-family: var(--editorial);
  font-size: 1.02rem;
  font-weight: 500;
}

.publication-list .publication-year {
  white-space: nowrap;
}

.timeline-item {
  padding: 1.9rem 0;
}

.contact-panel {
  margin-top: clamp(5rem, 9vw, 8rem);
  padding: clamp(2.75rem, 6vw, 5.5rem);
}

.current-role::after {
  font-size: clamp(4.5rem, 11vw, 10rem);
}

/* ============================================================
   8. Mobile
   ============================================================

   Desktop is unchanged: everything below is inside a media query.

   Three problems were found by measuring the built pages at 320-480px.
   Two were self-inflicted: the .section-heading and .publication-list
   tracks defined above sit outside any media query and were overriding
   the stacking that brand.css and styles.css already did, so the heading
   column collapsed to 0px and the publication title column to 3px. The
   third is type: the mono micro-labels bottom out near 10px, which is
   too small to read on a phone. */

@media (max-width: 820px) {
  /* Restore the single column these headings are meant to take. */
  .section-heading {
    grid-template-columns: minmax(0, 1fr);
    gap: 1.1rem;
  }

  .section-heading > p {
    max-width: 62ch;
  }
}

@media (max-width: 820px) {
  /* Year, title and journal each get the full width instead of being
     squeezed into a 150px sidebar and whatever is left. */
  .publication-list li {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.25rem;
    padding: 1.1rem 0;
  }

  .publication-list .publication-year {
    font-weight: 700;
  }

  /* Micro-type. Root is 17px here, so 0.62rem was 10.5px. */
  .status-pill {
    font-size: 0.76rem;
  }

  .tag-list span {
    font-size: 0.76rem;
  }

  .skill-tags li {
    font-size: 0.78rem;
  }

  .card-links a,
  .text-link {
    font-size: 0.78rem;
  }

  .button {
    font-size: 0.78rem;
  }

  .project-kicker {
    font-size: 0.76rem;
  }

  .eyebrow,
  .section-index,
  .fact-label,
  .proof-label,
  .company {
    font-size: 0.76rem;
  }

  .availability-line {
    font-size: 0.76rem;
    letter-spacing: 0.03em;
  }

  .metric-row span {
    font-size: 0.8rem;
  }

  .proof-note {
    font-size: 0.84rem;
  }

  .experience-meta {
    font-size: 0.82rem;
  }

  .mini-facts span,
  .education-grid span,
  .education-grid p,
  .capability-list p,
  .publication-list span {
    font-size: 0.84rem;
  }

  .portrait-wrap figcaption {
    font-size: 0.78rem;
  }

  .portrait-wrap figcaption span {
    font-size: 0.72rem;
  }

  .nav-footer {
    font-size: 0.76rem;
  }

  main.content code {
    font-size: 0.82rem;
  }
}

@media (max-width: 430px) {
  /* Three metric columns leave about 85px each, too narrow for a label
     like "real-project validation run". Two columns read better. */
  .metric-row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.9rem 0.75rem;
  }
}

/* ============================================================
   9. The homepage summary table on small screens
   ============================================================ */

/*
 * Below 900px the tools table stops being a table and becomes one card
 * per tool. On the homepage that repeats what the project cards below it
 * already say, so the same eight tools are read twice in a row.
 *
 * Scoped to .tools-overview-compact, which only the homepage copy carries;
 * the Tools page keeps its table in card form, since there it is the
 * content rather than a summary. Above 900px nothing changes anywhere.
 */
@media (max-width: 900px) {
  .tools-overview-compact {
    display: none;
  }
}

/* ============================================================
   10. Expertise keywords under each experience role
   ============================================================ */

/*
 * A row of keyword pills under each job title, in the same rounded-pill
 * shape as the project tags but tinted with the site's terracotta accent so
 * they read as a distinct band rather than blending into the body text.
 */
.role-keywords {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0 0 1.3rem;
}

.role-keywords span {
  padding: 0.34rem 0.74rem;
  border: 1px solid rgba(201, 101, 69, 0.28);
  border-radius: 999px;
  background: rgba(201, 101, 69, 0.08);
  color: #8a4632;
  font-family: var(--humanist);
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: 0.01em;
}

/* Sits close under the title, so tighten the gap the h3 leaves. */
.experience-content h3 {
  margin-bottom: 0.6rem;
}

@media (max-width: 820px) {
  .role-keywords span {
    font-size: 0.78rem;
  }
}

/* ============================================================
   11. Hero lead and personal line
   ============================================================ */

/* Both a touch smaller than before; the personal line goes italic. */
.hero-lead {
  font-size: clamp(1rem, 1.35vw, 1.14rem);
  line-height: 1.62;
}

.hero-personal {
  font-size: 0.9rem;
  font-style: italic;
  line-height: 1.7;
}
