/* ==========================================================================
   Inner page composition — About, Treatments, Contact, Blog
   Shared blocks live in components.css; this file only arranges them.
   ========================================================================== */

/* Small uppercase label that sits above a section heading. */
.section-topper {
  display: block;
  margin-bottom: 8px;
  font-size: var(--topper-font-size, 0.875rem);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--primary);
}

/* --------------------------------------------------------------------------
   Treatments — page lead

   Copy held to a readable measure while the strips underneath it run the full
   container. That difference is the point: the lede is something to read and
   the strips below it are something to scan, and giving them the same width
   would make them look like one block.

   The whole lede used to run to 367px on a 375px phone — 45% of the fold
   spent before the first word of content, in three separately-spaced bands
   (copy, cycle, nav). The three are now one block: the cycle sits tight under
   the paragraph as its caption, and the jump nav's own rule replaces the
   28px of white that used to be all that separated them.
   ----------------------------------------------------------------------- */

.page-lead {
  max-width: 46rem;
  margin-bottom: 0.875rem;
}

.page-lead__title {
  font-size: var(--h1);
  color: var(--color-4);
  margin-bottom: 0.625rem;
}

.page-lead__text {
  margin-bottom: 0;
}

/* Navigation for the sections below. The separation from the lede is the
   rule the nav's own label sits on now, rather than a stack of white — a
   named rule says "the lede ended here, and here is where you can go" in one
   row, which is what 28px of margin was failing to say in twenty-eight. */
.jump-nav {
  margin-top: 0.875rem;
}

/* Pairs with .section--flush-top on the accident banner, the same way
   .section--to-map pairs with the contact map. The banner is orientation, not
   content: it belongs to the block of "here is where you might be going" that
   the lede and the jump nav make up, and a full --section-gap between them
   read as the page proper having already started. */
.section--to-banner {
  margin-bottom: 24px;
}

/* --------------------------------------------------------------------------
   Detail pages — the way back to the index

   A treatment page is a landing page. Most of its traffic arrives from a
   search engine rather than from the site, so a reader can easily have never
   seen the index it belongs to and has no breadcrumb to climb.
   ----------------------------------------------------------------------- */

/* The back link belongs to the content above it, not to the closing call to
   action below it. With a full --section-gap on both sides it sat marooned in
   the middle of a white band — a 46px link with fifty pixels of nothing on
   either side, which reads as a section in its own right rather than as a way
   out of the one that just ended.

   Adjacent margins collapse to the largest positive plus the smallest
   negative, so this resolves against the previous section's --section-gap to
   about 20px above and leaves the full gap below intact. */
.section--back {
  margin-top: calc(20px - var(--section-gap));
}

/* The standing note above the related block on every library page.

   Deliberately the quietest text on the page: muted, a step down in size,
   and pulled tight against the block below so it reads as a footnote on the
   reference material above it rather than as a heading for what follows. It
   is a qualification, not a warning — a boxed caution here would tell the
   reader the page is unreliable, which is the opposite of what it says. */
/* The standing note is about the WHOLE page, and proximity is what says so.

   Two earlier attempts both said something narrower. Tucked tight under the
   last block it read as a footnote to that block — on most library pages the
   FAQ, so it appeared to qualify four questions rather than everything above
   them. Pushed down towards the related block it read as a subtitle of
   "Treatments offered at…".

   What scopes it correctly is a rule across the full column with clear air on
   both sides: a terminator. Everything above the line is the reference page;
   the line closes it; the note sits under the line as its footer. The rule is
   on the section so it spans the column, while the sentence keeps a measure
   it can be read at. */
.section--note {
  padding-top: 28px;
  border-top: 1px solid var(--border);
}

.page-note {
  max-width: 62ch;
  margin: 0;
  font-size: 0.875rem;
  line-height: 1.6;
  /* Body slate at 70%, rather than a new token for one element. */
  color: color-mix(in srgb, var(--text) 70%, var(--surface));
}

.page-note a {
  color: inherit;
  font-weight: 600;
  text-underline-offset: 0.2em;
}

.page-note a:hover,
.page-note a:focus-visible {
  color: var(--primary);
}

/* Padded and pulled back out, for the same reason the treatment rows are:
   four words of text is not a target. This gives it a 44px-tall hit area
   without moving it on the page. */
