/* ==========================================================================
   FAMILY TREE DENTAL — team.css
   The Our Team page's own four sections, and nothing else.
   ---------------------------------------------------------------------------
   Loaded after style.css and system.css, which between them have already
   supplied the tokens, the nav pill, the buttons, the eyebrow, the headline
   mask, the floats and every shared section this page calls. What is here is
   only what those two do not have:

     01. The hero            a split with an organic photograph
     02. The introduction    one paragraph in a lot of air
     03. The dentists        alternating editorial rows, not a card grid
     04. The editorial beat  three words, three speeds
     05. The wave            the seam into the footer
     06. Entry states        for this page's own reveal channels
     07. Responsive
     08. Reduced motion

   THE ENTRY STATES ARE IN SECTION 06, NOT IN THE JAVASCRIPT — the same
   arrangement system.css section 04 uses, and for the same reason: an element
   hidden by a script is an element that is briefly visible first. Everything
   this page animates is hidden here and un-hidden by `.no-js`, so a missing
   CDN leaves a complete, readable page rather than an empty one.
   ========================================================================== */


/* ==========================================================================
   01. THE HERO
   ---------------------------------------------------------------------------
   The same editorial split the service pages use, tuned for a two-word title
   and a landscape photograph rather than a treatment name and a portrait.
   ========================================================================== */
.tm-hero {
  position: relative;
  isolation: isolate;
  /* `clip` rather than `hidden`: `hidden` on a section this tall makes it a
     scroll container, which changes what `position: sticky` means below it. */
  overflow: clip;
  padding-top: calc(var(--util-h) + var(--nav-h) + var(--hero-inset) + var(--hero-pad) + clamp(1.5rem, 5vh, 3.5rem));
  padding-bottom: clamp(3.5rem, 9vh, 7rem);
  background:
    radial-gradient(90% 70% at 92% 4%, rgba(214, 232, 251, .8) 0%, rgba(214, 232, 251, 0) 58%),
    linear-gradient(168deg, var(--sv-ivory) 0%, #f6f5f2 38%, #eef5fd 100%);
}

.tm-hero__aura {
  position: absolute;
  top: -20%;
  right: -12%;
  z-index: -2;
  width: min(48vw, 660px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 40% 38%,
              rgba(127, 227, 212, .34) 0%,
              rgba(110, 178, 244, .22) 42%,
              rgba(110, 178, 244, 0) 70%);
  filter: blur(18px);
  pointer-events: none;
}

/* Grain, not copy. Most of the word sits below the section's floor; what
   shows is the top of the letterforms along the seam. */
.tm-hero__word {
  position: absolute;
  left: -0.06em;
  bottom: -0.46em;
  z-index: -1;
  font-family: var(--f-display);
  font-size: clamp(6rem, 19vw, 17rem);
  font-style: italic;
  line-height: .8;
  letter-spacing: -0.03em;
  color: rgba(11, 45, 82, .038);
  white-space: nowrap;
  pointer-events: none;
  user-select: none;
}

.tm-hero__inner {
  position: relative;
  z-index: 1;
  width: var(--sv-shell);
  margin-inline: auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  gap: clamp(2rem, 4.5vw, 4.5rem);
}

.tm-hero__copy .sv-eyebrow { margin-top: clamp(1rem, 2.5vh, 1.6rem); }

.tm-hero__title {
  position: relative;
  /* Shrink-to-fit so the accent rule ends where the word does, but still
     block-level so the strapline below cannot share its line box. */
  width: max-content;
  max-width: 100%;
  margin-top: clamp(.9rem, 2vh, 1.4rem);
  font-family: var(--f-display);
  font-size: clamp(3.2rem, 1rem + 8.5vw, 7.5rem);
  font-weight: 400;
  line-height: .96;
  letter-spacing: -0.024em;
  color: var(--c-ink);
}

.tm-hero__tag {
  margin-top: clamp(.7rem, 1.6vh, 1.1rem);
  font-family: var(--f-display);
  font-style: italic;
  font-size: clamp(1.05rem, .9rem + .5vw, 1.4rem);
  color: var(--sv-navy-2);
}

.tm-hero__lede {
  max-width: 46ch;
  margin-top: clamp(.9rem, 2vh, 1.35rem);
  font-size: clamp(1rem, .96rem + .18vw, 1.1rem);
  line-height: 1.65;
  color: rgba(11, 45, 82, .74);
}

.tm-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  margin-top: clamp(1.4rem, 3.4vh, 2.2rem);
}

