/* Responsive safeguards, loaded last so they win the cascade: nothing can
   force a horizontal scrollbar, headings wrap instead of overflowing, and the
   display scale is capped on small screens. On wide screens none of the caps
   engage, so the design is untouched. */

/* No element may create a horizontal scrollbar. overflow-x: clip (not hidden)
   keeps position: sticky and off-canvas drawers working. */
html, body { max-width: 100%; overflow-x: clip; }

/* Media and embeds never exceed their container. */
img, svg, video, canvas, iframe, embed, object, figure, picture {
  max-width: 100%;
}
img, video, canvas { height: auto; }
pre, code, kbd, samp { overflow-x: auto; max-width: 100%; }

/* A picture fills the frame drawn around it. <picture> holds the alternative
   files and has no size of its own to speak of, so it passes the frame's
   height through to the image inside it. Without this, a `height: 100%`
   written for the image is measured against a box of no height at all and
   quietly becomes `height: auto`: the frame keeps the shape it was given and
   the image takes the shape of its file, and the difference between them is
   painted in the frame's own background. Where the frame has no height of its
   own, 100% of nothing is still nothing and this changes neither box. */
picture { display: block; height: 100%; }

/* Headings and display lockups wrap instead of running off-screen. A
   white-space: nowrap that would push a headline off the edge is overridden;
   on wide screens the line still fits, so nothing wraps unnecessarily. */
h1, h2, h3, h4, h5, h6,
[class*="lockup"], [class*="display"], [class*="headline"], [class*="title"],
[class*="hero"] h1, [class*="hero"] h2 {
  overflow-wrap: break-word;
  word-break: normal;
  hyphens: manual;
}
[class*="lockup"], [class*="lockup"] > * { white-space: normal !important; }

/* Display type is set, not poured. `hyphens: auto` above used to let the
   browser cut a heading's word at a syllable to fill the line; a word in a
   headline is never cut — where one does not fit, the build measures the
   size that holds it. Short headings have their lines evened out, so a
   three-line title does not end on a single word. Figures line up in
   columns, since a price list is read down as well as across. */
h1, h2, h3 { text-wrap: balance; }
td, th, time, output, data,
[class*="price"], [class*="cost"], [class*="rate"], [class*="amount"],
[class*="figure"], [class*="stat"], [class*="number"], [class*="count"] {
  font-variant-numeric: lining-nums tabular-nums;
}

/* Long unbroken strings (URLs, emails, ids) wrap rather than overflow. On
   everything that can hold words, not a list of the elements that usually do:
   an email address in a <strong> inside a card was 192px of text in a 155px
   box, and <strong> was not on the list. The property only does anything when
   a word would otherwise overflow, so it costs a well-set page nothing. */
p, li, dd, dt, blockquote, figcaption, address, a, span, td, th,
div, strong, b, em, i, small, label, output, time, cite, abbr, code, summary,
h1, h2, h3, h4, h5, h6 {
  overflow-wrap: break-word;
}

/* Grid and flex children may shrink below their content so a single wide
   child cannot force the whole track past the viewport. */
[class*="grid"] > *, [class*="row"] > *, [class*="flex"] > *,
[class*="cols"] > *, [class*="columns"] > * { min-width: 0; }

/* An only child takes the whole row, so a grid declaring more columns than it
   has children cannot squeeze its one child into the narrow one. Ignored
   outright where the parent is not a grid; media is left out, because an image
   told to span two columns stretches. */
:not(img):not(picture):not(svg):not(video):not(canvas):only-child {
  grid-column: 1 / -1;
}

/* Wide data tables reflow into one card per row on a narrow screen, so
   nothing has to be dragged sideways to be read. Each value is printed under
   the column heading it belongs to. Where the headings could not be read off
   the table the layout is left alone and the wrapper scrolls instead. */
/* One page becomes the next instead of blinking into it. Where the browser
   does not support it nothing happens, and a visitor who prefers reduced
   motion gets plain navigation. */
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) {
  animation-duration: .28s;
}
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }
}

