/**
 * @file        author.css
 * @description Author expert-profile module (M02, C-14)
 *
 * @author      Thomas Dobler - SYNTHETIXMIND LTD
 * @email       tom@synthetixmind.com
 * @company     SYNTHETIXMIND LTD, Paphos, Cyprus
 * @url         https://synthetixmind.com
 *
 * @uid         3b6f49a0-8c17-4d52-ae83-05d17c69b2f4
 * @version     0.4.0.5
 * @created     2026-09-11
 * @updated     2026-09-17
 *
 * @copyright   (c) 2026 by SYNTHETIXMIND LTD
 * @license     Proprietary — All rights reserved
 */

/* ONE module: photo, biography, credentials and media mentions read together,
 * so credibility can be judged in a single pass rather than assembled from
 * sections scattered down the page. */

/* --- Breadcrumbs ----------------------------------------------------------
 * The same component the book detail page uses, and the same rule: the last
 * crumb is dropped below 48rem because it names the page whose <h1> is the very
 * next thing on screen. Duplicated here rather than shared because these are
 * the only two pages that carry a trail, and a third file for nine rules is
 * the abstraction the simplicity policy warns about - revisit at the third
 * caller, not the second. The JSON-LD keeps all three levels either way. */

.crumbs { margin-bottom: var(--space-3); }

.crumbs__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.crumbs__list li + li::before {
  content: "/";
  margin-right: var(--space-2);
  color: var(--border-subtle);
}

.crumbs__list [aria-current="page"] { color: var(--text-secondary); }

@media (max-width: 47.999rem) {
  .crumbs__list li:last-child { display: none; }
}

.author__module {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
}

.author__photo {
  max-width: 200px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-subtle);
}

/* The roster's monogram at profile scale. Same gradient-free Deep Space fill,
 * so a practitioner with no photograph reads as deliberate rather than broken. */
.author__monogram {
  display: grid;
  place-items: center;
  width: 200px;
  height: 200px;
  border-radius: var(--radius-lg);
  background: var(--surface-inverse);
  color: var(--text-on-dark);
  font-family: var(--font-heading);
  font-size: var(--text-4xl);
  line-height: 1;
  border: 1px solid var(--border-subtle);
}

/* A standfirst, not a caption: this is the line that says what the person
 * actually does, and it sits directly under their name. */
.author__headline {
  font-family: var(--font-heading);
  font-style: italic;
  font-size: var(--text-xl);
  line-height: var(--leading-tight);
  color: var(--text-secondary);
  max-width: var(--measure);
}

/* Two labelled facts about the practice. A <dl>, so the label/value pairing is
 * in the markup rather than implied by a colon, and the rows stack on narrow
 * viewports because a term and its definition must not be separated by a
 * column gap the reader has to jump. */
.author__practice {
  display: grid;
  gap: var(--space-2) var(--space-5);
  margin: var(--space-4) 0 0;
  font-size: var(--text-sm);
}

@media (min-width: 48rem) {
  .author__practice { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.author__practice dt {
  font-weight: 600;
  color: var(--text-secondary);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-size: var(--text-xs);
}

.author__practice dd {
  margin: 0;
  color: var(--text-primary);
}

/* The counter always carries a text label (FR22) - never a bare number. It is
 * now a pill so it reads as a fact about the person rather than as a sentence
 * fragment between the headline and the biography. */
.author__count {
  display: inline-block;
  margin-top: var(--space-4);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-full);
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  font-size: var(--text-sm);
  color: var(--text-secondary);
  font-weight: 600;
}

.author__bio { max-width: var(--measure); }

/* These are band headings now, not sub-headings inside a column, so they take
 * the size the rest of the site gives a band heading and carry the same gold
 * rule the homepage bands do. */
.author__credentials > h2,
.author__media > h2 {
  margin-bottom: var(--space-5);
}

.author__credentials > h2::after,
.author__media > h2::after {
  content: "";
  display: block;
  width: 2.5rem;
  height: 3px;
  margin-top: var(--space-3);
  background: linear-gradient(90deg, var(--color-golden-accent), rgb(191 155 48 / 0.15));
  border-radius: var(--radius-full);
}

/* --- Credential / mention cards -------------------------------------------
 * ONE CARD PER STORED LINE. The source is a newline-separated string, so the
 * card carries the whole line and nothing is parsed out of it - no icon, no
 * category, no attempt to guess which half is the institution. The reference
 * design splits each entry into three fields this schema does not have.
 *
 * Still a <ul> of <li>: the list semantics are what a screen reader uses to
 * announce "list, 6 items", and sprint2-discovery asserts the first <li>. */
.author__cards {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-4);
}

