/* ==========================================================================
   site.css

    1. Tokens            every site-specific value; nothing below hard-codes a colour
   1a. Fonts            the self-hosted heading face and its matched fallback
    2. Reset
    3. Base type         body, headings, links, lists, inline elements
    4. Focus and skip link
    5. Layout            two widths, breakout rows, full-width bands
    6. Header            logo, phone, navigation
    7. Page              h1, lead, prose rhythm
    8. Figure            the image component
    9. Blockquote
   10. Table             the price list
   11. FAQ
   12. Collection        the treatments index
   13. Link list         a short hand-picked list of links
   13a. Hero            optional top of a page, on the warm band
   13b. Facts           a quiet row of three facts
   13c. Cards           typographic cards, each one a link
   13d. Steps           a short numbered process
   13e. Split           a photograph beside text
   14. Call to action    the closing band, and the two button styles
   15. Phone links
   16. Footer
   17. Template variants landing, 404
   18. Motion
   19. Print
   ========================================================================== */


/* 1. Tokens
   ========================================================================== */

:root {
    /* Brand colours. Taken from the logo and the printed material.
       These are fixed. Do not adjust them to taste. */
    --navy:  #002f73;   /* primary: headings, links, buttons */
    --gold:  #d4af87;   /* accent ONLY: rules and small marks. Never text. */
    --paper: #f5f2ee;   /* page background */
    --ink:   #222222;   /* body text */
    --muted: #6e6e75;   /* secondary text, body size or larger only */
    --cream: #f4e7d6;   /* soft background band */

    /* Measured contrast of the brand pairs:
         ink on paper     14.26:1  AAA
         navy on paper    11.38:1  AAA
         white on navy    12.70:1  AAA
         muted on paper    4.53:1  AA, never below body size
         gold on paper     1.83:1  fails. Gold never carries text or meaning. */

    /* Derived colours. Every pair that carries text states its ratio. */
    --white:     #ffffff;   /* button text. white on navy 12.70:1 */
    --navy-deep: #001f4d;   /* button hover. white on navy-deep 16.11:1 */
    --ink-soft:  #454545;   /* lead, captions, attributions.
                               ink-soft on paper 8.59:1, on cream 7.87:1 */
    --line:      #d8d2c8;   /* hairlines between rows. Decorative, never text. */

    /* Terracotta: the clinic's own warm colour. Decoration only.
       terracotta on paper 2.49:1, white on terracotta 2.78:1: it fails as text and
       as a button, in either direction. NEVER text, NEVER a button. */
    --terracotta:      #d98664;
    /* A 22% tint of terracotta over paper, for band backgrounds.
       ink on wash 11.83:1, navy on wash 9.44:1, ink-soft on wash 7.13:1.
       --muted on wash is 3.76:1: never use muted text on a wash band. */
    --terracotta-wash: #efdad0;
    /* Text on the cream band: navy on cream 10.43:1, ink on cream 13.07:1. */

    /* Type. System fonts only. */
    /* Headings use Source Serif 4, served from this site (see the @font-face
       rules below). While it loads, and if it never does, the next name in the
       list is used: Georgia scaled to the same width, then plain Georgia. */
    --font-serif: "Source Serif 4", "Source Serif Fallback", Georgia, "Times New Roman", Times, serif;
    --font-sans:  system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

    /* Fluid scale. rem-based ends, so a visitor's own font size setting scales everything. */
    --text-base: clamp(1.0625rem, 1rem + 0.3vw, 1.1875rem);    /* 17px to 19px */
    --text-h1:   clamp(2rem, 1.55rem + 2.2vw, 2.875rem);
    --text-h2:   clamp(1.4375rem, 1.3rem + 0.7vw, 1.75rem);
    --text-h3:   clamp(1.1875rem, 1.13rem + 0.3vw, 1.3125rem);
    --leading:   1.6;

    /* Space */
    --space-xs: 0.5rem;
    --space-s:  1rem;
    --space-m:  1.5rem;
    --space-l:  2.5rem;
    --space-xl: 4rem;

    /* Layout */
    --container:      72rem;                   /* structure: header, footer, hero, rows of cards */
    --container-text: 46rem;                   /* the reading column: every page's own text */
    /* Space above and below a band. One value, used everywhere: 48px on a phone,
       growing with the window to 96px on a desktop. */
    --band-pad:  clamp(3rem, 1.5rem + 6vw, 6rem);
    --gutter:    clamp(1.25rem, 5vw, 2rem);    /* side padding; 20px at 360px wide */
    --measure:   32em;                         /* about 70 characters of body text per line.
                                                  em, not ch: ch is the width of a zero, which is
                                                  wider than the average letter and overshoots. */
    --tap:       2.75rem;                      /* 44px minimum touch target */
    --cell-pad:  clamp(0.5rem, 2.2vw, 0.75rem); /* table cell side padding; tight at 360px */
    --radius:    2px;
    --radius-l:  1rem;                         /* photographs in the hero */

    /* The logo is a raster file 147px tall. 4.5rem is 72px at the default font
       size, and stays under 147px until the visitor doubles their font size. */
    --logo-height: clamp(3.25rem, 2.6rem + 3vw, 4.5rem);
}


/* 1a. Fonts
   ========================================================================== */

/* One self-hosted face for headings, in two weights. Latin subset, woff2 only,
   42KB for both. Served from this site: nothing is requested from anyone else,
   so no cookie and no third party. Licence: SIL Open Font License 1.1, shipped
   beside the files as assets/fonts/OFL.txt. Body text stays on the system stack.
   font-display: swap shows the fallback at once and swaps when the file arrives. */
@font-face {
    font-family: "Source Serif 4";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/source-serif-4-latin-400.woff2") format("woff2");
}

@font-face {
    font-family: "Source Serif 4";
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("../fonts/source-serif-4-latin-700.woff2") format("woff2");
}