/* The wrapper is asked about its own width rather than the window's, because
   the two are not the same thing: a cookie table on a delivered site sat in a
   598px column on a 1920px screen, so no window breakpoint could tell that
   its five columns had 120px each. */
.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  container-type: inline-size;
}
/* No minimum width: a table allowed to compress wraps its columns and fits,
   and the scrollbar that used to appear on a wide screen was this wrapper
   holding the table out to its natural width. */
.table-scroll > table { width: 100%; }
@media (max-width: 48rem) {
  .table-scroll > table { font-size: .94em; }
}
/* A table the site stacked by hand goes back to being a table. A stacking
   rule written without labels on the cells is unreadable, and it also sets
   `width: 100%` on them, which is right for a block and ruinous for a cell: a
   table is as wide as its cells ask to be, so every cell asking for the whole
   table makes the table ask for the whole table again. Taking back only the
   display left a two-column table a million pixels wide, with the row
   headings on the phone and every value off the side of it — so the widths
   are taken back with it. */
.table-scroll > table,
.table-scroll > table > thead, .table-scroll > table > tbody,
.table-scroll > table > tfoot, .table-scroll > table tr,
.table-scroll > table th, .table-scroll > table td { display: revert; }
.table-scroll > table th, .table-scroll > table td {
  inline-size: auto;
  min-inline-size: 0;
}

/* Then the stacking rules, which are generated below this string: one block
   per column count, because how narrow is too narrow depends on how many
   columns have to fit in it. */

/* Cap the display scale on phones so no headline is bigger than the screen.
   These override the modular scale only where it is too large to fit. */
@media (max-width: 30rem) {
  :root {
    --step-7: clamp(2.2rem, 9vw, 3rem);
    --step-6: clamp(2rem, 8vw, 2.7rem);
    --step-5: clamp(1.8rem, 7vw, 2.4rem);
    --step-4: clamp(1.55rem, 6vw, 2.05rem);
    --step-3: clamp(1.35rem, 5vw, 1.8rem);
  }
}
@media (min-width: 30.01rem) and (max-width: 48rem) {
  :root {
    --step-7: clamp(2.8rem, 8vw, 4.6rem);
    --step-6: clamp(2.5rem, 7vw, 4rem);
    --step-5: clamp(2.2rem, 6vw, 3.4rem);
  }
}

/* Touch targets stay usable. */
@media (pointer: coarse) {
  a.btn, button, [role="button"], .btn,
  input[type="submit"], input[type="button"] { min-height: 44px; }
}

/* The keyboard can always see where it is. Written per element rather than
   as a bare `:focus-visible`, so it carries the same weight as the
   `a:focus { outline: none }` a reset likes to write and, loading last, wins
   it. A pointer gets no ring: `:focus-visible` is the keyboard's alone. */
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible, summary:focus-visible,
[tabindex]:focus-visible, [role="button"]:focus-visible {
  outline: 2px solid var(--focus-ring, currentColor);
  outline-offset: 3px;
}

/* What iPhone Safari does on its own, undone. It inflates text when the
   phone turns on its side; it draws its own rounded, inset-shadowed chrome
   on a field or a button the site did not style all the way down. Fields
   that are not a box of text (ticks, radios, sliders, files, colours) keep
   their native drawing, and so does <select>, whose arrow is its native
   appearance. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"]),
textarea, button, [type="submit"], [type="button"] {
  -webkit-appearance: none;
  appearance: none;
}

/* iPhone Safari zooms the page in when a field set under 16px is focused,
   and does not zoom back out when it is left. On a touch screen the type in
   a field is never under 16px, whatever the sheet says; `!important` because
   the sheet says it with a class and this is the net under the sheet. Only
   where the pointer is a finger and the screen is a phone's: on a desk a
   14px field is simply small, and the audit reports it. */
@media (pointer: coarse) and (max-width: 767px) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"]),
  select, textarea { font-size: max(16px, 1em) !important; }
}