@media (min-width: 48rem) {
  .author__cards { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 64rem) {
  .author__cards { grid-template-columns: repeat(3, 1fr); }
}

.author__card {
  margin: 0;
  /* FLEX, and it is load-bearing rather than cosmetic. As a plain block grid
   * item Obscura sized this card from a single line while painting two, so a
   * credential that wrapped was clipped by its own bottom border - box 59px,
   * content 65px, measured. A flex container is measured correctly and still
   * stretches to the grid row, which is what keeps the cards in a row equal
   * height. `align-items: start` also fixes it but gives that up. */
  display: flex;
  align-items: center;
  padding: var(--space-4);
  background: var(--surface-page);
  border: 1px solid var(--border-subtle);
  border-left: 3px solid var(--color-golden-accent);
  border-radius: var(--radius-md);
  line-height: var(--leading-body);
}

/* Media mentions rank below credentials, and the treatment says so: a steel
 * edge rather than a gold one, on the page surface rather than a raised card.
 * The rank is carried by more than colour - the band is last (NFR21). */
.author__cards--quiet .author__card {
  background: var(--surface-raised);
  border-left-color: var(--color-steel-mist);
}

.author__service { max-width: var(--measure); }
.author__service > h3 { font-size: var(--text-xl); margin-bottom: var(--space-2); }

@media (min-width: 768px) {
  .author__module {
    grid-template-columns: minmax(200px, 300px) 1fr;
    gap: var(--space-8);
    align-items: start;
  }

  .author__photo { max-width: 100%; }
  .author__monogram { width: 100%; height: auto; aspect-ratio: 1; }
}

/* The portrait gets a raised frame at desktop width, matching the book page's
 * hero panel so the two detail surfaces read as one family. */
@media (min-width: 64rem) {
  .author__photo,
  .author__monogram {
    box-shadow: 0 0.75rem 2rem rgb(45 49 66 / 0.16);
  }
}

/* --- Authors index (roster) -------------------------------------------------
 * The list page M02 never had. Shares this file with the profile module rather
 * than opening a second one, because the two are the same component at two
 * sizes and a separate sheet is how the photo treatment would eventually stop
 * matching between them. */

.authors__intro {
  font-size: var(--text-lg);
  max-width: var(--measure);
}

.authors__grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-5);
}

/* Mobile-first: one column is the default and the wider forms are the media
 * queries, per the banded layout's rule that 375px is the design target. */
@media (min-width: 48rem) {
  .authors__grid { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 64rem) {
  .authors__grid { grid-template-columns: repeat(3, 1fr); }
}

/* ONE link per card, so the whole tile is the target. min-height is not set:
 * the card is far taller than the 44px floor by virtue of its contents, and a
 * fixed height would clip a long headline rather than grow for it. */
.authors__card {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  height: 100%;
  padding: var(--space-4);
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  text-decoration: none;
  color: var(--text-primary);
}

.authors__card:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.authors__photo,
.authors__monogram {
  flex: 0 0 auto;
  width: 4.5rem;
  height: 4.5rem;
  border-radius: var(--radius-full);
  object-fit: cover;
}

/* The stand-in for a missing photograph. No author on this site has one yet,
 * so this is the state every card is currently in and it has to look
 * deliberate rather than broken. Deep Space on Cloud White is the same pairing
 * the masthead uses; the letter is centred by grid rather than by line-height
 * so it stays centred at any font size. */
.authors__monogram {
  display: grid;
  place-items: center;
  background: var(--surface-inverse);
  color: var(--text-on-dark);
  font-family: var(--font-heading);
  font-size: var(--text-2xl);
  line-height: 1;
  border: 1px solid var(--border-subtle);
}

.authors__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;   /* lets a long headline wrap instead of forcing the card wide */
}

/* An <h3>, so the browser's heading margins have to be cleared explicitly. */
.authors__name {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--text-lg);
  line-height: var(--leading-tight);
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