/* The fallback: Georgia from the visitor's own machine, scaled so its words
   are as wide as Source Serif's. At regular weight Source Serif is about 6.6%
   wider than Georgia, at bold 5.4% narrower. With the widths matched, lines
   break in the same places before and after the font arrives, so the page does
   not move. Line heights are unitless everywhere, so the taller letterforms do
   not change the height of a line either.
   The regular scale was chosen by test, not arithmetic: every serif element on
   every page at 360, 768 and 1280px, 777 in all. Unscaled Georgia wrapped 72 of
   them differently from the real font; 108% leaves 3. It cannot be made zero
   while font-display is swap. font-display: optional would make it zero, at
   the cost of a first visit on a slow connection keeping the fallback. */
@font-face {
    font-family: "Source Serif Fallback";
    font-weight: 400;
    src: local("Georgia");
    size-adjust: 108%;
}

@font-face {
    font-family: "Source Serif Fallback";
    font-weight: 700;
    src: local("Georgia Bold"), local("Georgia-Bold"), local("Georgia");
    size-adjust: 94.6%;
}


/* 2. Reset
   ========================================================================== */

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

body,
h1, h2, h3, h4,
p, ul, ol, figure, blockquote, address, table, caption, th, td {
    margin: 0;
}

img {
    display: block;
    max-width: 100%;
    height: auto;
}

address {
    font-style: normal;
}


/* 3. Base type
   ========================================================================== */

body {
    background: var(--paper);
    color: var(--ink);
    font-family: var(--font-sans);
    font-size: var(--text-base);
    line-height: var(--leading);
    overflow-wrap: break-word;
}

h1, h2, h3 {
    font-family: var(--font-serif);
    font-weight: 400;
    color: var(--navy);
    line-height: 1.2;
    text-wrap: balance;
}

h1 { font-size: var(--text-h1); line-height: 1.12; }
h2 { font-size: var(--text-h2); }
h3 { font-size: var(--text-h3); font-weight: 700; }

/* h4 steps down by changing face, not by shrinking: body size, sans, bold. */
h4 {
    font-family: var(--font-sans);
    font-size: 1em;
    font-weight: 700;
    color: var(--navy);
    line-height: 1.35;
}

/* Links are navy with a navy underline. Navy and ink are both dark, so the
   underline, not the colour, is what marks a link. */
a {
    color: var(--navy);
    text-decoration-line: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.18em;
}

a:hover {
    text-decoration-thickness: 2px;
}

strong { font-weight: 700; }
em     { font-style: italic; }

ul, ol {
    padding-left: 1.4em;
}

li + li {
    margin-top: 0.4em;
}

li::marker {
    color: var(--navy);
}

ol > li::marker {
    font-weight: 700;
}


/* 4. Focus and skip link
   ========================================================================== */

/* One focus style for every interactive element: a navy ring set off from the
   element, so it reads on paper, on cream and around the navy button. */
:focus-visible {
    outline: 3px solid var(--navy);
    outline-offset: 3px;
    border-radius: var(--radius);
}

.skip-link {
    position: absolute;
    top: var(--space-xs);
    left: var(--space-xs);
    z-index: 10;
    padding: 0.75rem 1.25rem;
    background: var(--navy);
    color: var(--white);
    font-weight: 700;
    text-decoration: none;
    border-radius: var(--radius);
    transform: translateY(-250%);
}

.skip-link:focus {
    transform: translateY(0);
    outline: 3px solid var(--navy);
    outline-offset: 3px;
}


/* 5. Layout
   ========================================================================== */

/* Two widths.
   Structure (header, footer, hero, rows of facts and cards, the treatments
   index, the closing band) uses the wide container.
   Text uses the reading column: main is that column, centred, and everything a
   page says in sentences stays inside it at --measure. Long lines hurt
   comprehension, and this site explains side effects. */
.site-header,
.site-footer {
    width: min(100% - 2 * var(--gutter), var(--container));
    margin-inline: auto;
}

main {
    width: min(100% - 2 * var(--gutter), var(--container-text));
    margin-inline: auto;
    display: flow-root;   /* contains the floated figure */
    padding-top: var(--space-l);
}

/* Structural rows break out of the reading column to the wide container.
   The margin is negative by exactly the difference between the two widths, so
   the row ends up as wide as the header and lined up with it. On a narrow
   screen both widths are the window minus its gutters and the margin is zero. */
.hero,
.facts,
.cards,
.steps,
.split,
.collection,
.cta-band {
    margin-inline: calc(50% - min(50vw - var(--gutter), var(--container) / 2));
}

/* A band is a row whose background runs to both edges of the window. The row
   itself stays the width of the container; the colour is carried outward by a
   very wide shadow, trimmed top and bottom by clip-path. Nothing overflows.
   Three background values at most on a page: paper, the wash, and navy. */
.hero,
.cards {
    padding-block: var(--band-pad);
    background: var(--terracotta-wash);
    box-shadow: 0 0 0 100vmax var(--terracotta-wash);
    clip-path: inset(0 -100vmax);
}

/* Rhythm: a band sits flush against what is above it, and whatever follows a
   band, or sits between two, gets a generous gap on paper. */
main > .hero + *,
main > .cards + *,
main > .steps + *,
main > .split,
main > .split + * {
    margin-top: calc(var(--band-pad) * 0.75);
}

main > .facts {
    margin-bottom: calc(var(--band-pad) * 0.75);
}

/* The closing band, when a page has one, runs to the foot of main. A page
   without one keeps the same breathing room above the footer as before. */
main > :last-child:not(.cta-band) {
    margin-bottom: var(--space-xl);
}


/* 6. Header
   ========================================================================== */

.site-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-xs) var(--space-m);
    position: relative;
    padding-top: var(--space-m);
    padding-bottom: var(--space-s);
}

/* The gold rule under the header runs the full width of the window, like the
   footer's. Bands below it are full width, and a rule only as wide as the text
   would stop short of them. Drawn the same way as the footer's rule. */
.site-header::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 2px;
    background: var(--gold);
    box-shadow: 0 0 0 100vmax var(--gold);
    clip-path: inset(0 -100vmax);
}

