/* Professional profile.
 *
 * Layered on top of business-profile.css rather than replacing it: the header,
 * footer, theme tokens and typography are shared, and a second full stylesheet
 * would drift from the first the first time a token changed.
 *
 * Every value here is a --biz-* token from that sheet. A literal colour would
 * be a light surface on a dark page the moment somebody switches theme.
 */

/* The palette, taken from the mockup rather than chosen.
 *
 * Sampled from documents/Copy-Shop-Create-App-Flow/Blog-Mockups/mockup.png:
 * a light grey ground at 65% of the pixels, near-black text, and an indigo
 * accent at 6%. The business template's warm cream and crimson is a different
 * product's identity -- a practice is not a shop, and the surface should not
 * say it is.
 *
 * Overriding the --biz-* tokens rather than writing new ones: the shared
 * header, footer and cards all read them, so the whole page moves together and
 * a profile's own accent_color still wins where it is set.
 */
.professional-profile-view {
  --biz-ground: #f0f0f2;
  --biz-surface: #ffffff;
  --biz-ink: #1c1c22;
  --biz-body: #55555f;
  --biz-line: #dedee4;
  --biz-accent: var(--business-accent, #6060b0);

  /* The two bands the mockup breaks the page with. */
  --prof-band: #afaad4;
  --prof-band-ink: #16161c;
  --prof-dark: #26262c;
  --prof-dark-ink: #f0eff8;
}

.professional-main {
  max-width: var(--biz-measure);
  margin: 0 auto;
  padding: 0 1.25rem 4rem;
}

/* Hero: portrait beside the name, stacking on a phone.
 *
 * The portrait is second in the markup so a screen reader and a narrow screen
 * both reach the name first -- who this is matters before what they look like.
 */
/* Phone first: the name and a small portrait share the top row, the stats span
   the full width underneath.

   Stacking the portrait below the stats put a photograph between the reader
   and the first real content of the page, and it was the last thing on a
   screen where it should have been among the first -- a masthead identifies
   the page, and an identity that arrives after six statistics is not doing
   that. */
.professional-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 1.5rem;
  /* Top-aligned, not centred.
     Centring is right when the two columns are a similar height. Six stats
     made the text column half again as tall as the portrait, so the photo
     floated in the middle of its own column with empty space above and below
     it and nothing in the row lined up with anything else. Aligned to the
     start, the portrait begins on the same line as the name. */
  align-items: start;
  padding: 3.5rem 0 2.5rem;
}

.professional-hero-text {
  grid-column: 1;
  grid-row: 1;
}

.professional-hero .professional-badges {
  grid-column: 1 / -1;
  grid-row: 2;
}

.professional-hero .professional-portrait {
  grid-column: 2;
  grid-row: 1;
}

/* Desktop: the portrait takes a column of its own and stands beside both the
   name and the stats, so it no longer has to be small enough to sit next to a
   heading. */
@media (min-width: 860px) {
  .professional-hero {
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
    gap: 3rem;
  }

  .professional-hero .professional-badges {
    grid-column: 1;
  }

  .professional-hero .professional-portrait {
    grid-row: 1 / span 2;
  }
}

.professional-eyebrow {
  margin: 0 0 0.75rem;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--biz-accent);
}

.professional-hero h1 {
  margin: 0;
  line-height: 1.1;
  color: var(--biz-ink);
}

/* Credentials sit with the name but must not compete with it: they are an
 * qualifier, and a physician's page reading "MD FRCPC" as loudly as their own
 * name gets the emphasis backwards. */
.professional-credentials {
  display: block;
  margin-top: 0.5rem;
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--biz-body);
}

.professional-lede {
  margin: 1.25rem 0 0;
  font-size: 1.125rem;
  line-height: 1.6;
  color: var(--biz-body);
}

.professional-hero-actions {
  margin: 1.75rem 0 0;
}

.professional-cta {
  display: inline-block;
  padding: 0.85rem 1.5rem;
  border-radius: var(--biz-radius);
  background: var(--biz-accent);
  color: var(--biz-surface);
  font-weight: 600;
  text-decoration: none;
}

.professional-cta:hover,
.professional-cta:focus-visible {
  filter: brightness(0.94);
}

/* Two columns, fixed, rather than as many as happen to fit.
   Flex sized every badge to its own label, so "25 Publications" and "28
   Conference presentations" started at different places and the numbers under
   them lined up with nothing.

   `auto-fit` fixed the alignment but not the count: the number of columns then
   depended on how wide the hero's text column happened to be, which depends on
   the length of the bio above it. Six stats came out in a single column half a
   screen tall. Two is a deliberate choice -- it holds a label as long as
   "Conference presentations" without wrapping to three lines, and it puts an
   even six into a tidy three rows. */
.professional-badges {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.5rem 2rem;
  margin: 2rem 0 0;
  padding: 0;
  list-style: none;
}

.professional-badges li {
  display: flex;
  flex-direction: column;
}

.professional-badges strong {
  font-size: 1.5rem;
  line-height: 1.1;
  color: var(--biz-ink);
}

