/* =========================================================================
   Troutwood company page
   Same field, same tokens, same rhythm as the rest of the site. Everything
   here is additive: tokens, primitives, nav, footer, hero, the trust panel
   and the close all come from tw-system.css. Organised by section, in page
   order.

   Three things needed styles of their own: the grade on the hero's own
   photograph, the three columns of what we build, and the team roster with its
   bio modals. Nothing else did.
   ========================================================================= */

/* -------------------------------------------------------------------------
   01. The hero scene
   The photograph behind the hero is the system's .field__scene, declared in
   the markup and driven by tw-field.js exactly as the homepage's is. What is
   here is the grade, which is the one part of it that cannot be shared,
   because a grade is cut against the picture it is laid over and there are now
   two pictures.

   Both rules below were measured rather than judged: every pixel of the built
   crop composited through the scrim, the tone pull and the foot fade the way
   the browser will, and read for the worst white-on-scene contrast anywhere in
   the copy's own column. The numbers quoted are that measurement.
   ------------------------------------------------------------------------- */

/* Landscape: the scrim, lighter.

   The system default is tuned for a gorge at first light — a photograph with a
   sun in it, whose left third the copy has to be protected from. This one
   arrives dark. Its left half means 6,31,21, which is #0c1f14 to within a
   point on every channel: the exact top of the page's own base gradient,
   already the tone a scrim would be pulling it to. Laying 0.86 over that
   protects nothing the picture has not already protected — it flattens the
   frame's own left-to-right ramp, which is the composition. Light arriving
   from the right is what this picture is for, and a scrim heavy enough to
   erase it leaves a rectangle of ground with a bright corner.

   So: lighter at the left edge, and carried further across before it lets go,
   because the light here starts at the frame's own centre rather than at two
   thirds. The worst pixel inside the copy's 52vw is the piece's top corner at
   the column's right edge, and this holds it at 5.6:1 against white on a 4.5:1
   bar — 5.57 at 16:9, 5.61 at 4:3, 5.55 at 21:9, the spread being the whole
   difference `cover` makes across every landscape aspect there is. Nothing in
   the column is under the bar at any of them. Past it the scrim is gone by
   86%, and the piece's own highlight lands at 217 of 255.

   The foot fade is the system's, restated because `background` is one property
   and this is the shorthand: it is what hands the scene off to the dark rather
   than ending it at an edge, and this frame's own foot is dark enough that it
   barely has to work.

   The media query is load-bearing rather than descriptive. This stylesheet
   comes after tw-system.css and a media query carries no specificity of its
   own, so an unscoped `.field__scene::after` here would win in portrait too
   and lay a horizontal scrim across a vertical photograph. */
@media (orientation: landscape) {
  .field__scene::after {
    background:
      linear-gradient(to bottom, transparent 62%, rgba(7, 18, 9, 0.66) 88%, var(--forest-950) 100%),
      linear-gradient(
        96deg,
        rgba(7, 18, 9, 0.58) 0%,
        rgba(7, 18, 9, 0.5) 26%,
        rgba(7, 18, 9, 0.34) 48%,
        rgba(7, 18, 9, 0.12) 68%,
        transparent 86%
      );
  }
}

/* Portrait: the tone, heavier. The scrim is left to the system.

   Portrait puts the copy *over* the picture instead of beside it, and this
   frame cannot be cropped out of the way of that. Its lit face sits above its
   own centre, at y 0.28-0.40 with specular highlights at a flat 255, and every
   1:2 rectangle this source holds puts them behind the headline: pushing them
   down means cutting height, cutting height means cutting width to match, and
   the crop that finally clears the copy is 238px wide. Cropping sideways into
   the dark half instead buys the contrast honestly and spends the picture to
   do it — the frame's left is a smooth ramp with nothing in it, so the phone
   would carry 29KB to show what the base gradient already shows.

   So the picture stays whole and the whole picture comes down. --scene-tone is
   the system's knob for exactly this: a flat pull toward the page's ground,
   which compresses the frame's range without touching the relationships inside
   it — the piece is still a lit piece over a dark ground, it is just further
   away. At 0.55 the worst pixel in a phone hero is 4.80:1 and nothing in the
   frame is under the bar, against 1.67:1 at the system's 0.16.

   A scrim reshaped to do the same job would have to hold a veil over the whole
   frame to catch highlights that are spread down two thirds of it, which is
   this pull with a gradient's worth of extra machinery in front of it. */
@media (orientation: portrait) {
  .field__scene {
    --scene-tone: 0.55;
  }
}

/* -------------------------------------------------------------------------
   02. What we build
   Three columns, a line each, and the things a reader can actually go and
   open. The legacy about page carried the full capability inventory here in
   three long lists; an about page is not a product spec, so what is left is
   the shape of the product and the links out of it.
   ------------------------------------------------------------------------- */

.craft__body {
  margin-top: 1.75rem;
  font-size: var(--step-lead);
  line-height: 1.55;
  color: var(--text-secondary);
}

.craft__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: clamp(2rem, 4vw, 3rem);
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
}

/* One sage edge across the top of each column. Three of them in a row is
   what makes the set read as three of one thing rather than three sections
   that happen to be beside each other. */