/* The logo sits on paper only: the file's own background is the paper colour. */
.site-brand {
    display: inline-flex;
    align-items: center;
    font-family: var(--font-serif);
    font-size: var(--text-h3);
    color: var(--navy);
    text-decoration: none;
}

.site-brand img {
    width: auto;
    height: var(--logo-height);
}

/* The site name as text, beside the logo. Hidden on screen, where the logo's
   alt text already carries it. Shown in print instead of the logo: see Print. */
.site-brand img + .site-brand-name {
    display: none;
}

/* The phone number: the second most prominent thing after the page title. */
.site-phone {
    display: inline-flex;
    align-items: center;
    min-height: var(--tap);
    /* 18px at 360px wide, so it shares a line with the logo; 26px on a desktop. */
    font-size: clamp(1.125rem, 0.85rem + 1.2vw, 1.625rem);
    font-weight: 700;
    font-variant-numeric: lining-nums tabular-nums;
    white-space: nowrap;
    text-decoration-thickness: 2px;
    text-underline-offset: 0.25em;
}

.site-phone:hover {
    text-decoration-thickness: 3px;
}

/* On a phone the navigation takes two rows, so the header gives back some of
   its padding. Tap heights are not reduced. */
@media (max-width: 39.99rem) {
    .site-header {
        gap: 0.25rem var(--space-s);
        padding-top: var(--space-s);
        padding-bottom: 0.25rem;
    }

    .site-nav {
        margin-top: 0.25rem;
        padding-top: 0.25rem;
    }
}

/* Navigation: six flat links, always visible. No toggle and no JavaScript:
   these links are how visitors reach treatments, prices and contact, and hiding
   them behind a tap would cost enquiries to fix what is only a spacing problem.
   On a phone they sit in a tidy grid, three across and two down, so the links
   line up in columns instead of wrapping wherever the words happen to end. Each
   column is as wide as its longest label and each link fills its cell, 44px
   tall. From 40rem up there is room for one row. */
.site-nav {
    flex-basis: 100%;
    margin-top: var(--space-xs);
    padding-top: var(--space-xs);
    border-top: 1px solid var(--line);
}

.site-nav ul {
    display: grid;
    grid-template-columns: repeat(3, auto);
    justify-content: space-between;
    gap: 0 clamp(0.4rem, 3vw, 1rem);
    padding: 0;
    list-style: none;
}

.site-nav li + li {
    margin-top: 0;
}

.site-nav a {
    display: flex;
    align-items: center;
    min-height: var(--tap);
    text-decoration: none;
    white-space: nowrap;   /* a label never breaks in two */
}

@media (min-width: 40rem) {
    .site-nav ul {
        display: flex;
        flex-wrap: wrap;
        justify-content: flex-start;
        gap: 0 var(--space-m);
    }

    .site-nav a {
        display: inline-flex;
    }
}

.site-nav a:hover {
    text-decoration-line: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 0.35em;
}

/* Current page: bold carries the meaning, the gold bar is decoration. */
.site-nav a[aria-current="page"] {
    font-weight: 700;
    box-shadow: inset 0 -3px 0 var(--gold);
}


/* 7. Page
   ========================================================================== */

main > * + * {
    margin-top: var(--space-m);
}

h1 {
    max-width: var(--measure);
}

/* Tagline: an optional strapline directly under the h1. It belongs to the
   title, so it sits tight beneath it, with the normal gap before the lead.
   Kept apart from its neighbours on purpose: the h1 and lead are serif, this is
   sans; headings are bold, this is regular weight; body text is ink, this is
   navy and lightly letter-spaced. Body size, so it never competes with the lead.
   navy on paper 11.38:1. */
.tagline {
    max-width: var(--measure);
    margin-top: 0.6rem;
    font-family: var(--font-sans);
    font-size: 1em;
    font-weight: 400;
    line-height: 1.4;
    letter-spacing: 0.06em;
    color: var(--navy);
    /* If it has to wrap on a narrow screen, split it into even lines rather than
       leaving one word alone on the second. */
    text-wrap: balance;
}

/* Lead: the opening sentence. Larger and a shade lighter than body. */
.lead {
    max-width: var(--measure);
    font-family: var(--font-serif);
    font-size: 1.25em;
    line-height: 1.5;
    color: var(--ink-soft);
}

/* Prose is raw HTML from content files, so it is styled by element. */
.prose > * {
    max-width: var(--measure);
}

.prose > * + * {
    margin-top: 1em;
}

.prose > h2 {
    margin-top: 2.25em;
}

.prose > h3 {
    margin-top: 1.9em;
}

.prose > h4 {
    margin-top: 1.6em;
}

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

/* A short gold rule above each h2. The heading itself carries the structure. */
.prose > h2::before,
.linklist > h2::before,
.cards > h2::before,
.steps > h2::before,
.split-text > h2::before {
    content: "";
    display: block;
    width: 2.5rem;
    height: 2px;
    margin-bottom: 0.7rem;
    background: var(--gold);
}

.prose > h2 + *,
.prose > h3 + *,
.prose > h4 + * {
    margin-top: 0.6em;
}

.prose li > ul,
.prose li > ol {
    margin-top: 0.4em;
}


/* 8. Figure
   ========================================================================== */

/* A figure/img pair, from the 'figure' section type. The img carries its real
   pixel width and height as attributes. With height: auto the browser derives
   the aspect ratio from those two numbers and reserves the space before the
   file arrives, so the page never shifts. It can never be wider than the container.
   The modifier class records the shape (portrait, landscape, square) for layout. */
.figure {
    max-width: min(100%, 16rem);
}

.figure img {
    width: 100%;
    height: auto;
    background: var(--cream);
    border-radius: var(--radius);
}

.figure--landscape {
    max-width: 100%;
}

.figure figcaption {
    margin-top: var(--space-xs);
    padding-left: 0.75rem;
    border-left: 2px solid var(--gold);
    font-size: 0.9375em;
    line-height: 1.4;
    color: var(--ink-soft);
}

/* On a wide screen a portrait or square figure sits to the right of the text. */
@media (min-width: 44rem) {
    .figure--portrait,
    .figure--square {
        float: right;
        width: 15rem;
        margin: 0.4rem 0 var(--space-m) var(--space-l);
    }
}