.professional-badges span {
  margin-top: 0.25rem;
  font-size: 0.8125rem;
  color: var(--biz-body);
}

.professional-portrait {
  width: 100%;
  max-width: 340px;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: var(--biz-radius);
  box-shadow: var(--biz-shadow);
  justify-self: center;
}

.professional-portrait-initials {
  display: grid;
  place-items: center;
  background: var(--biz-ink);
  color: var(--biz-surface);
  font-size: 5rem;
  font-weight: 600;
}

.professional-section {
  padding: 2.5rem 0;
  border-top: 1px solid var(--biz-line);
}

.professional-section h2 {
  margin: 0 0 1.5rem;
  color: var(--biz-ink);
}

.professional-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  gap: 1.25rem;
}

/* A story page's cards are paragraphs of an argument, read in the order the
 * author put them in. Side by side, a wide screen turns that sequence into a
 * row the eye scans left to right, and long prose gets squeezed into columns
 * narrow enough to hyphenate. Focus areas and locations keep the auto-fit grid
 * above -- those are a set of equals, where a row is right. */
.professional-cards-stacked {
  grid-template-columns: minmax(0, 1fr);
}

.professional-card {
  padding: 1.5rem;
  border: 1px solid var(--biz-line);
  border-radius: var(--biz-radius);
  background: var(--biz-surface);
}

.professional-card h3 {
  margin: 0 0 0.5rem;
  font-size: 1.0625rem;
  color: var(--biz-ink);
}

.professional-card p {
  margin: 0;
  line-height: 1.55;
  color: var(--biz-body);
}

.professional-card .ti {
  display: block;
  margin-bottom: 0.75rem;
  font-size: 1.5rem;
  color: var(--biz-accent);
}

a.professional-page-link {
  text-decoration: none;
  transition: border-color 0.15s ease;
}

a.professional-page-link:hover,
a.professional-page-link:focus-visible {
  border-color: var(--biz-accent);
}

.professional-qualifications {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.75rem;
}

.professional-qualifications li {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  align-items: baseline;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--biz-line);
}

.professional-qualifications strong {
  color: var(--biz-ink);
}

.professional-qualifications span {
  color: var(--biz-body);
}

.professional-year {
  margin-left: auto;
  font-variant-numeric: tabular-nums;
}

.professional-registration,
.professional-languages {
  margin: 1.25rem 0 0;
  color: var(--biz-body);
  line-height: 1.6;
}

.professional-location address {
  font-style: normal;
  /* An address is written on several lines and HTML collapses newlines, so
     without this a two-line address renders as one long run. */
  white-space: pre-line;
  margin: 0 0 0.75rem;
  color: var(--biz-body);
  line-height: 1.55;
}

.professional-hours {
  margin: 0 0 0.75rem;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.25rem;
  color: var(--biz-body);
  font-variant-numeric: tabular-nums;
}

.professional-phone {
  margin: 0;
}

.professional-phone a {
  color: var(--biz-accent);
}

.professional-note {
  margin: 0.75rem 0 0;
  font-size: 0.9375rem;
  color: var(--biz-body);
}

.professional-recognition {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.75rem;
  color: var(--biz-body);
}

.professional-recognition strong {
  color: var(--biz-ink);
}

/* The safety notice.
 *
 * Deliberately the loudest thing on the page after the name. For anyone in
 * trouble reading a clinician's website this is the only section that matters,
 * and a quiet grey footnote at the bottom is not good enough.
 *
 * The accent border rather than a red fill: this is not an error state, and
 * making a page look broken is its own kind of unhelpful.
 */
/* The safety notice is the mockup's dark band. It was a bordered card on a
   light ground, which read as a footnote; dark is the emphasis this section
   has always wanted, and it is emphasis rather than an error state. */
.professional-safety {
  margin-top: 3rem;
  padding: 1.75rem;
}

.professional-safety h2 {
  margin: 0 0 0.75rem;
  font-size: 1.125rem;
  color: var(--biz-ink);
}

.professional-safety p {
  margin: 0;
  line-height: 1.6;
  color: var(--biz-body);
}

.professional-safety-contacts {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  margin: 1.25rem 0 0;
  padding: 0;
  list-style: none;
}

.professional-safety-contacts li {
  display: flex;
  flex-direction: column;
}

.professional-safety-contacts span {
  font-size: 0.8125rem;
  color: var(--biz-body);
}

.professional-safety-contacts strong {
  font-size: 1.25rem;
  color: var(--biz-ink);
  font-variant-numeric: tabular-nums;
}

/* Media: talks, interviews, podcast episodes.
 *
 * A clinician's public work is often a conference talk or a podcast rather
 * than a blog post, and a page with nowhere to put those pushes people to
 * paste links into a paragraph.
 */
.profile-media-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: 1.75rem;
}

.profile-media-item {
  display: grid;
  gap: 0.875rem;
  align-content: start;
}

/* aspect-ratio rather than the padding-top trick: the embed keeps its shape
 * while the column width changes, without a wrapper whose only job is to hold
 * a percentage. */