.authors__card:hover .authors__name,
.authors__card:focus-visible .authors__name {
  color: var(--text-link);
}

.authors__headline {
  color: var(--text-secondary);
  font-size: var(--text-sm);
  line-height: var(--leading-body);
}

/* FR22: the counter always carries a text label, never a bare number. */
.authors__count {
  color: var(--text-secondary);
  font-size: var(--text-xs);
  font-weight: 600;
}

/* --- Motion -----------------------------------------------------------------
 * Enhancement only. Every rule below can be deleted and the page is unchanged
 * in content and reading order. Entrance-only, never looping (SC 2.2.2), and
 * switched OFF rather than shortened under prefers-reduced-motion — a
 * vestibular trigger shortened is still a trigger. */

@media (prefers-reduced-motion: no-preference) {
  .authors__card {
    transition:
      transform var(--duration-base) var(--ease-out),
      border-color var(--duration-base) var(--ease-out),
      box-shadow var(--duration-base) var(--ease-out);
  }

  .authors__card:hover,
  .authors__card:focus-visible {
    transform: translateY(-0.25rem);
    border-color: var(--color-golden-accent);
    box-shadow: 0 0.75rem 1.5rem rgb(45 49 66 / 0.12);
  }

  .authors__monogram {
    transition: transform var(--duration-base) var(--ease-out);
  }

  .authors__card:hover .authors__monogram,
  .authors__card:focus-visible .authors__monogram {
    transform: scale(1.06);
  }
}

/* ===========================================================================
 * THE PRACTITIONER PROFILE, SECOND PASS (migration 0014).
 *
 * 0.28.0 ported this design's LAYOUT - banded credential and mention cards, the
 * monogram fallback, the breadcrumb that drops its last crumb on a phone - and
 * listed what it could not build "for want of a data model rather than want of
 * effort". These are the rules for the blocks that data model now exists for:
 * the short brief in the hero, the thesis sidebar, the editorial biography with
 * its drop cap, and the gold-ruled pull quote.
 * ======================================================================== */

/* --- The section label ----------------------------------------------------
 * The same small uppercase label the homepage uses, and deliberately the same
 * VALUES rather than a shared class: home.css is loaded only by the homepage
 * and author.css only by the two author surfaces, so a shared `.eyebrow` would
 * have to move into base.css - a site-wide primitive introduced for two
 * callers. The simplicity policy says the smallest correct change; if a third
 * surface wants one, that is the moment it becomes a primitive.
 *
 * FULL-STRENGTH --text-secondary, never an alpha of it. On Surface Raised the
 * token has more headroom than it does on Cloud White, but the rule 0.27.0
 * arrived at is about the habit rather than the surface: a tint under a text
 * token on a light band is how 4.54:1 becomes 4.37:1 without anything failing. */