/* 9. Blockquote
   ========================================================================== */

/* The quotation is set in serif and indented. The gold bar is decoration. */
blockquote {
    padding: 0.25rem 0 0.25rem 1.25rem;
    border-left: 3px solid var(--gold);
    font-family: var(--font-serif);
    font-size: 1.125em;
    line-height: 1.55;
}

blockquote > * + * {
    margin-top: 0.75em;
}

/* The last paragraph of a multi-paragraph quote is the attribution:
   back to sans at body size, with a dash in front. No class needed. */
blockquote > p:last-child:not(:first-child) {
    font-family: var(--font-sans);
    font-size: 0.889em;
    color: var(--ink-soft);
}

blockquote > p:last-child:not(:first-child)::before {
    content: "\2014\00a0";
}


/* 10. Table
   ========================================================================== */

/* Built for the price list: two columns, a caption, and group headings that
   span both columns. Readable at 360px wide with no horizontal scrolling.

   - The table stops at 34rem, so on a wide screen a price never drifts far
     from its treatment name.
   - The price column shrinks to the width of its longest number and never
     wraps. The name column takes the rest and wraps freely.
   - Prices are right-aligned in tabular figures, so they scan as a column. */
table {
    width: 100%;
    max-width: 34rem;
    border-collapse: separate;
    border-spacing: 0;
    font-variant-numeric: lining-nums tabular-nums;
}

.prose > table {
    max-width: 34rem;
}

caption {
    caption-side: top;
    padding-bottom: var(--space-xs);
    text-align: left;
    color: var(--ink-soft);
}

thead tr,
tbody tr {
    vertical-align: baseline;
}

/* Column headers: small navy capitals over a solid navy rule. */
thead th {
    padding: 0.5rem var(--cell-pad);
    border-bottom: 2px solid var(--navy);
    text-align: left;
    vertical-align: bottom;
    font-size: 0.875em;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--navy);
}

thead th strong {
    font-weight: inherit;
}

/* Data rows: one hairline under each, tight padding for narrow screens. */
td {
    padding: 0.6rem var(--cell-pad);
    border-bottom: 1px solid var(--line);
    overflow-wrap: anywhere;
}

/* The second cell in a row is the price. */
thead th + th,
td + td {
    width: 1%;
    padding-left: 0.5rem;
    text-align: right;
    white-space: nowrap;
}

td + td {
    font-weight: 700;
}

/* Group headings are signposts, not entries. They differ from a data row in
   four ways at once: a cream band across both columns, serif type, navy colour,
   and a gap of paper above. The gold line on the band's top edge is decoration. */
tbody th[scope="colgroup"] {
    padding: 0.65rem var(--cell-pad);
    border-top: var(--space-m) solid var(--paper);
    background: var(--cream);
    box-shadow: inset 0 2px 0 var(--gold);
    text-align: left;
    font-family: var(--font-serif);
    font-size: 1.125em;
    font-weight: 700;
    line-height: 1.3;
    color: var(--navy);
}

/* Two group headings in a row: the second describes the first. It joins the
   same band as a plain line, with no gap and no rule of its own.
   Browsers without :has() show it as a second heading, which still reads. */
tbody tr:has(> th[scope="colgroup"]) + tr > th[scope="colgroup"] {
    padding-top: 0;
    border-top: 0;
    box-shadow: none;
    font-family: var(--font-sans);
    font-size: 1em;
    font-weight: 400;
    color: var(--ink);
}


/* 11. FAQ
   ========================================================================== */

.faq {
    max-width: var(--measure);
    border-top: 1px solid var(--line);
}

.faq > h2 {
    margin-block: var(--space-m) var(--space-s);
}

.faq details {
    border-bottom: 1px solid var(--line);
}

.faq summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-s);
    min-height: 3.25rem;
    padding-block: 0.75rem;
    font-family: var(--font-serif);
    font-size: 1.125em;
    line-height: 1.35;
    color: var(--navy);
    cursor: pointer;
    list-style: none;
}

.faq summary::-webkit-details-marker {
    display: none;
}

/* A drawn chevron: points down when closed, up when open. */
.faq summary::after {
    content: "";
    flex: none;
    width: 0.6rem;
    height: 0.6rem;
    margin: 0 0.35rem 0.2rem 0;
    border-right: 2px solid var(--navy);
    border-bottom: 2px solid var(--navy);
    transform: rotate(45deg);
}

.faq details[open] > summary::after {
    margin-bottom: -0.2rem;
    transform: rotate(-135deg);
}

.faq summary:hover {
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.2em;
}

.faq details > p,
.faq-answer {
    padding-bottom: var(--space-m);
}

.faq-answer > * + * {
    margin-top: 0.8em;
}


/* 12. Collection
   ========================================================================== */

/* The treatments index. Set like the index of a book: columns that read down,
   then across, so the alphabetical order survives. One column on a phone.
   Each entry is a full-width link with a hairline beneath, so long and short
   titles line up without needing equal lengths. */
.collection {
    columns: 3 15rem;
    column-gap: var(--space-l);
    padding: 0;
    border-top: 2px solid var(--navy);
    list-style: none;
}

.collection li {
    break-inside: avoid;
    border-bottom: 1px solid var(--line);
}

.collection li + li {
    margin-top: 0;
}

.collection a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-s);
    min-height: 3.25rem;
    padding-block: 0.6rem;
    font-family: var(--font-serif);
    font-size: 1.0625em;
    line-height: 1.3;
    text-decoration: none;
}

/* A small drawn chevron marks each entry as somewhere to go. */
.collection a::after {
    content: "";
    flex: none;
    width: 0.5rem;
    height: 0.5rem;
    margin-right: 0.3rem;
    border-top: 2px solid var(--gold);
    border-right: 2px solid var(--gold);
    transform: rotate(45deg);
}

.collection a:hover {
    text-decoration-line: underline;
    text-decoration-thickness: 1px;
}