.profile-embed {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: var(--biz-radius);
  overflow: hidden;
  background: var(--biz-ground);
}

/* Spotify's player is not 16:9 and is letterboxed by it.
 *
 * A class set from the provider rather than :has(iframe[src*=...]): :has() is
 * unsupported in Safari before 15.4 and Firefox before 121, and there the
 * player would silently sit in a 16:9 box. The template knows the provider, so
 * it can just say so. */
.profile-embed.is-audio {
  aspect-ratio: auto;
  height: 152px;
}

.profile-embed iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

.profile-media-thumb {
  display: block;
  border-radius: var(--biz-radius);
  overflow: hidden;
}

.profile-media-thumb img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.profile-media-source {
  margin: 0;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--biz-accent);
}

.profile-media-text h3 {
  margin: 0.375rem 0 0;
  font-size: 1.0625rem;
  line-height: 1.35;
  color: var(--biz-ink);
}

.profile-media-text h3 a {
  color: inherit;
  text-decoration: none;
}

.profile-media-text h3 a:hover,
.profile-media-text h3 a:focus-visible {
  text-decoration: underline;
}

.profile-media-text p {
  margin: 0.5rem 0 0;
  line-height: 1.55;
  color: var(--biz-body);
}

/* Links and collections. */
.professional-collection-note {
  margin: -0.75rem 0 1.5rem;
  color: var(--biz-body);
  line-height: 1.6;
}

.professional-link-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
  gap: 0.875rem;
}

.professional-link-grid a {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  padding: 1rem 1.125rem;
  border: 1px solid var(--biz-line);
  border-radius: var(--biz-radius);
  background: var(--biz-surface);
  color: var(--biz-ink);
  text-decoration: none;
  transition: border-color 0.15s ease, transform 0.15s ease;
}

.professional-link-grid a:hover,
.professional-link-grid a:focus-visible {
  border-color: var(--biz-accent);
  transform: translateY(-1px);
}

/* The middle column takes the remaining width so a long title wraps rather
 * than pushing the trailing arrow off the card. */
.professional-link-grid a > span {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  flex: 1 1 auto;
  min-width: 0;
}

.professional-link-grid strong {
  font-weight: 600;
  line-height: 1.3;
}

.professional-link-grid em {
  font-style: normal;
  font-size: 0.8125rem;
  color: var(--biz-body);
}

.professional-link-grid .ti {
  flex: 0 0 auto;
  color: var(--biz-accent);
}

@media (prefers-reduced-motion: reduce) {
  .professional-link-grid a {
    transition: none;
  }
  .professional-link-grid a:hover,
  .professional-link-grid a:focus-visible {
    transform: none;
  }
}


/* A fluid heading rather than one size everywhere.
 *
 * The base sheet's h1 is sized for a desktop hero; a long name at that size on
 * a 360px phone either wraps into four lines or overflows. clamp() lets it
 * shrink with the viewport without a breakpoint for every device.
 */
.professional-hero h1 {
  font-size: clamp(2rem, 6vw, 3.25rem);
}

.professional-section h2 {
  font-size: clamp(1.375rem, 3.2vw, 1.875rem);
}

/* Nothing here is allowed to push the page sideways.
 *
 * These fields carry text somebody typed -- a long URL in a fees note, a
 * German compound in a qualification, an unbroken registration string -- and a
 * single long token in a grid cell forces a horizontal scrollbar on the whole
 * document.
 */
.professional-lede,
.professional-card p,
.profile-media-text p,
.professional-registration,
.professional-languages,
.professional-note,
.professional-collection-note,
.professional-safety p,
.professional-location address,
.professional-link-grid strong,
.professional-link-grid em {
  overflow-wrap: anywhere;
}

/* Phones.
 *
 * The badges row and the safety contacts both use generous gaps that read as
 * disconnected columns once they wrap on a narrow screen.
 */
@media (max-width: 520px) {
  .professional-main {
    padding-inline: 1rem;
  }

  .professional-hero {
    padding-top: 2rem;
  }

  .professional-badges {
    gap: 1rem 1.25rem;
  }

  .professional-badges strong {
    font-size: 1.25rem;
  }

  .professional-safety {
    padding: 1.25rem;
  }

  .professional-safety-contacts {
    gap: 0.875rem 1.5rem;
  }
}


/* Bands.
 *
 * The mockup does not run one flat background top to bottom: a lavender
 * feature band sits around the middle of the page and a dark band near the
 * bottom, with lighter sections alternating between them. That rhythm is most
 * of why it reads as designed rather than as a document.
 *
 * Full-bleed with a negative margin and matching padding, so the colour
 * reaches both edges while the content stays on the same measure as every
 * other section.
 */
.professional-band {
  /* Full-bleed: pull the band out to the viewport edges from inside the
     measure-width column. */
  margin-inline: calc(50% - 50vw);
  padding-inline: max(1.25rem, calc(50vw - var(--biz-measure) / 2));
  border-top: 0;

  /* Air above and below. A full-bleed colour block butted straight against the
     card above it reads as the page breaking rather than as a new section --
     the card's bottom edge and the band's top edge become one line. The
     margin-inline above only moves the sides, so this has to be said
     separately. */
  margin-block: 3rem;
}

