/* Reset */

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

* {
  margin: 0;
}

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

/* The article rule gives the markers back to prose lists. */
ul,
ol {
  padding: 0;

  list-style: none;
}

/* Design tokens */
:root {
  color-scheme: light dark;

  --font-size: 1.125rem;
  --scale: 1.414;
  --baseline: 1.7rem;

  /* Typography */
  --font: "Mona Sans", sans-serif;

  /* A full step below 1rem is 11px, so --text-sm and --text-md are half steps. */
  --text-sm: calc(1rem / sqrt(var(--scale)));
  --text-base: 1rem;
  --text-md: calc(1rem * sqrt(var(--scale)));
  --text-lg: calc(1rem * var(--scale));
  --text-xl: calc(var(--text-lg) * var(--scale));
  --text-2xl: calc(var(--text-xl) * var(--scale));
  --text-3xl: calc(var(--text-2xl) * var(--scale));

  /*
   * Use --space-v-* for vertical space and ch units for horizontal space.
   *
   * Use xs, sm and md only in pairs that make one whole baseline, for example
   * the padding above and below a line box. One alone moves all content below
   * it off the grid. Do not use them as a line-height.
   */
  --space-v-xs: calc(var(--baseline) * 0.25);
  --space-v-sm: calc(var(--baseline) * 0.5);
  --space-v-base: var(--baseline);
  --space-v-md: calc(var(--baseline) * 1.5);
  --space-v-lg: calc(var(--baseline) * 2);
  --space-v-xl: calc(var(--baseline) * 3);

  /* Layout */
  --content-width: 1200px;
  --measure: 68ch;
  --gutter: 4ch;

  /*
   * The --color-inverse-* set does not change with the colour scheme. The
   * hero and the footer use it, so they look the same in light and dark.
   */
  --color-background: #FAF9F7;
  --color-surface: #F1EEE9;
  --color-text: #1A1815;
  --color-text-muted: #6B655C;
  --color-border: #C7C3BD;
  --color-accent: #B5471E;

  --color-inverse-background: #17150F;
  --color-inverse-text: #F5F2EC;
  --color-inverse-muted: #A69C8C;
  --color-inverse-border: #38332A;
  --color-inverse-accent: #E8763F;

  /*
   * The grid does not control the width of a border. The display draws a
   * hairline at its own width, and a box with a border is that much taller
   * than the baselines it measures. Do not subtract the border from padding:
   * padding uses CSS pixels and a border uses device pixels, and the two are
   * equal only at whole-number display scaling. Give the box a fixed height.
   *
   * Set both to 0px to compare the page against the debug grid.
   */
  --border: 1px solid var(--color-border);
  --border-strong: 1px solid var(--color-text);
}

@media (prefers-color-scheme: dark) {
  :root {
    /* Darker than --color-inverse-background, so the panels stay visible. */
    --color-background: #100F0D;
    --color-surface: #1B1915;
    --color-text: #EDEAE4;
    --color-text-muted: #9C948A;
    --color-border: #2E2B25;
    --color-accent: #E8763F;
  }
}

/* Base styles */
html {
  font-family: var(--font);
  font-size: var(--font-size);
  line-height: var(--baseline);

  font-optical-sizing: auto;
  font-weight: 400;
  font-style: normal;
  font-variation-settings: "wdth" 100;

  color: var(--color-text);
  background-color: var(--color-background);

  accent-color: var(--color-accent);
  -webkit-text-size-adjust: none;
}

body {
  display: flex;
  flex-direction: column;

  min-height: 100vh;
}