.collection a:hover::after {
    border-color: var(--navy);
}


/* 13. Link list
   ========================================================================== */

/* The 'linklist' section: a heading, an optional intro and a short list of
   links, one per line. A relative of the treatments index, built the same way:
   each row is a full-width link over a hairline, with a drawn chevron.
   It differs on purpose, because this is a shortlist and that is the index:
   sans instead of serif, one narrow column at every width, and a plain hairline
   on top instead of the index's navy rule. */
.linklist > h2 + p,
.linklist > h2 + ul {
    margin-top: 0.6em;
}

.linklist > p {
    max-width: var(--measure);
}

.linklist ul {
    max-width: 26rem;
    margin-top: var(--space-s);
    padding: 0;
    border-top: 1px solid var(--line);
    list-style: none;
}

.linklist li {
    border-bottom: 1px solid var(--line);
}

.linklist li + li {
    margin-top: 0;
}

/* The whole row is the link: 48px tall, wider than any finger. */
.linklist a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-s);
    min-height: 3rem;
    padding-block: 0.5rem;
    font-weight: 700;
    line-height: 1.3;
    text-decoration: none;
}

.linklist a::after {
    content: "";
    flex: none;
    width: 0.45rem;
    height: 0.45rem;
    margin-right: 0.3rem;
    border-top: 2px solid var(--gold);
    border-right: 2px solid var(--gold);
    transform: rotate(45deg);
}

.linklist a:hover {
    text-decoration-line: underline;
    text-decoration-thickness: 1px;
}

.linklist a:hover::after {
    border-color: var(--navy);
}


/* 13a. Hero
   ========================================================================== */

/* The top of a page that sets 'hero': the h1, tagline, a lead line and one or
   two buttons, with a photograph beside them, on the warm wash band.
   The header above stays on paper, so the logo never meets another colour.
   On a phone the text comes first and the image follows, in source order. */
.has-hero main {
    padding-top: 0;
}

.hero {
    display: grid;
    gap: var(--space-l);
}

/* The title is the largest thing on the site. It scales with the window, so it
   is 28px on a phone and 54px on a desktop, and at every width in between it is
   sized to sit on two lines in the room it has. Measured with Source Serif 4,
   which is wider than Georgia. (Balancing alone cannot do this: on three lines
   it leaves one word alone in the middle.) */
.hero h1 {
    font-size: clamp(1.75rem, 0.3rem + 3.8vw, 3.375rem);
    line-height: 1.08;
}

.hero .tagline {
    margin-top: 0.9rem;
}

/* The lead sits between the title and the body text in size. */
.hero-lead {
    max-width: 30em;
    margin-top: var(--space-s);
    font-family: var(--font-serif);
    font-size: clamp(1.1875rem, 1.05rem + 0.6vw, 1.4375rem);
    line-height: 1.5;
    color: var(--ink-soft);   /* 7.13:1 on the wash */
}

.hero-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 0.75rem;
    margin-top: var(--space-m);
}

/* The photograph: generous corners, and a solid terracotta block set a little
   down and to the right behind it. Decoration only; no shadow. */
.hero-image {
    position: relative;
    max-width: 16rem;
    margin-right: 0.75rem;
}

.hero-image::before {
    content: "";
    position: absolute;
    inset: 0.75rem -0.75rem -0.75rem 0.75rem;
    border-radius: var(--radius-l);
    background: var(--terracotta);
}

/* Shown whole, in its own shape: the browser reserves the space from the width
   and height on the tag, so nothing moves when it loads. */
.hero-image img {
    position: relative;
    width: 100%;
    height: auto;
    border-radius: var(--radius-l);
    background: var(--cream);
}

/* Tablet, still one column: the photograph can be a little larger. */
@media (min-width: 40rem) {
    .hero-image {
        max-width: 22rem;
    }
}

/* Wide: text and photograph side by side, the photograph about 43% of the row. */
@media (min-width: 56rem) {
    .hero {
        grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
        column-gap: clamp(2rem, 5vw, 4rem);
        align-items: center;
    }

    .hero-image {
        max-width: none;
        margin-right: 1rem;
    }

    .hero-image::before {
        inset: 1rem -1rem -1rem 1rem;
    }
}


/* 13b. Facts
   ========================================================================== */

/* A short row of facts under the hero, on paper between two bands: a prominent
   line and a sentence beneath. One list with thin dividers and no boxes, so it
   reads as one row of three. The prominent line is text ("One doctor"), not a
   numeral, so it is set at a size that holds a phrase. */
.facts {
    display: grid;
    gap: var(--space-m);
    padding: 0;
    list-style: none;
}

.facts li + li {
    margin-top: 0;
    padding-top: var(--space-m);
    border-top: 1px solid var(--line);
}

.facts-value {
    font-family: var(--font-serif);
    font-size: clamp(1.1875rem, 1rem + 0.8vw, 1.625rem);
    font-weight: 700;
    line-height: 1.25;
    color: var(--navy);
}

.facts-label {
    margin-top: 0.3rem;
    line-height: 1.5;
    color: var(--ink-soft);   /* 8.59:1 on paper */
}

@media (min-width: 44rem) {
    .facts {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        column-gap: 0;
    }

    .facts li {
        padding-inline: clamp(1rem, 2.6vw, 2.5rem);
    }

    .facts li:first-child {
        padding-left: 0;
    }

    .facts li:last-child {
        padding-right: 0;
    }

    .facts li + li {
        padding-top: 0;
        border-top: 0;
        border-left: 1px solid var(--line);
    }
}


/* 13c. Cards
   ========================================================================== */

/* A heading, an intro and a few cards. Each card is a title and a sentence or
   two. Typographic on purpose: there is no treatment photography, and three
   identical stock pictures would say less than the words do.
   The link is on the title. Its ::after is stretched over the whole card, so
   the card is clickable without any script. */
.cards > h2 + p,
.cards > h2 + ul {
    margin-top: 0.6em;
}

.cards > p {
    max-width: var(--measure);
}

.cards-list {
    display: grid;
    gap: var(--space-s);
    margin-top: var(--space-s);
    padding: 0;
    list-style: none;
}