/* Consecutive bands keep one gap between them rather than two. */
.professional-band + .professional-band {
  margin-top: 0;
}

.professional-band-feature {
  background: var(--prof-band);
  color: var(--prof-band-ink);
  padding-block: 3.5rem;
}

.professional-band-feature h2,
.professional-band-feature h3 {
  color: var(--prof-band-ink);
}

/* Cards on the band keep a white surface so they lift off it rather than
   dissolving into it. */
.professional-band-feature .professional-card {
  background: var(--biz-surface);
  border-color: transparent;
}

.professional-band-dark {
  background: var(--prof-dark);
  color: var(--prof-dark-ink);
  padding-block: 3rem;
  margin-top: 3rem;
  border: 0;
  border-radius: 0;
}

.professional-band-dark h2,
.professional-band-dark strong {
  color: var(--prof-dark-ink);
}

.professional-band-dark p,
.professional-band-dark span {
  color: color-mix(in srgb, var(--prof-dark-ink) 78%, transparent);
}

/* Sections alternate rather than repeating one background, which is what
   stops a long page reading as one undifferentiated column. */
.professional-section-alt {
  background: color-mix(in srgb, var(--biz-ground) 55%, #ffffff);
  margin-inline: calc(50% - 50vw);
  padding-inline: max(1.25rem, calc(50vw - var(--biz-measure) / 2));
  padding-block: 2.5rem;
}

/* 100vw includes the scrollbar, so a full-bleed band is a few pixels wider
   than the viewport and the page scrolls sideways. Clipping at the root costs
   nothing and removes the whole class of problem. */
.professional-profile-view body,
body.professional-profile-view {
  overflow-x: clip;
}

/* Free-form prose.
 *
 * Markdown a profile wrote, so the shapes are unpredictable -- headings,
 * lists, tables, quotes. These give it the page's typography rather than the
 * browser's defaults, which is the difference between prose that belongs and
 * prose that was pasted in.
 */
.professional-prose {
  color: var(--biz-body);
  line-height: 1.7;
  overflow-wrap: anywhere;
}

.professional-prose h2,
.professional-prose h3,
.professional-prose h4 {
  color: var(--biz-ink);
  margin: 2rem 0 0.75rem;
}

.professional-prose h2:first-child,
.professional-prose h3:first-child {
  margin-top: 0;
}

.professional-prose p,
.professional-prose ul,
.professional-prose ol {
  margin: 0 0 1rem;
}

.professional-prose ul,
.professional-prose ol {
  padding-left: 1.25rem;
}

.professional-prose li {
  margin-bottom: 0.375rem;
}

.professional-prose a {
  color: var(--biz-accent);
}

.professional-prose blockquote {
  margin: 1.5rem 0;
  padding-left: 1.25rem;
  border-left: 3px solid var(--biz-accent);
  color: var(--biz-ink);
}

/* A wide table is the one shape that will not fit a narrow column, so it
   scrolls inside itself rather than widening the page. */
.professional-prose table {
  display: block;
  overflow-x: auto;
  width: 100%;
  border-collapse: collapse;
}

.professional-prose th,
.professional-prose td {
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--biz-line);
  text-align: left;
}

/* "Currently" / "In the lab".
 *
 * A researcher's page goes stale faster than a practice's, and a dated status
 * block is the difference between a page somebody trusts and one they assume
 * is abandoned. Given the accent edge so it reads as live rather than as
 * another content section.
 */
.profile-status {
  margin-top: 2rem;
  padding: 1.5rem 1.75rem;
  border: 1px solid var(--biz-line);
  border-left: 4px solid var(--biz-accent);
  border-radius: var(--biz-radius);
  background: var(--biz-surface);
}

.profile-status-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  margin-bottom: 0.75rem;
}

.profile-status-head h2 {
  margin: 0;
  font-size: 1rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--biz-accent);
}

.profile-status-date {
  font-size: 0.8125rem;
  color: var(--biz-body);
  font-variant-numeric: tabular-nums;
}

.profile-status-headline {
  margin: 0 0 0.5rem;
  font-size: 1.125rem;
  line-height: 1.45;
  color: var(--biz-ink);
}

.profile-status p {
  margin: 0;
  line-height: 1.6;
  color: var(--biz-body);
  overflow-wrap: anywhere;
}

.profile-status-items {
  margin: 1rem 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.5rem;
}

.profile-status-items li {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.75rem;
  align-items: baseline;
}

.profile-status-items strong {
  color: var(--biz-ink);
}

.profile-status-items span {
  color: var(--biz-body);
}

.profile-status-link {
  display: inline-block;
  margin-top: 1rem;
  color: var(--biz-accent);
  font-weight: 600;
}

/* Dynamic lists: reading, resources, publications. A bibliography wants its
   metadata subordinate to the title, not competing with it. */