.back-link {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.625rem 0.75rem;
  margin-inline-start: -0.75rem;
  border-radius: 12px;
  font-weight: 700;
  color: var(--primary);
  transition: background-color var(--transition);
}

.back-link:hover {
  background-color: var(--surface-tint);
  color: var(--primary);
}

.back-link__arrow {
  font-size: 1.25rem;
  line-height: 1;
}

@media only screen and (min-width: 62.5em) {
  .page-lead {
    margin-bottom: 1.125rem;
  }

  .jump-nav {
    margin-top: 1.125rem;
  }
}

/* --------------------------------------------------------------------------
   Treatments — opening hours
   ----------------------------------------------------------------------- */

.hours-list {
  list-style: none;
  display: grid;
  gap: 0;
  margin-bottom: 1.5rem;
}

.hours-list li {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 1rem;
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
}

.hours-list li:first-child {
  border-top: 1px solid var(--border);
}

.hours-list__day {
  font-weight: 700;
  color: var(--color-4);
}

.hours-note {
  font-size: 0.9375rem;
  font-style: italic;
}

/* --------------------------------------------------------------------------
   Contact — form beside the details panel
   ----------------------------------------------------------------------- */

/* One blended panel. Two rounded boxes side by side read as two components
   that happen to be adjacent; the photograph instead dissolves into the
   panel's own surface colour, so the whole thing is a single object. */
.contact-panel {
  position: relative;
  display: grid;
  overflow: hidden;
  border-radius: var(--radius-panel);
  background-color: var(--surface-tint);
}

/* ---------------------------------------------------------------------------
   The blend.

   A mask rather than a gradient laid over the top: an overlay has to be told
   the panel's colour and drifts the moment that token moves, while a mask
   fades the image itself out and lets --surface-tint show through, so the two
   can never disagree. It also cannot accidentally cover the subject.

   The stops approximate smoothstep (3t² − 2t³) rather than ramping linearly.
   CSS cannot ease interpolation between gradient stops, and a linear alpha
   ramp reads as a hard shoulder where the fade begins and a mushy tail where
   it ends — the eye tracks the rate of change, not the value. Nine stops is
   enough to put the curve under banding threshold at these sizes.

   Keep the two ramps mirror images if either is retuned: same curve, one
   vertical and one horizontal.
   ------------------------------------------------------------------------ */
:root {
  --contact-fade-v: linear-gradient(
    to bottom,
    #000 0,
    #000 22%,
    rgba(0, 0, 0, 0.957) 31.75%,
    rgba(0, 0, 0, 0.844) 41.5%,
    rgba(0, 0, 0, 0.684) 51.25%,
    rgba(0, 0, 0, 0.5) 61%,
    rgba(0, 0, 0, 0.316) 70.75%,
    rgba(0, 0, 0, 0.156) 80.5%,
    rgba(0, 0, 0, 0.043) 90.25%,
    transparent 100%
  );
  --contact-fade-h: linear-gradient(
    to right,
    transparent 0,
    rgba(0, 0, 0, 0.043) 7.75%,
    rgba(0, 0, 0, 0.156) 15.5%,
    rgba(0, 0, 0, 0.316) 23.25%,
    rgba(0, 0, 0, 0.5) 31%,
    rgba(0, 0, 0, 0.684) 38.75%,
    rgba(0, 0, 0, 0.844) 46.5%,
    rgba(0, 0, 0, 0.957) 54.25%,
    #000 62%
  );
}

.contact-panel__media {
  display: block;
  /* Wider than the image's own 1.7:1, which is what makes the crop vertical.
     In a box narrower than that, `cover` fills by height and trims the sides
     instead — the whole sky stays in frame and object-position has nothing to
     move. This is the only way to take anything off the top. */
  aspect-ratio: 2 / 1;
  -webkit-mask-image: var(--contact-fade-v);
  mask-image: var(--contact-fade-v);
}

.contact-panel__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Past centre, so the trim comes off the sky rather than off the asphalt.
     The building keeps its full band. */
  object-position: center 72%;
}

.contact-panel__body {
  position: relative;
  z-index: 1;
  padding: 0 25px 30px;
  /* Lifts the heading onto the faded foot of the photograph, where the mask
     has all but resolved to the panel surface — so the title keeps the same
     contrast it would have on the panel proper.

     -3.5rem put it far enough up that it covered the building rather than the
     asphalt below it. The overlap is meant to tie the two halves together, not
     to sit on the subject. */
  margin-top: -2rem;
}