.card {
    position: relative;
    padding: var(--space-m);
    border-top: 3px solid var(--navy);
    border-radius: 0 0 var(--radius) var(--radius);
    background: var(--paper);   /* paper cards on the wash band. ink on paper 14.26:1 */
}

.card + .card {
    margin-top: 0;
}

.card:hover {
    background: var(--white);   /* ink on white 15.9:1, navy on white 12.70:1 */
}

.card-title {
    font-size: var(--text-h3);
    line-height: 1.25;
}

.card-title a {
    text-decoration: none;
}

.card:hover .card-title a {
    text-decoration-line: underline;
    text-decoration-thickness: 1px;
}

.card-title a::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: var(--radius);
}

/* Focus: the ring goes round the whole card, drawn on the stretched ::after.
   The link's own ring is kept but made transparent, so there is one ring, not
   two. Nothing on the card clips it: no overflow is hidden. In forced-colours
   mode the transparent ring becomes visible again, which is correct. */
.card-title a:focus-visible {
    outline-color: transparent;
}

.card-title a:focus-visible::after {
    outline: 3px solid var(--navy);
    outline-offset: 3px;
}

.card p {
    margin-top: 0.5rem;
    line-height: 1.55;
}

.cards-list {
    gap: var(--space-m);
    margin-top: var(--space-m);
}

/* Three across only when each card has room for a comfortable line. */
@media (min-width: 56rem) {
    .cards-list {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}


/* 13d. Steps
   ========================================================================== */

/* A short process in order, on paper: a heading, then a title and a sentence
   or two per step, three across on a wide screen. Each step carries a large
   numeral, 01 02 03, drawn here from a counter. The numerals are rhythm, not
   content: they are in gold (decoration only), and the empty text after the
   slash tells a screen reader to say nothing for them. The order itself is in
   the markup, which is an ordered list. A browser too old to understand the
   slash keeps the first declaration and still draws the numeral. */
.steps-list {
    display: grid;
    gap: var(--space-l);
    margin-top: var(--space-m);
    padding: 0;
    list-style: none;
    counter-reset: step;
}

.steps-list li {
    counter-increment: step;
}

.steps-list li + li {
    margin-top: 0;
}

.steps-list li::before {
    content: counter(step, decimal-leading-zero);
    content: counter(step, decimal-leading-zero) / "";
    display: block;
    margin-bottom: 0.5rem;
    font-family: var(--font-serif);
    font-size: clamp(2.75rem, 2.2rem + 2.4vw, 4rem);
    font-weight: 400;
    line-height: 1;
    color: var(--gold);
}

.step-title {
    font-size: var(--text-h3);
    line-height: 1.25;
}

.steps-list p {
    max-width: var(--measure);
    margin-top: 0.5rem;
    line-height: 1.55;
}

@media (min-width: 56rem) {
    .steps-list {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        column-gap: clamp(2rem, 5vw, 4rem);
    }
}


/* 13e. Split
   ========================================================================== */

/* A photograph beside a heading, some text and one button, on paper. On a
   phone it is one column in source order: heading, text, button, photograph.
   On a wide screen the photograph takes the larger share of the row, on the
   side the content names. The photograph is shown whole, in its own shape:
   the browser takes the ratio from the width and height on the tag, as it does
   for the hero and for figures, so nothing is cropped and nothing moves when
   it loads. Crop the file, not the box. */
.split {
    display: grid;
    gap: var(--space-l);
}

.split-text > * + * {
    margin-top: var(--space-s);
}

.split-text > p {
    max-width: var(--measure);
}

.split-text > h2 + * {
    margin-top: 0.6em;
}

.split-text > .split-action {
    margin-top: var(--space-m);
}

.split-image img {
    width: 100%;
    height: auto;
    border-radius: var(--radius-l);
    background: var(--cream);
}

@media (min-width: 56rem) {
    .split {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr);
        column-gap: clamp(2rem, 5vw, 4rem);
        align-items: center;
    }

    .split--image-left {
        grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
    }

    .split--image-left .split-image {
        order: -1;
    }
}


/* 14. Call to action
   ========================================================================== */

/* The closing band: one line and the page's button, on navy, the strongest
   colour on the page, across the full width of the window.
   white on navy 12.70:1. */
.cta-band {
    clear: both;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-m) var(--space-l);
    margin-top: var(--band-pad);
    padding-block: calc(var(--band-pad) * 0.7);
    background: var(--navy);
    box-shadow: 0 0 0 100vmax var(--navy);
    clip-path: inset(0 -100vmax);
}

.cta-band-text {
    flex: 1 1 18rem;
    max-width: 36rem;
    font-family: var(--font-serif);
    font-size: clamp(1.25rem, 1.1rem + 0.7vw, 1.625rem);
    line-height: 1.3;
    color: var(--white);
}

.button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 3rem;
    padding: 0.7rem 1.75rem;
    border: 2px solid var(--navy);
    border-radius: var(--radius);
    background: var(--navy);
    color: var(--white);
    font-weight: 700;
    line-height: 1.25;
    text-align: center;
    text-decoration: none;
}

.button:hover {
    border-color: var(--navy-deep);
    background: var(--navy-deep);
}

/* On the navy band the button is turned inside out, white with navy text, so it
   still stands out. navy on white 12.70:1. Its focus ring is white, because a
   navy ring would vanish against the band. */
.cta-band .button {
    border-color: var(--white);
    background: var(--white);
    color: var(--navy);
}

.cta-band .button:hover {
    border-color: var(--cream);
    background: var(--cream);   /* navy on cream 10.43:1 */
}

.cta-band .button:focus-visible {
    outline-color: var(--white);
}

/* The quieter second button: same shape, outline only. Navy on paper 11.38:1.
   There is no third colour, and gold is never a button. */
.button--secondary {
    background: transparent;
    color: var(--navy);
}

.button--secondary:hover {
    border-color: var(--navy);
    background: var(--cream);
}


/* 15. Phone links
   ========================================================================== */