/* --- The photograph ------------------------------------------------------ */
.tm-hero__media { position: relative; }

/* THE ORGANIC EDGE. Four different corner radii, which is what stops it
   reading as "a rounded rectangle" — the shape is asymmetric enough to look
   drawn and regular enough to still look deliberate. */
.tm-hero__frame {
  position: relative;
  margin: 0;
  overflow: hidden;
  aspect-ratio: 20 / 17;
  border-radius: 46% 54% 42% 58% / 38% 34% 66% 62%;
  box-shadow: 0 20px 50px rgba(11, 45, 82, .14), 0 60px 120px rgba(11, 45, 82, .12);
}
.tm-hero__photo {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 32%;
  /* Oversized inside the frame; team.js settles it to 1 as the mask passes,
     so the panel reads as a camera arriving rather than a picture appearing. */
  will-change: transform;
}
.tm-hero__grade {
  position: absolute;
  inset: 0;
  background: linear-gradient(196deg, rgba(6, 33, 58, 0) 42%, rgba(6, 33, 58, .28) 100%);
  pointer-events: none;
}

/* THE TWO FLOATING CARDS NEED THEIR OWN COORDINATES HERE.
   `.sv-float` is absolutely positioned by system.css but deliberately carries
   no offsets — every page places its own, and the ones for `--tl` live in
   service-detail.css and services-hub.css, neither of which this page loads.
   Without these two rules both cards fall back to `auto` on all four sides,
   which puts them at their static position and stacks them on top of each
   other under the photograph. */
.tm-hero .sv-chip--float {
  position: absolute;
  top: clamp(1.5rem, 5vw, 3.5rem);
  left: clamp(-1.5rem, -1.5vw, -0.5rem);
  z-index: 3;
}

.tm-hero__float {
  top: auto;
  bottom: clamp(1rem, 3vw, 2.5rem);
  left: clamp(-3rem, -3.5vw, -1rem);
  width: min(16rem, 74%);
}


/* ==========================================================================
   02. THE INTRODUCTION
   ---------------------------------------------------------------------------
   One eyebrow, one heading, one paragraph, and a great deal of nothing. It is
   the beat between the hero and the portraits; the whitespace IS the design.
   ========================================================================== */