/* An option shows the outline on its label, not on the input inside it. */
:focus-visible,
.options label:has(:focus-visible) {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

/* Typography */

/*
 * Every line-height is a whole number of baselines.
 *
 * Headings have a bottom margin and no top margin, so the element above sets
 * the gap. A top margin would need margin collapse, and a flex container does
 * not collapse margins. h3 has no bottom margin because it introduces the
 * block below it.
 */

h1,
h2,
h3 {
  font-weight: 700;
  text-wrap: balance;
  overflow-wrap: break-word;
}

h1,
h2 {
  line-height: var(--space-v-lg);

  margin-block-end: var(--space-v-base);
}

h1 {
  font-size: var(--text-2xl);
  letter-spacing: -0.02em;
}

h2 {
  font-size: var(--text-xl);
  letter-spacing: -0.01em;
}

h3 {
  font-size: var(--text-lg);
  line-height: var(--space-v-base);
}

p {
  text-wrap: pretty;

  margin-block: 0 var(--space-v-base);
}

small {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

strong {
  font-weight: 600;
}

:is(h1, h2, h3, p):last-child {
  margin-block-end: 0;
}

a {
  color: inherit;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

a:hover {
  text-decoration-color: var(--color-accent);
}

/* A half step. A full step is h3 size, which needs more leading than one baseline. */
.lead {
  font-size: var(--text-md);
  line-height: var(--space-v-base);
  color: var(--color-text-muted);

  max-width: 44ch;
}

.eyebrow {
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent);

  margin-block-end: 0;
}

.skip-link {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: var(--gutter);
  z-index: 10;

  padding-inline: 2ch;

  font-size: var(--text-sm);
  font-weight: 600;

  color: var(--color-background);
  background-color: var(--color-text);
}

.skip-link:not(:focus):not(:focus-visible) {
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Header */

.site-header {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-v-base) var(--gutter);

  width: 100%;
  max-width: var(--content-width);
  margin-inline: auto;

  padding-block: var(--space-v-sm);
  padding-inline: var(--gutter);
}

/* The tallest item in the header, so this height is the height of the row. */
.brand {
  display: flex;
  align-items: center;

  height: var(--space-v-lg);

  text-decoration: none;
}

/*
 * aspect-ratio gives the width before the file loads, so there is no reflow.
 * The file sets its own colours. See assets/img/logo-text.svg.
 */
.brand__logo {
  width: auto;
  height: 2.25rem;
  aspect-ratio: 148.8914 / 43.2296;
}

/* Navigation */

/* Row gap 0: each item is one line box, so a wrapped nav stays on the grid. */
.nav > ul {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0 3ch;
}

.nav > ul > li {
  font-size: var(--text-sm);
  font-weight: 600;
}

.nav a {
  letter-spacing: 0.08em;
  text-decoration: none;
  text-transform: uppercase;
}

.nav :is(a:hover, [aria-current="page"]) {
  text-decoration: underline;
  text-underline-offset: 0.4em;
}

.nav [aria-current="page"] {
  color: var(--color-accent);
}

/* Main */

main {
  display: flex;
  flex-direction: column;
  flex: 1 0 auto;
}

section {
  display: flex;
  flex-direction: column;
  align-items: center;

  padding-block: var(--space-v-lg);
  padding-inline: var(--gutter);

  text-align: center;
}

/* Block children use --content-width. Running text stops at --measure. */
section > * {
  width: 100%;
  max-width: var(--content-width);
}

section > :is(h2, h3, p, .eyebrow):not(.lead) {
  max-width: var(--measure);
}

.section--surface {
  background-color: var(--color-surface);
}

/* Inverse panels */

/*
 * These two panels change the tokens instead of the components. Every element
 * inside them then uses the inverse palette without a rule of its own.
 */
.hero,
footer {
  --color-accent: var(--color-inverse-accent);
  --color-background: var(--color-inverse-background);
  --color-border: var(--color-inverse-border);
  --color-text: var(--color-inverse-text);
  --color-text-muted: var(--color-inverse-muted);

  color: var(--color-text);
  background-color: var(--color-background);
}

/* Hero */

/* isolation lets ::before use a negative z-index and stay above the background. */
.hero {
  position: relative;
  isolation: isolate;

  padding-block: var(--space-v-xl);
}

/* Decoration, so it is not in the markup. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;

  background-image: radial-gradient(
    70% 60% at 50% 106%,
    color-mix(in oklab, var(--color-accent) 45%, transparent),
    transparent 72%
  );
}

.hero h1 {
  font-size: var(--text-3xl);
  line-height: var(--space-v-xl);

  max-width: 16ch;
}

.hero .actions {
  margin-block-start: var(--space-v-base);
}

/* Actions */

.actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-v-base) 2ch;
}

/* Content pages */

/* <section> is full width and centred. <article> is one measure wide, ranged left. */
article {
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;

  padding-block: var(--space-v-lg);
  padding-inline: var(--gutter);
}

/* Gives back the markers the reset removed. */
article :is(ul, ol) {
  padding-inline-start: 3ch;
  margin-block: 0 var(--space-v-base);

  list-style: revert;
}

.page-header {
  max-width: var(--measure);
  margin-inline: auto;

  padding-block: var(--space-v-lg) 0;
  padding-inline: var(--gutter);
}