/* A phone number inside running text. Bold, never broken across lines, and
   padded top and bottom: on an inline element that padding enlarges the tap
   area past 44px without moving the lines around it.
   A phone link that is the page's button keeps the button's own shape. */
main a[href^="tel:"]:not(.button) {
    padding-block: 0.8em;
    font-weight: 700;
    font-variant-numeric: lining-nums tabular-nums;
    white-space: nowrap;
}


/* A contact value on its own: a paragraph, straight after an h2, holding nothing
   but a phone or email link. The link is the point of the block, so it is set
   like a heading: large, bold, and a full 44px to tap.
   CSS cannot see text, only elements. This matches "h2, then a paragraph whose
   one element is the link". A sentence with a single contact link in it,
   directly under an h2, would match too. No page has one today. */
.prose > h2 + p > a:only-child[href^="tel:"],
.prose > h2 + p > a:only-child[href^="mailto:"] {
    display: inline-flex;
    align-items: center;
    min-height: var(--tap);
    padding-block: 0;
    font-size: clamp(1.25rem, 1.1rem + 0.8vw, 1.5rem);
    font-weight: 700;
    line-height: 1.25;
    text-decoration-thickness: 2px;
    text-underline-offset: 0.22em;
    overflow-wrap: anywhere;
    white-space: normal;
}

/* A caution in the email block: the paragraph that opens in bold, one or two
   paragraphs below the email address. Set apart on the cream band with a navy
   edge, at full body size and full ink. It should read as care, not alarm:
   no red, no icon, no capitals. ink on cream 13.07:1, navy on cream 10.43:1.
   Needs :has(). Older browsers show an ordinary paragraph with a bold opening. */
.prose > h2 + p:has(> a:only-child[href^="mailto:"]) + p:has(> strong:first-child),
.prose > h2 + p:has(> a:only-child[href^="mailto:"]) + p + p:has(> strong:first-child) {
    margin-top: 1.4em;
    padding: var(--space-s) 1.1rem;
    border-left: 3px solid var(--navy);
    border-radius: 0 var(--radius) var(--radius) 0;
    background: var(--cream);
}

.prose > h2 + p:has(> a:only-child[href^="mailto:"]) + p:has(> strong:first-child) > strong:first-child,
.prose > h2 + p:has(> a:only-child[href^="mailto:"]) + p + p:has(> strong:first-child) > strong:first-child {
    color: var(--navy);
}


/* 16. Footer
   ========================================================================== */

/* Three columns on a wide screen: contact, treatments, the clinic. Then a
   closing line under a hairline. Stacked on a phone.
   It stays on paper. The band directly above it is navy, and a coloured footer
   beneath that would merge with it into one slab. The substance comes from what
   is in the footer, not from a background. */
.site-footer {
    position: relative;
    display: grid;
    gap: var(--space-l) var(--space-l);
    padding-block: var(--band-pad) var(--space-l);
    font-size: 1rem;
    line-height: 1.5;
    /* The footer sits on the wash, edge to edge, the same way the bands do.
       Navy text 9.44:1, ink 11.83:1, ink-soft 7.13:1 on the wash. It is never
       navy: the navy band above it has to stay a separate thing. */
    background: var(--terracotta-wash);
    box-shadow: 0 0 0 100vmax var(--terracotta-wash);
    clip-path: inset(0 -100vmax);
}

/* The footer's gold rule runs the full width of the window. It closes the page,
   and it usually follows the full-width navy band, so a rule only as wide as
   the text would read as a short underline.
   Drawn as a 2px strip the width of the container, carried to both edges by a
   wide shadow that clip-path trims to the strip's own height. No overflow. */
.site-footer::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 2px;
    background: var(--gold);
    box-shadow: 0 0 0 100vmax var(--gold);
    clip-path: inset(0 -100vmax);
}

/* Column 1: who and where, then when. */
.site-footer-contact {
    display: grid;
    gap: var(--space-m);
    align-content: start;
}

.site-footer-name {
    margin-bottom: var(--space-xs);
    font-family: var(--font-serif);
    font-size: 1.25rem;
    line-height: 1.3;
    color: var(--navy);
}

.site-footer-phone {
    margin-top: var(--space-xs);
}

.site-footer-phone a {
    display: inline-flex;
    align-items: center;
    min-height: var(--tap);
    font-size: 1.125rem;
    font-weight: 700;
    font-variant-numeric: lining-nums tabular-nums;
    white-space: nowrap;
}

/* Email sits directly under the phone, the same height to tap. */
.site-footer-email a {
    display: inline-flex;
    align-items: center;
    min-height: var(--tap);
    overflow-wrap: anywhere;
}

/* The small bold heading over the hours and over each column of links. */
.site-footer-label {
    font-weight: 700;
    color: var(--navy);
}

/* Opening hours: a definition list, one row per line. Days on the left, times
   on the right, the two columns sized by their longest entry. */
.site-footer-hours dl {
    display: grid;
    grid-template-columns: auto auto;
    justify-content: start;
    gap: 0.2rem var(--space-s);
    margin: 0.35rem 0 0;
    font-variant-numeric: lining-nums tabular-nums;
}

.site-footer-hours dl > div {
    display: contents;
}

.site-footer-hours dt,
.site-footer-hours dd {
    margin: 0;
}

.site-footer-hours dd {
    white-space: nowrap;
}

/* A closed row is said in words. Ink-soft only sets it back a little:
   ink-soft on paper is 8.59:1. */
.site-footer-hours .is-closed dt,
.site-footer-hours .is-closed dd {
    color: var(--ink-soft);
}

/* Columns 2 and 3: a heading and a list of links. Each link is a full row,
   44px tall, with no underline until it is hovered: in a list this plain, the
   position says "link" and a column of underlines would only add noise. */
.site-footer-nav ul {
    margin: 0.2rem 0 0;
    padding: 0;
    list-style: none;
}

.site-footer-nav li + li {
    margin-top: 0;
}

.site-footer-nav a {
    display: flex;
    align-items: center;
    min-height: var(--tap);
    text-decoration: none;
}