.profile-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  /* No gap: every row draws its own bottom rule, and a gap on top of that puts
     a stripe of background between the rule and the next citation. */
  gap: 0;
}

/* One row treatment for all three kinds of entry.
   `.profile-list li a` used to give any anchor in the list a bordered card on
   its own surface -- written when this list held nothing but links, and left
   behind when it grew a collapsible variant and a static one. The result was a
   bibliography where a citation with an abstract was a flat row, a citation
   with only a URL was a raised card, and the two started at different left
   edges. Twenty-eight of them in a column read as two lists interleaved.

   Flat is the right choice rather than making everything a card: at this
   length a card each is a wall of boxes, and a rule between rows is what a
   reference list looks like. */
/* Decoration only. Colour is set per variant below: `.profile-list li a` beats
   a single class, so setting a colour here would have overridden
   `.profile-list-link` and quietly greyed out every "Read it". */
.profile-list li a {
  text-decoration: none;
}

.profile-list strong {
  line-height: 1.4;
  overflow-wrap: anywhere;
}

.profile-list-meta {
  font-size: 0.8125rem;
  color: var(--biz-accent);
}

.profile-list-note {
  font-size: 0.875rem;
  color: var(--biz-body);
}

.professional-figure {
  margin: 0;
}

.professional-figure img {
  width: 100%;
  border-radius: var(--biz-radius);
}

.professional-figure figcaption {
  margin-top: 0.5rem;
  font-size: 0.875rem;
  color: var(--biz-body);
}

/* An honest placeholder, not a teaser. */
.professional-soon p {
  margin: 0;
  color: var(--biz-body);
}

/* A page's own banner: a lab logo, a title card. Capped in height because
   these are supplied by the profile and a tall one would otherwise push the
   page's actual content below the fold. */
.professional-page-banner {
  display: block;
  width: 100%;
  max-width: 520px;
  height: auto;
  max-height: 220px;
  object-fit: contain;
  object-position: left;
  margin: 0 0 1.25rem;
  border-radius: var(--biz-radius);
}

@media (max-width: 640px) {
  .professional-page-banner {
    max-width: 100%;
    object-position: center;
  }
}

/* A long dynamic list: publications, reading, resources.
   The citation is always visible and the abstract opens on demand, so twenty
   papers read as twenty lines rather than several screens of prose. */
.profile-list-entry {
  display: block;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--biz-border, rgba(0, 0, 0, 0.08));
}

.profile-list li:last-child .profile-list-entry {
  border-bottom: 0;
}

.profile-list-entry > summary {
  cursor: pointer;
  list-style: none;
  display: grid;
  gap: 0.2rem;
  /* Room for the marker drawn below, so a two-line citation does not run
     under it. */
  padding-left: 1.4rem;
  position: relative;
}

.profile-list-entry > summary::-webkit-details-marker {
  display: none;
}

.profile-list-entry > summary::before {
  content: '+';
  position: absolute;
  left: 0;
  top: 0;
  font-weight: 700;
  color: var(--biz-accent);
}

.profile-list-entry[open] > summary::before {
  content: '−';
}

.profile-list-entry[open] > summary {
  margin-bottom: 0.4rem;
}

.profile-list-entry .profile-list-note {
  padding-left: 1.4rem;
  margin: 0 0 0.5rem;
}

.profile-list-link {
  margin-left: 1.4rem;
  font-weight: 600;
  color: var(--biz-accent);
}

/* No disclosure marker, but the same indent, so every citation in the list
   starts on the same left edge whether or not it has an abstract. */
.profile-list-entry-plain {
  display: grid;
  gap: 0.2rem;
  padding-left: 1.4rem;
  color: var(--biz-ink);
  text-decoration: none;
}

a.profile-list-entry-plain:hover strong,
a.profile-list-entry-plain:focus-visible strong {
  color: var(--biz-accent);
}

/* The year filter. Hidden until the page's JS reveals it, so a reader without
   scripting sees the full list rather than a control that does nothing. */
.profile-list-filter {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 1rem;
}

.profile-list-filter-label {
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--biz-muted, #666);
  margin-right: 0.2rem;
}

.profile-list-chip {
  border: 1px solid var(--biz-border, rgba(0, 0, 0, 0.15));
  background: transparent;
  border-radius: 999px;
  padding: 0.25rem 0.7rem;
  font: inherit;
  font-size: 0.85rem;
  cursor: pointer;
}

.profile-list-chip.is-active {
  background: var(--biz-accent);
  border-color: var(--biz-accent);
  color: #fff;
}