/*
 * One baseline tall, with the border on its bottom edge, so the space and the
 * border together measure one baseline.
 */
.page-header::after {
  content: "";
  display: block;

  inline-size: 6ch;
  block-size: var(--space-v-base);

  border-block-end: 2px solid var(--color-accent);
}

/* Cards */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(26ch, 1fr));
  gap: var(--space-v-base) var(--gutter);

  counter-reset: card;

  margin-block-start: var(--space-v-base);

  text-align: start;
}

.cards > li {
  counter-increment: card;

  padding-block-start: var(--space-v-sm);

  border-block-start: var(--border);
}

.cards > li::before {
  content: counter(card, decimal-leading-zero);

  display: block;

  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--color-accent);
}

.cards h3 {
  margin-block-end: var(--space-v-sm);
}

/* Price list */

.pricelist {
  max-width: var(--measure);

  margin-block: var(--space-v-base);

  text-align: start;
}

.pricelist > li {
  display: flex;
  align-items: baseline;
  gap: 1.5ch;

  line-height: var(--space-v-base);
}

/* order puts the leader between the two spans, so the markup needs no third element. */
.pricelist > li::after {
  content: "";
  order: 0;
  flex: 1;

  border-block-end: 1px dotted var(--color-border);
  translate: 0 -0.25em;
}

.pricelist > li > :last-child {
  order: 1;

  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Tables */

.table-scroll {
  overflow-x: auto;
}

/* Two baselines, because a table needs more space below it than a paragraph. */
.table-scroll:not(:last-child) {
  margin-block-end: var(--space-v-lg);
}

table {
  width: 100%;

  border-collapse: collapse;
}

th,
td {
  padding-block: var(--space-v-sm);
  padding-inline-end: 2ch;

  text-align: start;
  vertical-align: baseline;
  white-space: nowrap;
}

th[scope="row"] {
  text-align: center;
}

th {
  font-weight: 600;
}

td {
  font-variant-numeric: tabular-nums;
}

/* No bottom margin: the padding of the header row is the space below it. */
caption {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  text-align: start;
}

thead :is(th, td) {
  border-block-end: var(--border-strong);
}

tbody tr + tr :is(th, td) {
  border-block-start: var(--border);
}

tbody tr:hover :is(th, td) {
  background-color: var(--color-surface);
}

:is(th, td) small {
  display: block;
}

/* Accordions */

details {
  border-block-start: var(--border);
}

details:last-of-type {
  border-block-end: var(--border);
}

summary {
  display: flex;
  align-items: baseline;
  gap: 1.5ch;

  padding-block: var(--space-v-sm);

  font-weight: 600;
  list-style: none;
  cursor: pointer;
}

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

summary::before {
  content: "+";

  font-weight: 400;
  color: var(--color-accent);
}

details[open] summary::before {
  content: "−";
}

summary:hover {
  color: var(--color-accent);
}

details > :not(summary):last-child {
  margin-block-end: var(--space-v-base);
}

/* Gallery */

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(22ch, 1fr));
  gap: var(--space-v-base) 2ch;

  margin-block: var(--space-v-base);
}

/*
 * The column width and the 4:3 ratio do not give a whole number of baselines,
 * so round() moves the height to the nearest one. cqw measures the column,
 * which is why the figure is a container. If the browser does not support
 * round(), block-size is invalid and aspect-ratio applies.
 */
.gallery figure {
  container-type: inline-size;
}

.gallery img {
  inline-size: 100%;
  aspect-ratio: 4 / 3;
  block-size: round(75cqw, var(--baseline));
  object-fit: cover;

  background-color: var(--color-surface);
}

.gallery figcaption {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* Forms */

input,
select,
textarea,
button {
  font: inherit;
  color: inherit;
}

/*
 * A group is 2.5 baselines: one line box for the label and 1.5 for the
 * control. The gap must first replace that half baseline, so the only values
 * that keep the grid are 0.5 and 1.5. This uses 1.5.
 */
form {
  display: flex;
  flex-direction: column;
  gap: var(--space-v-base);
}

/* flex, not a line of inline boxes: the strut of a line box adds height below the button. */
form .actions {
  justify-content: start;

  margin-block-start: var(--space-v-base);
}

form label {
  display: block;
}

.field > label,
legend {
  font-weight: 600;
}

fieldset {
  padding: 0;

  border: 0;
}

legend {
  padding: 0;
}

.options {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-v-sm) 1ch;
}