.contact-panel__title {
  margin-bottom: 1.5rem;
}

@media only screen and (min-width: 62.5em) {
  /* Copy sized by its content, with the photograph taking whatever is left
     rather than the reverse.

     Was 25rem, set when this column held five short rows of contact details.
     It now carries the address, the fax and the three directions entries, and
     at 25rem those wrapped every second word. The photograph still has room:
     its mask is transparent for the first 62% of whatever column it gets, so
     the building itself does not come into view until well right of the copy
     however this split moves. */
  .contact-panel {
    grid-template-columns: minmax(0, 31rem) minmax(0, 1fr);
    align-items: stretch;
  }

  .contact-panel__media {
    grid-column: 2;
    grid-row: 1;
    aspect-ratio: auto;
    height: 100%;
    /* Back to centre: the desktop column is tall enough that nothing needs
       shifting, and off-centre here would tilt the building in frame. */
    /* The fade turns horizontal, dissolving the photograph's leading edge
       into the column the copy occupies. It starts on the column boundary,
       so there is no seam to see. */
    -webkit-mask-image: var(--contact-fade-h);
    mask-image: var(--contact-fade-h);
  }

  .contact-panel__media img {
    object-position: center;
  }

  .contact-panel__body {
    grid-column: 1;
    grid-row: 1;
    align-self: center;
    margin-top: 0;
    padding: 40px 30px;
  }
}

a.info-list__value:hover {
  color: var(--color-1);
  text-decoration: underline;
}

/* --------------------------------------------------------------------------
   Contact details — the plain row under the booking panel

   Four labelled facts and nothing else. A row rather than a column because a
   stack of four short values reads as a form to work through, and these are
   four separate answers a reader picks ONE of. See contact-page.html.
   ----------------------------------------------------------------------- */

.info-list--row .info-list__value {
  font-style: normal;
  line-height: 1.5;
}

/* The fax is the one value here that is not a link — see contact-page.html —
   and in the same blue as the three that are, it reads as a link that does
   not work. Navy instead: same weight, same size, plainly not clickable. */
.info-list--row span.info-list__value {
  color: var(--color-4);
}

/* Two up on a tablet, four across on a desktop. Stacked below that, where
   four columns of a street address would be four columns of nothing. */
@media only screen and (min-width: 43.125em) {
  .info-list--row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1.75rem 2rem;
  }
}

@media only screen and (min-width: 62.5em) {
  .info-list--row {
    /* The address is the widest of the four and the only one that wraps, so
       it gets the slack rather than being squeezed into a quarter while the
       fax number sits in a quarter it does not need. */
    grid-template-columns: auto auto auto minmax(0, 1fr);
    gap: 3rem;
  }
}

/* --------------------------------------------------------------------------
   About — patient rating, credentials, certifications
   ----------------------------------------------------------------------- */

/* One line under the doctor's name. Reads as a caption on the name, not as a
   panel competing with it. */
.rating-line {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.5rem 0.625rem;
  margin-bottom: 1.5rem;
}

/* The mark is a mask sized by height, so it needs its own baseline nudge to
   sit with type rather than on it. */
.rating-line__stars {
  align-self: center;
}

.rating-line__value {
  font-size: 1.25rem;
  font-weight: 800;
  color: var(--color-4);
  line-height: 1;
}

.rating-line__meta {
  font-size: 0.9375rem;
  color: var(--color-3);
}

/* --- Credentials --------------------------------------------------------- */

.credentials {
  display: grid;
  gap: 2.5rem;
  grid-template-columns: 1fr;
}

@media only screen and (min-width: 62.5em) {
  .credentials {
    /* Education runs to four entries and appointments to two, so equal
       columns would leave the second half empty. Weighted to match. */
    grid-template-columns: 1.15fr 1fr;
    gap: 3.5rem;
  }
}

.credentials__label {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--primary);
  padding-bottom: 0.75rem;
  margin-bottom: 0.25rem;
  border-bottom: 2px solid var(--border);
}

.credential-list {
  margin: 0;
}