.author__eyebrow {
  margin: 0 0 var(--space-3);
  color: var(--text-secondary);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* --- The short brief ------------------------------------------------------
 * Set one step up from body size, which is the comp's treatment and the reason
 * it works: it is the only paragraph in the hero, so it reads as a standfirst
 * rather than as the first of several. */
.author__brief {
  margin: var(--space-4) 0 0;
  max-width: var(--measure);
  font-size: var(--text-lg);
  line-height: var(--leading-body);
}

/* --- Biography band -------------------------------------------------------
 * ONE COLUMN UNTIL 64rem. The comp is a 4/8 split, and at 375px a sidebar is
 * simply a block that comes first - which is the right order anyway, since the
 * thesis is the shorter and more pointed of the two. */
.author-life__grid {
  display: grid;
  gap: var(--space-8);
}

@media (min-width: 64rem) {
  .author-life__grid {
    grid-template-columns: 4fr 8fr;
    align-items: start;
  }

  /* STICKY, not fixed, and only where there is a column for it to travel in.
   * The thesis is the frame the biography should be read through, so it stays
   * in view while the prose scrolls past it. `top` clears nothing in
   * particular because this site's masthead does not float - it is a plain
   * offset so the heading is not flush against the viewport edge. */
  .author-life__thesis {
    position: sticky;
    top: var(--space-5);
  }
}

.author-life__thesis-title {
  margin: 0 0 var(--space-4);
  font-size: var(--text-2xl);
  line-height: var(--leading-tight);
}

/* The same trailing gold rule the homepage bands and the credentials heading
 * carry, so the page reads as one system. Decorative and generated: never
 * text, never announced. */
.author-life__thesis-title::after {
  content: "";
  display: block;
  width: 2.5rem;
  height: 3px;
  margin-top: var(--space-3);
  background: linear-gradient(90deg, var(--color-golden-accent), rgb(191 155 48 / 0.15));
  border-radius: var(--radius-full);
}

.author-life__thesis-body {
  margin: 0;
  color: var(--text-secondary);
  max-width: var(--measure);
}

.author-life__prose {
  max-width: var(--measure);
}

/* --- The drop cap ---------------------------------------------------------
 * `::first-letter` on the FIRST paragraph only, which is what makes this safe
 * to apply to operator-written prose: the selector cannot match anything the
 * editor types, so there is no markup they could write that turns a second
 * paragraph into a second drop cap.
 *
 * NOT `initial-letter`, which is the property actually designed for this and is
 * still unimplemented in Firefox. `float` plus a line height is the spelling
 * that has worked in every browser for twenty years.
 *
 * ⚠️ THIS RULE CANNOT BE VERIFIED BY THIS PROJECT'S TEST BROWSER, and that is
 * measured rather than assumed. Obscura 0.2.1 does not implement
 * `::first-letter` at all: injecting `font-size: 10em` on it changes the
 * paragraph's height by zero pixels, while injecting `padding-top: 100px` on
 * the same paragraph moves it by exactly 100 - so the stylesheet is being
 * applied and the pseudo-element is being ignored. (`::before` and `::after`
 * ARE implemented: the same probe grows the pull quote from 29px to 149px. What
 * Obscura cannot do is REPORT a pseudo-element's computed style - it returns
 * the element's own - which is why no test in this repository asserts one.)
 *
 * KEPT ANYWAY, which is a deliberate departure from the rule 0.27.0 set when it
 * deleted the CSS counter, so the difference is stated: that counter rendered a
 * visible "0" three times over and the numeral carried the list's ORDERING, so
 * being wrong meant publishing wrong information in a prominent gold disc. A
 * drop cap that does not apply is a normal capital letter at the start of a
 * paragraph. The failure mode is invisible and carries no meaning, so the cost
 * of being wrong is a cosmetic one rather than an untrue one. Nothing asserts
 * it; nobody should add a test that appears to.
 *
 * NO CONTRAST CONCERN: it is the same colour as the paragraph it belongs to,
 * larger. A gold drop cap would be --color-gold-text at 4.54:1 on a white band
 * and the margin is not there to spend on an ornament. */
.author-life__prose .author__bio > p:first-child::first-letter {
  float: left;
  margin: 0.05em var(--space-2) 0 0;
  font-family: var(--font-heading);
  font-size: 3.2em;
  line-height: 0.82;
  font-weight: 600;
  color: var(--text-primary);
}

/* --- The pull quote -------------------------------------------------------
 * Rules above and below rather than a bar down the left, which is the same
 * decision the essay page made in 0.28.0 and for the same reason: a left bar
 * reads as a nested aside, and this is the practitioner's own voice raised,
 * not a digression from it. */
.author-life__quote {
  margin: var(--space-6) 0;
  padding: var(--space-5) 0;
  border-top: 2px solid var(--color-golden-accent);
  border-bottom: 1px solid var(--border-subtle);
}

/* The quotation marks are GENERATED, which is why the admin help text tells the
 * editor not to type them: typed and generated together give ""like this"".
 * They are decoration on a <blockquote>, which already carries the semantics a
 * screen reader announces, so nothing is lost by their being CSS. */
.author-life__quote blockquote {
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--text-xl);
  line-height: var(--leading-tight);
  font-style: italic;
}

.author-life__quote blockquote::before { content: "\201C"; }
.author-life__quote blockquote::after  { content: "\201D"; }

.author-life__quote figcaption {
  margin-top: var(--space-3);
  color: var(--text-secondary);
  font-size: var(--text-sm);
}

/* An em dash before the attribution, generated so the editor types a name and
 * gets a citation. */
.author-life__quote figcaption::before {
  content: "\2014\00a0";
}