.profile-list-empty {
  color: var(--biz-muted, #666);
}

/* --- Header ------------------------------------------------------------
 *
 * The shared header is built for "brand left, nav and one action right" and
 * is a full pill (border-radius: 999px). A practice or a lab has more pages
 * than a shop and often two ways to be contacted, so it wraps -- and a
 * wrapped pill is a tall rounded blob with the nav running off the edge.
 *
 * Scoped to the professional view. Business profiles fit on one row today and
 * should keep the shape they were designed with.
 */

/* A radius that is a pill at one row's height and a rounded card when it
   wraps, so the header looks deliberate either way rather than only when it
   happens to fit. */
@media (min-width: 1101px) {
  .professional-profile-view .business-header {
    border-radius: 16px;
    gap: 0.5rem 1.25rem;
    box-shadow: 0 2px 12px rgb(26 21 18 / 0.06);
  }
}

/* Compact contact actions leave the profile name and navigation prominent. */
.professional-profile-view .business-header .business-action {
  min-height: 32px;
  box-sizing: border-box;
  padding: 0.25rem 0.5rem;
  border-radius: 4px;
  font-size: 14px;
  line-height: 1.35;
  font-weight: 500;
  justify-content: center;
  white-space: normal;
  overflow-wrap: anywhere;
  text-align: center;
}

.professional-profile-view .business-header .business-action-secondary {
  background: transparent;
  border-color: transparent;
  color: var(--biz-body);
}

.professional-profile-view .business-header .business-action-secondary:hover {
  background: var(--biz-ground);
  color: var(--biz-ink);
}

.professional-profile-view .business-header .business-action:focus-visible {
  outline: 2px solid var(--biz-accent);
  outline-offset: 3px;
}

.professional-profile-view .business-header .business-action {
  background: transparent;
  border-color: transparent;
  color: var(--biz-body);
  box-shadow: none;
}

.professional-profile-view .business-header .business-action:hover {
  color: var(--biz-accent);
  text-decoration: underline;
  text-underline-offset: 3px;
  transform: none;
}

.professional-profile-view .business-mobile-menu-actions {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.5rem;
}

.professional-profile-view .business-mobile-menu-actions .business-action {
  min-height: 44px;
  justify-content: flex-start;
  text-align: left;
}

@media (min-width: 1101px) {
  /* Nav takes the space that is left and wraps inside itself, instead of
     pushing the actions onto a row of their own. */
  .professional-profile-view .business-nav {
    /* Centred between the brand and the actions.
       Pushed to flex-end the nav sat jammed against the two email buttons with
       a wide gap after the brand, which reads as a layout that has come apart
       rather than one that is right-aligned on purpose. */
    flex: 1 1 auto;
    justify-content: center;
    gap: 0.4rem 1.15rem;
    min-width: 0;
  }

  .professional-profile-view .business-nav > a,
  .professional-profile-view .business-nav-group > a {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    min-height: 32px;
    box-sizing: border-box;
    padding: 0.25rem 0.5rem;
    font-size: 14px;
    font-weight: 500;
    line-height: 1.35;
  }

  /* Whatever row the actions end up on, they stay to the right rather than
     collapsing to the left edge under the brand. */
  .professional-profile-view .business-header-actions {
    margin-left: auto;
    flex: 0 0 auto;
  }

  /* An overflow link is a nav item here, not a footnote: with seven pages the
     last two were being dimmed for no reason a reader would understand. */
  .professional-profile-view .business-nav-overflow {
    opacity: 1;
  }
}

/* Eight items and two buttons do not fit one row, at any width.
   The header is capped, so "nav wraps inside itself" above only holds while
   the menu is short: at eight items -- which is what an academic profile grows
   to, with About, lab, research, teaching, contact, blog and a publications
   page -- the actions were pushed onto a row of their own and it read as a
   layout that had come apart.

   So the nav takes a full-width row of its own, deliberately, with a rule
   above it. Two rows either way; this way it looks like a masthead.

   No upper bound, and that was the bug in the first attempt: the header is
   capped at 1240px whatever the screen is, so a 2560px monitor has exactly the
   same problem as a 1300px one. Bounding this at a viewport width meant the
   broken layout came back on the widest screens -- the ones most likely to be
   showing the site to somebody who matters. The floor stays at 1101px because
   below it the shared header hides the inline nav and hands to the mobile
   menu. */
@media (min-width: 1101px) {
  .professional-profile-view .business-nav {
    /* `flex` and not `flex-basis`: the rule above sets the shorthand, which
       would otherwise reset the basis back to auto. */
    flex: 1 0 100%;
    order: 3;
    justify-content: center;
    gap: 0.4rem 1.35rem;
    margin-top: 0.25rem;
    padding-top: 0.6rem;
    border-top: 1px solid var(--biz-line, rgba(0, 0, 0, 0.08));
  }

  .professional-profile-view .business-header {
    row-gap: 0.35rem;
  }
}

/* Nothing below 1100px. The shared header already hides the inline nav and
   the actions there and hands over to the mobile menu, so rules for tablet and
   phone widths would either do nothing or -- worse -- put the hidden elements
   back and leave two navigations on screen at once. The overflow this fixes
   only happens on a wide screen, which is the only place these rules apply.

   Checked rather than assumed: business-profile.css hides
   `.business-header > .business-nav` and `.business-header >
   .business-header-actions` inside @media (max-width: 1100px), and this file
   loads after it, so anything declared here would have won. */

/* An institution that links to itself. Underlined on hover only, so a list of
   three degrees does not read as a row of buttons. */
.professional-qualification-link {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, currentColor 30%, transparent);
}