/* A hairline between entries instead of a bullet before them. The rule is the
   separator a reference list wants — a dot implies an unordered set of
   equivalent things, which a training history is not.

   min-height is the height of an ordinary two-line entry, so a row whose term
   stands alone — the medical school in both languages — matches its
   neighbours instead of collapsing to a short band. justify-content then
   centres that lone term in the space rather than leaving it sitting high
   with a gap beneath. Rows whose term wraps to two lines are taller than the
   floor and grow past it untouched. */
.credential {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  min-height: 4.625rem;
  padding: 0.875rem 0;
  border-bottom: 1px solid var(--border);
}

.credential:last-child {
  border-bottom: 0;
}

.credential__org {
  font-weight: 700;
  color: var(--color-4);
  line-height: 1.35;
}

/* An entry whose whole phrase lives in the term needs no definition line —
   see the Yonsei entry in the Korean data. The <dd> is still emitted so the
   <dl> keeps one per <dt>, which the spec requires; it is hidden here rather
   than dropped from the template. */
.credential__note:empty {
  display: none;
}

/* <dd> carries a UA margin that would indent every second line. */
.credential__note {
  margin: 0;
  font-size: 0.9375rem;
  color: var(--color-3);
  line-height: 1.4;
}

/* --- Certifications ------------------------------------------------------ */

.cert-grid {
  display: grid;
  gap: 14px;
  grid-template-columns: 1fr;
  list-style: none;
}

@media only screen and (min-width: 43.125em) {
  .cert-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media only screen and (min-width: 62.5em) {
  .cert-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 20px;
  }
}

/* White, not --surface-tint, and the border is what makes the card visible
   against an equally white page. Two of the four seals — abem.png and
   aapmr.png — are opaque PNGs with a white square baked in (the other two do
   carry alpha). On a tinted card those two render as white rectangles with a
   logo inside. Matching the card to the artwork costs nothing; re-cutting two
   PNGs to add transparency is the alternative, and would let this go back to
   --surface-tint if the set is ever redone. */
.cert {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 18px 20px;
  border: 2px solid var(--border);
  border-radius: var(--radius-panel);
  background-color: var(--surface);
}

@media only screen and (min-width: 62.5em) {
  /* Upright once there are four across: the seals line up on one axis and the
     captions read as a row of labels rather than four separate rows. */
  .cert {
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
    padding: 22px;
  }
}

/* Normalised by height, not boxed into a square. The four marks run from 1:1
   to 2.34:1 — three circular seals and one wide wordmark — and a square box
   sized them all by their widest edge, which crushed the AAPM&R wordmark to
   26px tall and illegible. Matching their heights is how a row of mixed
   logos is conventionally balanced, and is what the old .badge-row did. */
/* Pinned to the card's right edge while the card is a row — which is every
   width below desktop, and is where the problem actually was.
   
   Laid out badge-first, the seals' different widths (52 to 122px) push each
   caption to a different x, so the names stagger down the stack. Moving the
   badge to the end gives every caption the same left edge and every seal the
   same right edge; the uneven gap lands in the middle where nothing lines up
   against it. */
.cert__badge {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  flex-shrink: 0;
  height: 3.25rem;
  order: 1;
  margin-left: auto;
}

.cert__badge picture {
  display: block;
  height: 100%;
}

.cert__badge img {
  display: block;
  height: 100%;
  width: auto;
  max-width: 100%;
  object-fit: contain;
}

/* Back to the top left once the card is a column. The seal then sits on its
   own line above the caption, so its width cannot push anything around, and it
   shares the card's left padding edge with the name beneath it. Right-pinning
   was tried at this breakpoint and looked worse — it cut the seal loose from
   the caption it belongs to.

   This has to come after the base .cert__badge rule, not in the earlier
   min-width block with .cert. A media query adds no specificity, so declared
   above it the base rule's `order: 1` and `margin-left: auto` simply won at
   every width and the reset never applied. */
@media only screen and (min-width: 62.5em) {
  .cert__badge {
    order: 0;
    margin-left: 0;
  }
}