.site-footer-nav a:hover {
    text-decoration-line: underline;
    text-decoration-thickness: 1px;
}

/* On a phone, a column of short links (About, Contact...) goes two across,
   which keeps the footer from running long. The treatment names are too long
   for that and stay one per row. Marked in the markup by a count class. */
@media (max-width: 39.99rem) {
    /* A phone footer is kept to about two screens. The opening hours are left
       to the contact page, and a column marked 'phones' => false in the site
       data is left out. Both stay in the markup, and both are back from 40rem.
       A landing page keeps its hours: it has no navigation and no link to the
       contact page, so its footer is the only place they appear. */
    body:not(.t-landing) .site-footer-hours,
    .site-footer-nav--wide-only {
        display: none;
    }

    .site-footer-nav--short > ul:first-of-type {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        column-gap: var(--space-s);
    }
}

/* The social links close the last column, side by side under a hairline. */
.site-footer-nav .site-footer-socials {
    display: flex;
    flex-wrap: wrap;
    gap: 0 var(--space-m);
    margin-top: var(--space-xs);
    padding-top: var(--space-xs);
    border-top: 1px solid var(--gold);
}

.site-footer-socials a {
    display: inline-flex;
}

/* The closing line: copyright, under a hairline, across the full footer. */
.site-footer-close {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0 var(--space-m);
    padding-top: var(--space-s);
    border-top: 1px solid var(--gold);   /* decoration; the grey line is lost on the wash */
    color: var(--ink-soft);   /* 7.13:1 on the wash */
}

.site-footer-links {
    display: flex;
    flex-wrap: wrap;
    gap: 0 var(--space-m);
    margin: 0;
    padding: 0;
    list-style: none;
}

.site-footer-links li + li {
    margin-top: 0;
}

.site-footer-links a {
    display: inline-flex;
    align-items: center;
    min-height: var(--tap);
}

/* Tablet: contact across the top, with the hours beside the address, and the
   two link columns side by side beneath. */
@media (min-width: 40rem) {
    .site-footer {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .site-footer-contact,
    .site-footer-close {
        grid-column: 1 / -1;
    }

    .site-footer-contact {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        column-gap: var(--space-l);
    }
}

/* Wide: three columns. Contact is the widest and stacks its own parts again. */
@media (min-width: 60rem) {
    .site-footer {
        grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 1fr);
        column-gap: var(--space-xl);
    }

    .site-footer-contact {
        grid-column: auto;
        grid-template-columns: minmax(0, 1fr);
    }
}


/* 17. Template variants
   ========================================================================== */

/* Landing page: no navigation, one call to action, a narrower column.
   Narrowing the container narrows the header and footer with it. */
.t-landing {
    --container: 38rem;
    --container-text: 38rem;
}

.landing .button {
    width: 100%;
    min-height: 3.5rem;
    font-size: 1.125em;
}

@media (min-width: 30rem) {
    .landing .button {
        width: auto;
        min-width: 18rem;
    }
}

/* 404: the title, a line of help and three links, with room above. */
.not-found {
    padding-top: var(--space-xl);
}



/* 18. Motion
   ========================================================================== */

/* The only movement on the site: colour and underline easing on hover and focus.
   Skipped entirely for visitors who ask for reduced motion. */
@media (prefers-reduced-motion: no-preference) {
    a,
    .button {
        transition: background-color 120ms ease, border-color 120ms ease,
                    text-decoration-thickness 120ms ease;
    }

    .skip-link {
        transition: transform 120ms ease;
    }
}


/* 19. Print
   ========================================================================== */

/* Written for the price list, the one page people print. Aim: two or three
   sheets, readable, no wasted ink. */
@media print {
    /* Smaller type and tighter spacing, by resetting the tokens for paper. */
    :root {
        --text-base: 10pt;
        --text-h1:   18pt;
        --text-h2:   12pt;
        --text-h3:   11pt;
        --leading:   1.35;
        --space-s:   0.5rem;
        --space-m:   0.5rem;
        --space-l:   0.75rem;
        --space-xl:  1rem;
        --cell-pad:  0.4rem;
    }

    /* Nothing to click on paper: drop the nav, the button and the social links. */
    .skip-link,
    .site-nav,
    .cta-band,
    .hero-actions,
    .site-footer-nav,
    .site-footer-links {
        display: none;
    }

    /* White paper, and the full width of the sheet. */
    body {
        background: var(--white);
    }

    .site-header,
    main,
    .site-footer {
        width: auto;
    }

    .hero,
    .facts,
    .cards,
    .steps,
    .split,
    .collection {
        margin-inline: 0;
    }

    /* The logo's background is the paper colour, which would print as a tinted
       rectangle on white. Print the clinic name as text instead. */
    .site-brand img {
        display: none;
    }

    .site-brand img + .site-brand-name {
        display: inline;
    }

    .site-header {
        padding-top: 0;
    }

    .site-phone {
        min-height: 0;
        font-size: 12pt;
    }

    /* Tighter rows. */
    thead th,
    td {
        padding-block: 0.12rem;
    }

    tbody th[scope="colgroup"] {
        padding-block: 0.15rem;
        font-size: 1.05em;
    }

    /* Repeat the column headers at the top of every printed page. */
    thead {
        display: table-header-group;
    }

    /* Never split a row across two pages, or strand a group heading
       at the foot of a page away from its first price. */
    tr {
        break-inside: avoid;
    }

    /* The gap above a group heading is a paper-coloured border. On white paper
       it would print as a tinted band, so it turns white with the page. */
    tbody th[scope="colgroup"] {
        break-after: avoid;
        border-top-color: var(--white);
    }

    /* The footer keeps the address, phone, hours and copyright line, without
       tall tap targets. */
    .site-footer {
        grid-template-columns: 1fr;
        padding-top: var(--space-m);
        background: none;
        box-shadow: none;
        clip-path: none;
    }

    .site-footer-contact {
        grid-template-columns: 1fr 1fr;
    }

    .site-footer-phone a,
    .site-footer-email a {
        min-height: 0;
    }
}