.tm-intro {
  position: relative;
  padding-block: clamp(4.5rem, 12vh, 9rem) clamp(3rem, 8vh, 6rem);
  background: linear-gradient(180deg, #eef5fd 0%, var(--sv-ivory) 62%);
}

.tm-intro__inner {
  width: min(58rem, 100% - 2 * var(--gutter));
  margin-inline: auto;
  text-align: center;
}
/* The eyebrow is a flex row with a drawn rule; centring the block is not
   enough to centre its contents. */
.tm-intro .sv-eyebrow { justify-content: center; }

.tm-intro__title {
  margin-top: clamp(.8rem, 2vh, 1.2rem);
  font-size: clamp(2.1rem, 1.1rem + 3.1vw, 3.6rem);
  line-height: 1.08;
}

.tm-intro__lede {
  max-width: 54ch;
  margin: clamp(1.2rem, 3vh, 1.9rem) auto 0;
  font-size: clamp(1.02rem, .97rem + .22vw, 1.16rem);
  line-height: 1.75;
  color: rgba(11, 45, 82, .74);
}


/* ==========================================================================
   03. THE DENTISTS
   ---------------------------------------------------------------------------
   NOT a two-column grid of equal cards. Each doctor is a full-width row whose
   photograph and copy swap sides, and the second row sits lower than the
   first, so the eye travels down a diagonal instead of across a table.

   `data-side` comes from the loop index in PHP, so a third doctor added to
   config.php lands on the correct side and enters from the correct direction
   with no new rule here and no new line in team.js.
   ========================================================================== */
.tm-docs {
  position: relative;
  isolation: isolate;
  overflow: clip;
  padding-block: clamp(2rem, 6vh, 4rem) clamp(4.5rem, 12vh, 9rem);
  background: var(--sv-ivory);
}

/* The thread. One hairline down the middle, drawn by team.js as the section
   is crossed, tying the two portraits into one composition. Hidden below the
   breakpoint where the rows stop alternating and it would just be a line. */
.tm-docs__thread {
  position: absolute;
  top: 0;
  left: 50%;
  z-index: -1;
  width: 1px;
  height: 100%;
  background: linear-gradient(180deg,
              rgba(120, 170, 225, 0) 0%,
              rgba(120, 170, 225, .5) 12%,
              rgba(120, 170, 225, .5) 88%,
              rgba(120, 170, 225, 0) 100%);
  transform-origin: 50% 0;
  pointer-events: none;
}

.tm-docs__inner {
  width: var(--sv-shell);
  margin-inline: auto;
  display: grid;
  gap: clamp(4rem, 11vh, 8.5rem);
}

.tm-doc {
  display: grid;
  grid-template-columns: minmax(0, .88fr) minmax(0, 1.12fr);
  align-items: center;
  gap: clamp(1.75rem, 5vw, 4.5rem);
}
/* The swap. `order` and not a second grid definition, so the DOM order stays
   photograph-then-copy for a screen reader on every row. */
.tm-doc[data-side="right"] .tm-doc__media { order: 2; }
.tm-doc[data-side="right"] .tm-doc__copy  { order: 1; }
/* The drop that makes it a diagonal. Margin and not transform — team.js owns
   the transforms on everything inside this row. */
.tm-doc[data-side="right"] .tm-doc__media { margin-top: clamp(0rem, 5vh, 3.5rem); }

/* --- The portrait -------------------------------------------------------- */
.tm-doc__media { position: relative; }

.tm-doc__halo {
  position: absolute;
  inset: -8% -6% -10% -8%;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(circle at 46% 40%,
              rgba(127, 227, 212, .3) 0%,
              rgba(110, 178, 244, .18) 46%,
              rgba(110, 178, 244, 0) 72%);
  filter: blur(14px);
  pointer-events: none;
}

/* Organic, and mirrored on the alternate row so the two portraits are a pair
   rather than a repeat. */
.tm-doc__frame {
  position: relative;
  margin: 0;
  overflow: hidden;
  aspect-ratio: 1;
  border-radius: 52% 48% 56% 44% / 46% 52% 48% 54%;
  /* BOTH HEADSHOTS CARRY THEIR OWN OPAQUE WHITE STUDIO BACKGROUND — only the
     top corners are transparent — so there is no tint that can show through
     and no colour to put behind them. Fighting that (blend modes, a coloured
     ground) muddies two real people's skin tones to solve a problem nobody
     has. The disc is white to match the photograph exactly, so there is no
     seam where the two meet, and it is given a rim and a shadow to read as a
     deliberate studio portrait rather than a pale shape on a pale page. The
     colour is supplied BEHIND it by .tm-doc__halo.

     Swap in photography with a real background and this is one edit. */
  background: linear-gradient(178deg, #ffffff 0%, #ffffff 62%, #f4f9ff 100%);
  box-shadow:
    inset 0 0 0 1px rgba(120, 170, 225, .34),
    0 18px 44px rgba(11, 45, 82, .13),
    0 48px 96px rgba(11, 45, 82, .1);
}
.tm-doc[data-side="right"] .tm-doc__frame {
  border-radius: 48% 52% 44% 56% / 52% 46% 54% 48%;
}

.tm-doc__photo {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 28%;
  transition: transform 1.1s var(--ease-out);
}
/* Elegant, not aggressive. 1.04, and the veil comes up to meet it. */
.tm-doc:hover .tm-doc__photo,
.tm-doc:focus-within .tm-doc__photo { transform: scale(1.04); }

/* Kept light. A heavy scrim over a white studio background turns the bottom
   of the disc into a grey smudge rather than reading as shade. */
.tm-doc__veil {
  position: absolute;
  inset: 0;
  background: linear-gradient(190deg, rgba(26, 114, 214, 0) 52%, rgba(26, 114, 214, .14) 100%);
  opacity: 0;
  transition: opacity var(--t-med) var(--ease-out);
  pointer-events: none;
}
.tm-doc:hover .tm-doc__veil,
.tm-doc:focus-within .tm-doc__veil { opacity: 1; }

/* The index. Set in the display face at a size that reads as a graphic mark
   rather than as a number you are meant to count with. */
.tm-doc__n {
  position: absolute;
  top: -.18em;
  right: -.04em;
  z-index: 2;
  font-family: var(--f-display);
  font-size: clamp(3.2rem, 7vw, 6rem);
  font-style: italic;
  line-height: 1;
  color: rgba(11, 45, 82, .1);
  pointer-events: none;
  user-select: none;
}
.tm-doc[data-side="right"] .tm-doc__n { right: auto; left: -.04em; }

/* --- The copy ------------------------------------------------------------ */
.tm-doc__role {
  font-size: .78rem;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--c-blue-700);
}

.tm-doc__name {
  margin-top: .35rem;
  font-family: var(--f-display);
  font-size: clamp(1.9rem, 1.15rem + 2.3vw, 3.1rem);
  font-weight: 400;
  line-height: 1.06;
  letter-spacing: -0.018em;
  color: var(--c-ink);
}

.tm-doc__rule {
  display: block;
  width: clamp(3rem, 7vw, 5.5rem);
  height: 2px;
  margin-top: clamp(.9rem, 2vh, 1.3rem);
  background: linear-gradient(90deg, var(--c-blue-700), rgba(127, 227, 212, .9));
  border-radius: 2px;
  transform-origin: 0 50%;
}

.tm-doc__bio {
  max-width: 52ch;
  margin-top: clamp(1rem, 2.4vh, 1.5rem);
  font-size: clamp(1rem, .96rem + .18vw, 1.08rem);
  line-height: 1.75;
  color: rgba(11, 45, 82, .74);
}

.tm-doc__actions { margin-top: clamp(1.2rem, 2.8vh, 1.8rem); }
/* The arrow travels on hover; the underline is the .sv-link's own. */
.tm-doc__cta svg { transition: transform var(--t-med) var(--ease-out); }
.tm-doc__cta:hover svg { transform: translateX(5px); }


/* ==========================================================================
   04. THE EDITORIAL BEAT
   ---------------------------------------------------------------------------
   Three words from the practice's own messaging at a size that makes them
   architecture. They move at three different speeds as the section crosses
   the viewport, which is the whole of the effect — there is nothing to read
   here that the rest of the page has not already said.
   ========================================================================== */
.tm-say {
  position: relative;
  isolation: isolate;
  overflow: clip;
  padding-block: clamp(4.5rem, 14vh, 10rem);
  background: linear-gradient(180deg, var(--sv-ivory) 0%, #e9f2fd 45%, #eaf3fd 100%);
}

.tm-say__inner {
  width: var(--sv-shell);
  margin-inline: auto;
  text-align: center;
}

.tm-say__title {
  margin: 0;
  font-family: var(--f-display);
  font-size: clamp(2.4rem, .8rem + 8vw, 7rem);
  font-weight: 400;
  line-height: 1.02;
  letter-spacing: -0.028em;
  color: var(--c-ink);
}

.tm-say__w {
  display: block;
  /* Each word gets its own row and its own speed. `will-change` is set only
     on these three, because they are the only elements in the section that a
     scrub writes to every frame. */
  will-change: transform;
}
.tm-say__w[data-say="1"] { color: var(--c-blue-700); font-style: italic; }
.tm-say__w[data-say="2"] { color: rgba(11, 45, 82, .42); }

.tm-say__note {
  margin-top: clamp(1.2rem, 3vh, 2rem);
  font-family: var(--f-display);
  font-style: italic;
  font-size: clamp(1rem, .94rem + .3vw, 1.25rem);
  color: rgba(11, 45, 82, .6);
}


/* ==========================================================================
   05. (WAS THE WAVE)
   ---------------------------------------------------------------------------
   REMOVED FROM THE WHOLE SITE. The coloured band that used to sit between the
   last section and the footer is gone from every page, along with its
   component, its rules in system.css and the scrub in each page controller.

   Every page now closes the way this one always did: the last section meets
   the footer's own top edge, and that edge is the transition.
   ========================================================================== */


/* ==========================================================================
   06. ENTRY STATES — this page's own reveal channels
   ---------------------------------------------------------------------------
   system.css section 04 already hides [data-sv] and [data-sv-mask] on every
   page. These are the four channels that only exist here. Same contract: the
   start state is authored in CSS so nothing flashes, and `.no-js` returns
   every one of them to its finished state.
   ========================================================================== */
[data-doc-mask]  { clip-path: inset(0% 0% 100% 0%); }
[data-doc-item]  { opacity: 0; }
.tm-doc__n       { opacity: 0; }
.tm-doc__rule    { transform: scaleX(0); }
.tm-docs__thread { transform: scaleY(0); }

.no-js [data-doc-mask]  { clip-path: none; }
.no-js [data-doc-item]  { opacity: 1; }
.no-js .tm-doc__n       { opacity: 1; }
.no-js .tm-doc__rule    { transform: none; }
.no-js .tm-docs__thread { transform: none; }


/* ==========================================================================
   07. RESPONSIVE
   ========================================================================== */
@media (max-width: 1180px) {
  .tm-hero__inner { gap: clamp(1.5rem, 3.5vw, 3rem); }
  .tm-doc { grid-template-columns: minmax(0, .95fr) minmax(0, 1.05fr); }
}

/* The split becomes a stack. Copy first on every row — the name tells you
   whose portrait you are looking at, so it cannot come second. */
@media (max-width: 980px) {
  .tm-hero__inner { grid-template-columns: minmax(0, 1fr); gap: clamp(2.25rem, 6vw, 3.5rem); }
  .tm-hero__frame { aspect-ratio: 16 / 11; border-radius: var(--sv-r-xl); }
  .tm-hero__title { font-size: clamp(3rem, 1rem + 11vw, 5.5rem); }
  .tm-hero__lede  { max-width: 62ch; }
  .tm-hero__word  { display: none; }

  /* The cards come inside the frame — there is no margin left to hang off. */
  .tm-hero .sv-chip--float { left: clamp(.75rem, 2vw, 1.25rem); }
  .tm-hero__float         { left: clamp(.75rem, 2vw, 1.25rem); width: min(17rem, 76%); }

  .tm-docs__thread { display: none; }
  .tm-docs__inner  { gap: clamp(3rem, 8vh, 5rem); }

  .tm-doc { grid-template-columns: minmax(0, 1fr); gap: clamp(1.5rem, 5vw, 2.25rem); }
  .tm-doc__media,
  .tm-doc[data-side="right"] .tm-doc__media { order: 2; margin-top: 0; }
  .tm-doc__copy,
  .tm-doc[data-side="right"] .tm-doc__copy  { order: 1; }

  /* A square portrait at full column width is most of a phone screen. */
  .tm-doc__frame,
  .tm-doc[data-side="right"] .tm-doc__frame {
    max-width: 26rem;
    aspect-ratio: 5 / 4;
    border-radius: var(--sv-r-xl);
  }
  .tm-doc__n,
  .tm-doc[data-side="right"] .tm-doc__n { top: auto; bottom: -.1em; right: .1em; left: auto; }
}

@media (max-width: 560px) {
  .tm-hero__title { font-size: clamp(2.7rem, 1rem + 13vw, 4rem); }
  .tm-hero__float { display: none; }          /* two floating cards is one too many here */
  .tm-intro       { padding-block: clamp(3.25rem, 9vh, 5rem) clamp(2.25rem, 6vh, 3.5rem); }
  .tm-doc__frame,
  .tm-doc[data-side="right"] .tm-doc__frame { max-width: none; aspect-ratio: 4 / 3; }
  /* The index has nowhere left to sit. At this width the photograph reaches
     both edges, so the numeral can only land ON it — where a 10%-opacity
     serif reads as a printing fault rather than as a device. It is
     decorative and aria-hidden, so it simply goes. */
  .tm-doc__n,
  .tm-doc[data-side="right"] .tm-doc__n { display: none; }
  .tm-say__title  { letter-spacing: -0.02em; }
}

/* 360px. The narrowest screen the site is expected to meet. */
@media (max-width: 400px) {
  .tm-hero__actions .btn { width: 100%; justify-content: center; }
  .tm-say__title { font-size: clamp(2rem, 9.5vw, 2.6rem); }
}


/* ==========================================================================
   08. REDUCED MOTION
   ---------------------------------------------------------------------------
   team.js already returns before it builds a single timeline when the query
   matches, which leaves every element in the finished state authored above.
   What is left for CSS is the motion that is NOT team.js's: the hover crops,
   the veil and the float keyframes.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  [data-doc-mask]  { clip-path: none; }
  [data-doc-item]  { opacity: 1; }
  .tm-doc__n       { opacity: 1; }
  .tm-doc__rule    { transform: none; }
  .tm-docs__thread { transform: none; }

  .tm-doc__photo,
  .tm-doc__veil { transition: none; }
  .tm-doc:hover .tm-doc__photo,
  .tm-doc:focus-within .tm-doc__photo { transform: none; }
  .tm-hero__photo { will-change: auto; }
  .tm-say__w      { will-change: auto; }
}