.cert__body {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.cert__name {
  font-weight: 700;
  line-height: 1.3;
  color: var(--color-4);
}

.cert__issuer {
  font-size: 0.875rem;
  color: var(--color-3);
  line-height: 1.35;
}

/* .section-actions carries a top margin for use at the end of a block. In its
   own section the section gap already provides the separation, and the two
   stacked put the button adrift. */
.section-actions--flush {
  margin-top: 0;
}

/* --------------------------------------------------------------------------
   Blog post
   ----------------------------------------------------------------------- */

.post-header {
  margin-bottom: 1.5rem;
}

.post-header__title {
  font-size: var(--h2);
  color: var(--color-4);
  margin-bottom: 12px;
}

.post-hero {
  width: 100%;
  aspect-ratio: 2 / 1;
  object-fit: cover;
  border-radius: var(--radius-panel);
  margin-bottom: 2.5rem;
}

/* --------------------------------------------------------------------------
   Treatments — the visit band

   Hours and address in one tinted panel. Replaces a full `.feature` row that
   carried a photograph of the waiting area: four facts do not need a picture,
   and they certainly do not need one directly above the closing ask.

   The hours list is the same `.hours-list` component as before, so nothing
   about how a row is set had to change — only what surrounds it.
   ----------------------------------------------------------------------- */

.visit {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
  padding: 1.75rem 1.5rem;
  border-radius: var(--radius-panel);
  background-color: var(--surface-tint);
}

.visit__title {
  font-size: var(--h4);
  color: var(--color-4);
  margin-bottom: 1rem;
}

/* The list already draws a rule above its first row and below its last, so
   its own bottom margin would double the gap before the note. */
.visit .hours-list {
  margin-bottom: 1rem;
}

.visit__address {
  display: flex;
  flex-direction: column;
  font-weight: 700;
  line-height: 1.45;
  color: var(--color-4);
  margin-bottom: 1.25rem;
}

@media only screen and (min-width: 62.5em) {
  /* Hours take the room, the address takes what it needs. An even split left
     the address column mostly empty next to a three-row table. */
  .visit {
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
    gap: 3rem;
    padding: 2.25rem 3rem;
    align-items: start;
  }

  .visit__col--where {
    /* Optically level with the hours table rather than with the heading
       above it — there is no second heading on this side to line up with. */
    padding-top: 0.5rem;
  }
}

/* -------------------------------------------------------------------------
   Contact — booking block and directions

   Added when the contact page stopped being a definition list with a map
   under it. Two new pieces: the email line that sits below the call button,
   and the directions list inside the building panel.
   ----------------------------------------------------------------------- */

/* The contact page reuses `.visit` for its lead, but with one column: a
   heading, a paragraph, the call button and the line of opening hours. The
   two-column rule above is the treatments page's, and it has to be undone
   here or the panel reserves a second track for a column that is not there
   and the copy sits in 60% of it. */
.visit--single {
  grid-template-columns: 1fr;
}

@media only screen and (min-width: 62.5em) {
  .visit--single {
    grid-template-columns: 1fr;
  }
}

/* The opening hours, as a footnote to the button rather than as a section.
   Muted and a size down: it is the answer to a question the button raises,
   not a thing to read on the way to it. Held to the copy's measure so it
   cannot run the full width of a panel on a desktop. */
.visit__open {
  max-width: 46ch;
  margin: 1rem 0 0;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: color-mix(in srgb, var(--color-3) 82%, transparent);
}

/* Directions: parking, step-free entrance, which suite. A list rather than
   cards — three short facts do not need three boxes, and boxing them would
   make them compete with the address block directly above. The rule on the
   left is what separates them instead, which is also how the hours table
   above sets its rows. */
.directions {
  list-style: none;
  margin: 1.75rem 0 0;
  padding: 0;
  display: grid;
  gap: 1.25rem;
}

.directions__item {
  padding-left: 1rem;
  border-left: 3px solid var(--primary);
}

.directions__title {
  font-size: 1rem;
  font-weight: 700;
  color: var(--color-4);
  margin: 0 0 0.25rem;
}

.directions__text {
  margin: 0;
  color: var(--bodyTextColor);
}

/* --------------------------------------------------------------------------
   Plain page lead — the third hero, used by library pages that open with an
   explanation rather than with a panel. See detail-page.html.
   ----------------------------------------------------------------------- */

/* Two columns of ticks on a wide screen. Four short claims stacked under a
   46rem lede leave most of the row empty and push the first real section
   below the fold for no gain; paired, they read as one block of evidence
   under the paragraph they belong to. */
@media only screen and (min-width: 62.5em) {
  .tick-list--split {
    grid-template-columns: 1fr 1fr;
    gap: 0.75rem 2.5rem;
    max-width: 56rem;
  }
}

.lead-actions {
  margin-top: 1.75rem;
}