.professional-qualification-link:hover,
.professional-qualification-link:focus-visible {
  color: var(--biz-accent);
  border-bottom-color: currentColor;
}

/* --- Mobile ------------------------------------------------------------ */

/* The portrait is a supporting image, not the page.
   At 340px wide with a 4:5 ratio it is 425px tall, which on a 360px phone
   fills the screen below the name and pushes everything else out of sight --
   a reader scrolls past a photograph to reach what the page is about. */


/* The dropdown must paint above the page, not merely after it.
   The header carries z-index 50 and the panel inherited no stacking of its
   own, so anything on the page that creates a stacking context could cover
   it -- and a menu that opens underneath the content looks exactly like a
   menu that did not open. */
@media (max-width: 1100px) {
  .professional-profile-view .business-mobile-menu-panel {
    z-index: 60;
  }
}

/* "Back to the practice" on the links page. Understated: it is an exit, not
   the reason somebody is here. */
.professional-back {
  margin: 0 0 1.5rem;
}

.professional-back a {
  color: var(--biz-accent);
  text-decoration: none;
  font-weight: 600;
}

.professional-back a:hover,
.professional-back a:focus-visible {
  text-decoration: underline;
}

/* --- The hero on a page of its own ------------------------------------- */

/* A masthead, not a cover. On a sub-page the reader has already met the
   person; what they asked for is below, and on a phone the full hero pushed it
   entirely off screen. */
.professional-hero-compact {
  padding-block: 1.25rem 0;
  gap: 1rem;
}

.professional-hero-compact h1 {
  font-size: clamp(1.5rem, 4vw, 2rem);
}

/* The bio and the calls to action belong to the front page. Repeating them
   above every page is what made each one look like the last. */
.professional-hero-compact .professional-lede,
.professional-hero-compact .professional-badges,
.professional-hero-compact .professional-hero-actions {
  display: none;
}

/* The portrait stays, small, and beside the name rather than across from it.
   Hiding it entirely was an over-correction: a masthead with no face reads as
   a different site from the one the reader just left, and the point of the
   compact hero was to shorten the header, not to remove the person from it.

   But pinning it to the far right of a full-width column left it stranded in
   whitespace, vertically centred against a three-line name block and touching
   the rule below -- decoration dropped into a corner rather than part of the
   masthead. An avatar belongs next to the name it labels, so it moves to the
   left and the pair sit together at the start of the row.

   Placed by grid area, not by source order: the portrait stays second in the
   markup so a screen reader and a narrow screen still reach the name first. */
.professional-hero-compact {
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  justify-content: start;
  gap: 1rem;
}

.professional-hero-compact > :first-child {
  grid-area: 1 / 2;
}

.professional-hero-compact .professional-portrait {
  grid-area: 1 / 1;
  max-width: 64px;
  aspect-ratio: 1;
  border-radius: 50%;
  justify-self: start;
}

/* The initials fallback sizes its type to a 340px portrait. */
.professional-hero-compact .professional-portrait-initials {
  font-size: 1.5rem;
}

/* --- The portrait on small screens ------------------------------------- */

/* A circle, and small. At 4:5 and full column width the portrait was taller
   than a phone screen -- a reader scrolled past a photograph to reach the
   page. Circular because at this size it reads as an avatar, which is what it
   is doing here. */
/* Below the hero's own breakpoint, not near it: at 900px the two-column
   desktop hero was still being served the small circular phone portrait. */
@media (max-width: 859px) {
  /* Avatar-sized, and no larger.
     At 104px the photo took a third of a phone's width away from the column
     beside it, so the field line and the name both wrapped that would
     otherwise have fitted -- the header got shorter and the name got harder to
     read, which is the opposite trade. 72px leaves the name a line of its own
     at 375px, and it is the size the site header already uses for the same
     face, so the two read as the same element rather than two photographs. */
  .professional-hero {
    gap: 1rem;
  }

  .professional-portrait {
    max-width: 72px;
    aspect-ratio: 1;
    border-radius: 50%;
    justify-self: end;
  }
}

@media (max-width: 380px) {
  .professional-portrait {
    max-width: 60px;
  }
}

/* A nav item with children. Opens on hover and on keyboard focus, so it is
   reachable without a pointer. */
.professional-profile-view .business-nav-group {
  position: relative;
}

.professional-profile-view .business-nav-dropdown {
  position: absolute;
  top: calc(100% + 0.5rem);
  left: 0;
  /* See the bridge below: this gap is why the menu vanished on the way to it. */
  min-width: 220px;
  padding: 0.4rem;
  border: 1px solid var(--biz-line);
  border-radius: 12px;
  background: var(--biz-surface);
  box-shadow: 0 18px 50px rgb(26 21 18 / 0.16);
  display: grid;
  gap: 0.1rem;
  opacity: 0;
  visibility: hidden;
  z-index: 60;
}