/* One card per row, once there is no longer room for the columns. Asked of the
   wrapper rather than the window: the two are not the same width. */
@container (max-width: 26rem) {
  .table-scroll.table-stack.tcols-3 > table,
  .table-scroll.table-stack.tcols-3 > table > tbody,
  .table-scroll.table-stack.tcols-3 > table > tbody > tr,
  .table-scroll.table-stack.tcols-3 > table > tbody > tr > td,
  .table-scroll.table-stack.tcols-3 > table > tbody > tr > th {
    display: block;
    inline-size: auto;
    /* The site's own minimum has to go with the table layout. A table told to
       be at least 580px wide stays 580px wide as a stack of cards too, and
       the wrapper goes on scrolling: measured at 390px, cards 570px wide in a
       355px box. */
    min-inline-size: 0 !important;
  }
  /* The heading row goes, rather than being hidden the way a screen-reader
     label is hidden. Taking the table out of table layout has already taken
     its headings away from assistive technology — a block is not a table and
     the cell/heading association does not survive it — so a clipped `thead`
     would be an empty gesture that still laid its cells out at full width
     underneath the cards. Each value carries its own heading instead. */
  .table-scroll.table-stack.tcols-3 > table > thead { display: none; }
  .table-scroll.table-stack.tcols-3 > table > tbody > tr {
    margin-block-end: .75rem;
    padding: .2rem .25rem;
    border: 1px solid;
    border-color: color-mix(in srgb, currentColor 20%, transparent);
    border-radius: .5rem;
  }
  .table-scroll.table-stack.tcols-3 > table > tbody > tr > td {
    padding-block: .4rem;
    padding-inline: .7rem;
  }
  /* The label above the value rather than beside it: at 320px a label column
     wide enough to read leaves the value too narrow to. */
  .table-scroll.table-stack.tcols-3 > table > tbody > tr > td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-size: .82em;
    font-weight: 600;
    letter-spacing: .02em;
    opacity: .68;
  }
  .table-scroll.table-stack.tcols-3 > table > tbody > tr > td:empty { display: none; }
}
@container (max-width: 35rem) {
  .table-scroll.table-stack.tcols-4 > table,
  .table-scroll.table-stack.tcols-4 > table > tbody,
  .table-scroll.table-stack.tcols-4 > table > tbody > tr,
  .table-scroll.table-stack.tcols-4 > table > tbody > tr > td,
  .table-scroll.table-stack.tcols-4 > table > tbody > tr > th {
    display: block;
    inline-size: auto;
    /* The site's own minimum has to go with the table layout. A table told to
       be at least 580px wide stays 580px wide as a stack of cards too, and
       the wrapper goes on scrolling: measured at 390px, cards 570px wide in a
       355px box. */
    min-inline-size: 0 !important;
  }
  /* The heading row goes, rather than being hidden the way a screen-reader
     label is hidden. Taking the table out of table layout has already taken
     its headings away from assistive technology — a block is not a table and
     the cell/heading association does not survive it — so a clipped `thead`
     would be an empty gesture that still laid its cells out at full width
     underneath the cards. Each value carries its own heading instead. */
  .table-scroll.table-stack.tcols-4 > table > thead { display: none; }
  .table-scroll.table-stack.tcols-4 > table > tbody > tr {
    margin-block-end: .75rem;
    padding: .2rem .25rem;
    border: 1px solid;
    border-color: color-mix(in srgb, currentColor 20%, transparent);
    border-radius: .5rem;
  }
  .table-scroll.table-stack.tcols-4 > table > tbody > tr > td {
    padding-block: .4rem;
    padding-inline: .7rem;
  }
  /* The label above the value rather than beside it: at 320px a label column
     wide enough to read leaves the value too narrow to. */
  .table-scroll.table-stack.tcols-4 > table > tbody > tr > td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-size: .82em;
    font-weight: 600;
    letter-spacing: .02em;
    opacity: .68;
  }
  .table-scroll.table-stack.tcols-4 > table > tbody > tr > td:empty { display: none; }
}
@container (max-width: 44rem) {
  .table-scroll.table-stack.tcols-5 > table,
  .table-scroll.table-stack.tcols-5 > table > tbody,
  .table-scroll.table-stack.tcols-5 > table > tbody > tr,
  .table-scroll.table-stack.tcols-5 > table > tbody > tr > td,
  .table-scroll.table-stack.tcols-5 > table > tbody > tr > th {
    display: block;
    inline-size: auto;
    /* The site's own minimum has to go with the table layout. A table told to
       be at least 580px wide stays 580px wide as a stack of cards too, and
       the wrapper goes on scrolling: measured at 390px, cards 570px wide in a
       355px box. */
    min-inline-size: 0 !important;
  }
  /* The heading row goes, rather than being hidden the way a screen-reader
     label is hidden. Taking the table out of table layout has already taken
     its headings away from assistive technology — a block is not a table and
     the cell/heading association does not survive it — so a clipped `thead`
     would be an empty gesture that still laid its cells out at full width
     underneath the cards. Each value carries its own heading instead. */
  .table-scroll.table-stack.tcols-5 > table > thead { display: none; }
  .table-scroll.table-stack.tcols-5 > table > tbody > tr {
    margin-block-end: .75rem;
    padding: .2rem .25rem;
    border: 1px solid;
    border-color: color-mix(in srgb, currentColor 20%, transparent);
    border-radius: .5rem;
  }
  .table-scroll.table-stack.tcols-5 > table > tbody > tr > td {
    padding-block: .4rem;
    padding-inline: .7rem;
  }
  /* The label above the value rather than beside it: at 320px a label column
     wide enough to read leaves the value too narrow to. */
  .table-scroll.table-stack.tcols-5 > table > tbody > tr > td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-size: .82em;
    font-weight: 600;
    letter-spacing: .02em;
    opacity: .68;
  }
  .table-scroll.table-stack.tcols-5 > table > tbody > tr > td:empty { display: none; }
}
@container (max-width: 52rem) {
  .table-scroll.table-stack.tcols-6 > table,
  .table-scroll.table-stack.tcols-6 > table > tbody,
  .table-scroll.table-stack.tcols-6 > table > tbody > tr,
  .table-scroll.table-stack.tcols-6 > table > tbody > tr > td,
  .table-scroll.table-stack.tcols-6 > table > tbody > tr > th {
    display: block;
    inline-size: auto;
    /* The site's own minimum has to go with the table layout. A table told to
       be at least 580px wide stays 580px wide as a stack of cards too, and
       the wrapper goes on scrolling: measured at 390px, cards 570px wide in a
       355px box. */
    min-inline-size: 0 !important;
  }
  /* The heading row goes, rather than being hidden the way a screen-reader
     label is hidden. Taking the table out of table layout has already taken
     its headings away from assistive technology — a block is not a table and
     the cell/heading association does not survive it — so a clipped `thead`
     would be an empty gesture that still laid its cells out at full width
     underneath the cards. Each value carries its own heading instead. */
  .table-scroll.table-stack.tcols-6 > table > thead { display: none; }
  .table-scroll.table-stack.tcols-6 > table > tbody > tr {
    margin-block-end: .75rem;
    padding: .2rem .25rem;
    border: 1px solid;
    border-color: color-mix(in srgb, currentColor 20%, transparent);
    border-radius: .5rem;
  }
  .table-scroll.table-stack.tcols-6 > table > tbody > tr > td {
    padding-block: .4rem;
    padding-inline: .7rem;
  }
  /* The label above the value rather than beside it: at 320px a label column
     wide enough to read leaves the value too narrow to. */
  .table-scroll.table-stack.tcols-6 > table > tbody > tr > td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-size: .82em;
    font-weight: 600;
    letter-spacing: .02em;
    opacity: .68;
  }
  .table-scroll.table-stack.tcols-6 > table > tbody > tr > td:empty { display: none; }
}
@container (max-width: 61rem) {
  .table-scroll.table-stack.tcols-7 > table,
  .table-scroll.table-stack.tcols-7 > table > tbody,
  .table-scroll.table-stack.tcols-7 > table > tbody > tr,
  .table-scroll.table-stack.tcols-7 > table > tbody > tr > td,
  .table-scroll.table-stack.tcols-7 > table > tbody > tr > th {
    display: block;
    inline-size: auto;
    /* The site's own minimum has to go with the table layout. A table told to
       be at least 580px wide stays 580px wide as a stack of cards too, and
       the wrapper goes on scrolling: measured at 390px, cards 570px wide in a
       355px box. */
    min-inline-size: 0 !important;
  }
  /* The heading row goes, rather than being hidden the way a screen-reader
     label is hidden. Taking the table out of table layout has already taken
     its headings away from assistive technology — a block is not a table and
     the cell/heading association does not survive it — so a clipped `thead`
     would be an empty gesture that still laid its cells out at full width
     underneath the cards. Each value carries its own heading instead. */
  .table-scroll.table-stack.tcols-7 > table > thead { display: none; }
  .table-scroll.table-stack.tcols-7 > table > tbody > tr {
    margin-block-end: .75rem;
    padding: .2rem .25rem;
    border: 1px solid;
    border-color: color-mix(in srgb, currentColor 20%, transparent);
    border-radius: .5rem;
  }
  .table-scroll.table-stack.tcols-7 > table > tbody > tr > td {
    padding-block: .4rem;
    padding-inline: .7rem;
  }
  /* The label above the value rather than beside it: at 320px a label column
     wide enough to read leaves the value too narrow to. */
  .table-scroll.table-stack.tcols-7 > table > tbody > tr > td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-size: .82em;
    font-weight: 600;
    letter-spacing: .02em;
    opacity: .68;
  }
  .table-scroll.table-stack.tcols-7 > table > tbody > tr > td:empty { display: none; }
}