.options label {
  display: flex;
  align-items: center;
  gap: 1ch;

  block-size: var(--space-v-md);
  padding-inline: 1.5ch;

  border: var(--border);
  cursor: pointer;
}

/* <small> is a flex item, so it has its own line box. 1 aligns it with the label. */
.options small {
  line-height: 1;
}

.options label:hover {
  border-color: var(--color-text-muted);
}

.options label:has(:checked) {
  color: var(--color-accent);
  border-color: var(--color-accent);
  box-shadow: inset 0 0 0 1px var(--color-accent);
}

.options label:has(:disabled) {
  border: 0;
  color: var(--color-text-muted);
  text-decoration: line-through;
}

.options input:focus-visible {
  outline: none;
}

/*
 * These controls have a fixed height, because browsers do not agree on the
 * line box of a single-line input. box-sizing is border-box, so the border is
 * inside that height.
 *
 * display is block because a textarea takes its baseline from its bottom
 * edge. Inline, it also carries the descender space of its line. 5.5
 * baselines is what rows="5" gives. The attribute stays for a reader with no
 * stylesheet, but block-size sets the height.
 */
input[type="text"],
input[type="email"],
input[type="tel"],
textarea {
  display: block;
  inline-size: 100%;

  padding-block: 0;
  padding-inline: 1ch;

  background-color: var(--color-background);
  border: var(--border);
}

input[type="text"],
input[type="email"],
input[type="tel"] {
  block-size: var(--space-v-md);
}

input:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 0;
  border-color: var(--color-accent);
}

/* Auto-resize textarea */
textarea {
  field-sizing: content;
  min-height: var(--space-v-xl)
}

/* Buttons */

/* Fixed height. box-sizing is border-box, so the border is inside it. See --border. */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;

  block-size: var(--space-v-lg);
  padding-block: 0;
  padding-inline: 3ch;

  font-size: var(--text-base);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-align: center;
  text-decoration: none;
  text-transform: uppercase;

  color: var(--color-background);
  background-color: var(--color-accent);
  border: 1px solid var(--color-accent);
  cursor: pointer;

  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.button:hover {
  color: var(--color-accent);
  background-color: transparent;
}

/* inherit and currentColor make this work on the inverse palette too. */
.button--ghost {
  color: inherit;
  background-color: transparent;
  border-color: currentColor;
}

.button--ghost:hover {
  color: var(--color-background);
  background-color: var(--color-text);
  border-color: var(--color-text);
}

/* Footer */

footer {
  font-size: var(--text-sm);

  padding-block: var(--space-v-lg);
  padding-inline: var(--gutter);
}

footer nav > ul {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-v-base) var(--gutter);

  margin-inline: auto;

  max-width: var(--content-width);
}

footer h2 {
  font-size: inherit;
  font-weight: 600;
  line-height: var(--space-v-base);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);

  margin-block-end: 0;
}

footer nav a:not(:hover) {
  text-decoration: none;
}

footer nav a:hover {
  color: var(--color-accent);
}

/*
 * Narrow viewports
 *
 * One breakpoint. A smaller --scale changes every size, space and line box.
 * What remains is the two rows that become columns, and the hero headline,
 * which drops one step but keeps its line box.
 */
@media (max-width: 48rem) {
  :root {
    --font-size: 1rem;
    --scale: 1.4;
    --gutter: 2ch;
  }

  .hero h1 {
    font-size: var(--text-2xl);
    line-height: var(--space-v-lg);
  }

  .site-header {
    flex-direction: column;
    gap: var(--space-v-base);
  }

  footer nav > ul {
    flex-direction: column;
    align-items: center;
    gap: var(--space-v-base);

    text-align: center;
  }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}

/*
 * Debug: vertical rhythm
 *
 * Draws a band over every second baseline, above the page content. Delete
 * these two rules to remove it. Nothing else uses them.
 *
 * A box on the rhythm starts and ends on a line, and a line of text sits in
 * the band below one. Set --border and --border-strong to 0px before you
 * compare, because one hairline is enough to move a box off a line.
 */
/*
body {
  position: relative;
}

body::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 999;
  pointer-events: none;

  background-image: linear-gradient(
    to bottom,
    oklch(0.7 0.15 250 / 0.1) 0%,
    oklch(0.7 0.15 250 / 0.1) 50%,
    transparent 50%,
    transparent 100%
  );
  background-size: 100% calc(var(--baseline) * 2);
}
*/