/* A transparent bridge across the gap.
   The panel sits half a rem below its trigger, so moving the pointer toward it
   left the group -- :hover ended, the panel disappeared, and the item was
   unclickable. The bridge makes the hover area continuous without closing the
   visual gap. */
.professional-profile-view .business-nav-dropdown::before {
  content: '';
  position: absolute;
  top: -0.6rem;
  left: 0;
  right: 0;
  height: 0.6rem;
}

.professional-profile-view .business-nav-group:hover .business-nav-dropdown,
.professional-profile-view .business-nav-group:focus-within .business-nav-dropdown {
  opacity: 1;
  visibility: visible;
}

/* Keyboard users get the same thing without a pointer: the trigger and every
   item are links, so focus moving into the panel keeps it open via
   :focus-within above. */
.professional-profile-view .business-nav-group > a {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}

.professional-profile-view .business-nav-dropdown a {
  padding: 0.45rem 0.6rem;
  border-radius: 8px;
  white-space: nowrap;
}

.professional-profile-view .business-nav-dropdown a:hover,
.professional-profile-view .business-nav-dropdown a:focus-visible {
  background: color-mix(in srgb, var(--biz-accent) 10%, transparent);
}

/* A child in the phone menu, set in from its parent. */
.business-mobile-menu-child {
  padding-left: 1.5rem !important;
  font-size: 0.92em;
  opacity: 0.9;
}

/* A record entry with nowhere to go. Reads as text, not as something to click:
   no pointer cursor, no hover state, no underline on the way past. */
.profile-list-entry-static {
  cursor: default;
  color: inherit;
}

/* "See all grants and recognition" under a home-page section that shows only
   its first few entries. */
.professional-section-more {
  display: inline-block;
  margin-top: 1rem;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--biz-accent);
  text-decoration: none;
}

.professional-section-more:hover,
.professional-section-more:focus-visible {
  text-decoration: underline;
}

/* A section's opening sentence.
   Deliberately the same size and line height as the prose beneath it: set a
   size larger, as it was when it borrowed the hero's `professional-lede`, the
   two paragraphs stopped sharing a rhythm and the page looked like it had
   changed font halfway down a passage. Weight and colour lead instead. */
.professional-section-lede {
  margin: 0 0 1rem;
  line-height: 1.7;
  font-weight: 500;
  color: var(--biz-ink);
}

/* A card whose title goes somewhere. */
.professional-card-linked h3 {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
}

.professional-card-linked h3 a {
  color: inherit;
  text-decoration: none;
}

/* The same icon the link cards use, rather than a CSS escape for the
   north-east arrow.

   The escape was authored from a Python heredoc, where a backslash
   followed by 21 is an octal escape rather than the start of a CSS hex
   escape. The stylesheet ended up carrying a literal 0x11 control byte
   followed by the characters 9 and 7, so the cards read
   "IVY Lab (Psychology), StFX 97".

   An element from the icon font the page already loads cannot be mangled
   on the way in, and it matches the arrow beside every other outbound link
   on the site. */
.professional-card-outbound {
  font-size: 0.85em;
  color: var(--biz-accent);
}

.professional-card-linked h3 a:hover,
.professional-card-linked h3 a:focus-visible {
  color: var(--biz-accent);
  text-decoration: underline;
}

/* --- Downloads ---------------------------------------------------------- */

/* A file the profile is offering, which is not the same as a link to
   somewhere else -- so it does not borrow the link grid's card. The row reads
   left to right as icon, what it is, and the action, which is the order
   somebody scanning a list of documents actually needs. */
.profile-downloads {
  display: grid;
  gap: 0.75rem;
}

.profile-download {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 1rem;
  padding: 0.875rem 1rem;
  border: 1px solid var(--biz-line);
  border-radius: var(--biz-radius);
  background: var(--biz-surface);
  color: var(--biz-ink);
  text-decoration: none;
}

.profile-download:hover,
.profile-download:focus-visible {
  border-color: var(--biz-accent);
}

.profile-download-icon {
  font-size: 1.5rem;
  color: var(--biz-accent);
}

.profile-download-text {
  display: grid;
  gap: 0.15rem;
  min-width: 0;
}

.profile-download-text strong {
  line-height: 1.4;
  overflow-wrap: anywhere;
}

.profile-download-text em {
  font-style: normal;
  font-size: 0.875rem;
  color: var(--biz-body);
  overflow-wrap: anywhere;
}

/* The type and size. Quieter than the description, because it is the last
   thing read and the first thing ignored once the decision is made. */
.profile-download-meta {
  font-size: 0.8125rem;
  color: var(--biz-body);
  opacity: 0.85;
}

.profile-download-action {
  font-size: 1.125rem;
  color: var(--biz-accent);
}

/* Collection layouts. `grid` is the default card grid above. */
.professional-link-grid--list {
  grid-template-columns: minmax(0, 1fr);
}

.professional-link-grid--compact {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  gap: 0.5rem;
}

.professional-link-grid--compact a {
  padding: 0.625rem 0.875rem;
}

.professional-link-grid--compact em,
.professional-link-grid--compact a > .ti:first-child {
  display: none;
}