.craft__col {
  padding-top: clamp(1.25rem, 2.5vw, 1.75rem);
  border-top: 2px solid var(--sage);
}

.craft__lead {
  margin-top: 0.625rem;
  font-size: var(--step-small);
  line-height: 1.55;
  color: var(--text-secondary);
}

.craft__list {
  display: grid;
  gap: 0.5rem;
  margin-top: clamp(1.125rem, 2.5vw, 1.375rem);
  font-size: var(--step-small);
  line-height: 1.45;
  color: var(--text-tertiary);
}

/* Hanging indent: a wrapped second line clears the dot rather than running
   back under it. */
.craft__list li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: 0.5rem;
}

.craft__list li::before {
  content: '';
  width: 5px;
  height: 5px;
  margin-top: 0.55em;
  border-radius: 50%;
  background: var(--sage);
  box-shadow: 0 0 10px var(--accent-glow);
}

/* Links keep the global sage and their underline, which is the only thing
   separating the items that go somewhere from the items that do not. */
.craft__list a:hover {
  color: var(--text-primary);
}

/* -------------------------------------------------------------------------
   03. The team
   A roster: face, name, title. Everything else is in the dialog.

   Ten bios laid out in the scroll is three screens of prose nobody reads,
   and expanded in place inside a fifth of the container they set at a
   22-character measure. So the card carries only what identifies a person
   and the biography opens over the page.
   ------------------------------------------------------------------------- */

.crew__body {
  margin-top: 1.75rem;
  font-size: var(--step-lead);
  line-height: 1.55;
  color: var(--text-secondary);
}

.crew__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 12.5rem), 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
}

/* One <a> around the whole tile, on the homepage router card's pattern: the
   entire card is the target, and it is keyboard reachable in DOM order and
   activates on Enter with nothing bound to it. */
.crew__card {
  display: grid;
  align-content: start;
  justify-items: center;
  gap: 0.3125rem;
  padding: clamp(1.25rem, 2.5vw, 1.75rem) clamp(1rem, 2vw, 1.25rem);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  color: inherit;
  text-align: center;
  text-decoration: none;
  transition: background-color 200ms var(--ease), border-color 200ms var(--ease),
    transform 200ms var(--ease);
}

.crew__card:hover {
  background: var(--surface-hi);
  border-color: var(--rule-strong);
  transform: translateY(-2px);
}

.crew__photo {
  width: clamp(84px, 11vw, 132px);
  height: clamp(84px, 11vw, 132px);
  margin-bottom: 0.75rem;
  border-radius: 50%;
  border: 1px solid var(--rule-strong);
  object-fit: cover;
}

/* Smaller than the global h3, because in a 200px card a fluid 21px name sets
   "Evimar Principal de Soto" on four lines and pushes the row apart. */
.crew__name {
  font-size: 1.0625rem;
  line-height: 1.25;
}

.crew__title {
  font-size: var(--step-small);
  line-height: 1.35;
  color: var(--text-secondary);
}

.crew__cue {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  margin-top: 0.625rem;
  font-size: var(--step-eyebrow);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sage-bright);
}

.crew__caret {
  width: 10px;
  height: 10px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  transition: transform 200ms var(--ease);
}

.crew__card:hover .crew__caret {
  transform: translateX(2px);
}

/* -------------------------------------------------------------------------
   04. The bio modal
   One <dialog> per person, opened with showModal() where there is script and
   presented by `:target` where there is not. Both states are styled through
   the same selector list, so the panel is written once.

   The dialog element is the full-viewport layer and the panel inside it is
   the card. That split is what makes a click outside the panel land on the
   dialog itself, which is all the dismiss handler in tw-company.js tests.
   ------------------------------------------------------------------------- */

.bio {
  /* Reset the UA's centred, bordered box. Placement is the two blocks below:
     a sheet at the bottom on a phone, a centred card above that. */
  width: 100%;
  max-width: none;
  max-height: none;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--text-primary);
  overflow: hidden;
}

/* The no-JS path. A dialog without `open` is display:none, so the anchor
   needs this to show anything at all, and it needs to be fixed because it is
   not in the top layer the way showModal() would put it. The two never
   overlap: with script the hash never changes, without it `open` is never
   set. */
.bio:target {
  display: flex;
  position: fixed;
  inset: 0;
  z-index: 120;
}

.bio[open] {
  display: flex;
  /* Explicit rather than inherited from the UA's `dialog:modal` block, which
     sets the block insets and leaves the inline ones to the base rule. */
  position: fixed;
  inset: 0;
}

/* The scrim. `::backdrop` is the top layer's own and only exists for
   showModal(); the pseudo-element repeats it for the `:target` path. */
.bio::backdrop {
  background: rgba(4, 12, 7, 0.72);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  animation: bio-scrim 240ms var(--ease-out);
}

.bio:target::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  background: rgba(4, 12, 7, 0.72);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

@keyframes bio-scrim {
  from {
    opacity: 0;
  }
}