/* Consent — a corner card on a desk, a short bar on a phone, and late. */
@keyframes consent-arrive { from { opacity: 0; } }
.cookie-banner {
  max-height: 30vh;
  overflow: auto;
  box-sizing: border-box;
  top: auto;
  bottom: 0;
}
html body .cookie-banner.cookie-banner {
  animation: consent-arrive .6s ease-out 1.8s backwards !important;
}
@media (min-width: 48rem) {
  html body .cookie-banner.cookie-banner {
    position: fixed !important;
    top: auto !important;
    bottom: var(--consent-bottom, 1.25rem) !important;
    left: var(--consent-left, 1.25rem) !important;
    right: auto !important;
    width: min(380px, calc(100vw - 2.5rem)) !important;
    max-width: 380px !important;
    max-height: min(60vh, 30rem) !important;
    margin: 0 !important;
    padding: 1.1rem 1.25rem !important;
    flex-direction: column !important;
    align-items: stretch !important;
    justify-content: flex-start !important;
    gap: .8rem !important;
  }
  .cookie-banner > :where(div, form, section, nav):not([hidden]) {
    display: flex !important;
    flex-direction: column !important;
    align-items: stretch !important;
    justify-content: flex-start !important;
    gap: .8rem !important;
  }
  /* A `flex: 1 1 320px` written for a row is a 320px HEIGHT in a column. */
  .cookie-banner > :not([hidden]),
  .cookie-banner > :where(div, form, section, nav):not([hidden]) > :not([hidden]) {
    flex: 0 0 auto !important;
    min-width: 0;
    width: auto !important;
    max-width: none !important;
    margin: 0 !important;
  }
  .cookie-banner :where(div, p, nav, form, section) {
    flex-wrap: wrap;
  }
}
@media (prefers-reduced-motion: reduce) {
  html body .cookie-banner.cookie-banner { animation-duration: .01s !important; }
}