.bio__panel {
  position: relative;
  width: 100%;
  padding: clamp(1.75rem, 4vw, 2.75rem);
  background: linear-gradient(140deg, rgba(31, 68, 48, 0.96), rgba(9, 22, 14, 0.98));
  border: 1px solid var(--rule-strong);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.bio__close {
  position: absolute;
  top: clamp(0.75rem, 2vw, 1rem);
  right: clamp(0.75rem, 2vw, 1rem);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  color: var(--text-secondary);
  text-decoration: none;
  transition: background-color 200ms var(--ease), color 200ms var(--ease);
}

.bio__close svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
}

.bio__close:hover {
  background: rgba(255, 255, 255, 0.08);
  color: var(--text-primary);
}

.bio__head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  column-gap: clamp(1rem, 2.5vw, 1.5rem);
  /* Clears the close control, so a long title never runs under it. */
  padding-right: 2.5rem;
}

.bio__photo {
  width: 96px;
  height: 96px;
  border-radius: 50%;
  border: 1px solid var(--rule-strong);
  object-fit: cover;
}

.bio__name {
  font-size: var(--step-h3);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.015em;
}

.bio__title {
  margin-top: 0.25rem;
  font-size: var(--step-small);
  line-height: 1.35;
  color: var(--text-secondary);
}

.bio__place {
  margin-top: 0.375rem;
  font-size: var(--step-eyebrow);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sage-bright);
}

.bio__body {
  margin-top: clamp(1.25rem, 3vw, 1.75rem);
  padding-top: clamp(1.25rem, 3vw, 1.75rem);
  border-top: 1px solid var(--rule);
  font-size: var(--step-small);
  line-height: 1.65;
  color: var(--text-secondary);
}

.bio__body p + p {
  margin-top: 0.875rem;
}

/* ---- Phone: a sheet ------------------------------------------------------
   Bottom-anchored and full width, rising into place. The strip of scrim left
   above it is deliberate: it is what tells a thumb the page is still there
   and that this can be dismissed by reaching past it. */
.bio {
  align-items: flex-end;
  justify-content: center;
}

.bio__panel {
  max-height: 88svh;
  border-radius: 20px 20px 0 0;
  border-bottom: 0;
  animation: bio-sheet 340ms var(--ease-out);
}

@keyframes bio-sheet {
  from {
    transform: translateY(100%);
  }
}

/* ---- Above that: a centred card ---------------------------------------- */
@media (min-width: 42rem) {
  .bio {
    align-items: center;
    padding: var(--gutter);
  }

  .bio__panel {
    max-width: 44rem;
    max-height: 84svh;
    border-radius: calc(var(--radius) + 8px);
    border-bottom: 1px solid var(--rule-strong);
    box-shadow: 0 40px 80px -32px rgba(2, 8, 4, 0.8);
    animation: bio-card 240ms var(--ease-out);
  }

  @keyframes bio-card {
    from {
      opacity: 0;
      transform: translateY(14px) scale(0.985);
    }
  }
}

@media (max-width: 30rem) {
  .bio__head {
    grid-template-columns: minmax(0, 1fr);
    justify-items: start;
    row-gap: 0.875rem;
  }

  .bio__photo {
    width: 80px;
    height: 80px;
  }
}

/* The page under an open dialog. showModal() makes it inert but not still,
   and a phone scrolling the page behind a sheet reads as the sheet coming
   loose from it.

   On <html> only. The same declaration on <body> would replace its
   `overflow-x: clip` with `hidden`, which makes the body a scroll container
   and is the documented way to break a sticky descendant. */
.is-bio-open {
  overflow: hidden;
}

/* -------------------------------------------------------------------------
   05. Trust
   The panel itself is the homepage's, unchanged. The homepage runs it with a
   visually-hidden heading and nothing above it, so it needs no top margin
   there; here it sits under a visible eyebrow and title, which is what this
   modifier is for.

   Third copy of this rule, after tw-advisors.css and tw-employers.css. It is
   duplicated rather than promoted because moving it would edit two shipped
   pages' stylesheets to fix nothing they have wrong; the right home for it is
   section 15 of tw-system.css whenever those three are next touched together.
   ------------------------------------------------------------------------- */

.trust__panel--titled {
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
}

/* The four commitments used to open on a 2px accent line; they now open on
   the homepage's icon tile instead. The tile carries --sage-bright by
   default, which is the token every small accent uses on the field. This
   panel is inside the paper band, where --sage is 5.7:1 and passes as a
   foreground on its own, so the glyph keeps the exact green the rule it
   replaced was drawn in rather than shifting a shade off it. */
.trust__icon {
  color: var(--sage);
}

/* -------------------------------------------------------------------------
   06. Print
   A dialog prints as nothing at all, so the bios would be missing from a
   printed page entirely. They come back as plain blocks under the roster.
   ------------------------------------------------------------------------- */

@media print {
  .bio {
    display: block;
    position: static;
    height: auto;
    overflow: visible;
    break-inside: avoid;
  }

  .bio::before {
    display: none;
  }

  .bio__panel {
    max-width: none;
    max-height: none;
    padding: 0 0 1.25rem;
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    overflow: visible;
    animation: none;
  }

  .bio__close,
  .crew__cue {
    display: none;
  }
}
