/*
 * Entry stylesheet. Every file is imported from here, one level deep, and the
 * server bundles them into one file (src/stylesheet.rs). Imported files can't
 * import others, and their url()s must start with "/".
 */
@layer reset, tokens, base, components, pages;

@layer reset {
/* https://piccalil.li/blog/a-more-modern-css-reset/ */
/* Overrides from Kevin Powell */
/* Imported into the `reset` layer by main.css. Its font and width variables
   come from tokens/semantic/typography.css. */

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

/* Prevent font size inflation */
html {
  -moz-text-size-adjust: none;
  -webkit-text-size-adjust: none;
  text-size-adjust: none;

  font-family: var(--font-family-base);
  hanging-punctuation: first last;
  interpolate-size: allow-keywords;
}

/* Remove default margin in favour of better control in authored CSS */
body,
h1,
h2,
h3,
h4,
p,
figure,
blockquote,
dl,
dd {
  margin-block-end: 0;
}

/* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */
:is(ul, ol)[class] {
  list-style: "";
  margin: 0;
  padding: 0;
}

/* Set core body defaults */
body {
  margin: 0;
  min-height: 100vh;
  line-height: var(--font-family-base-line-height);
}

/* Set shorter line heights on headings and interactive elements */
h1,
h2,
h3,
h4,
button,
input,
label {
  line-height: var(--font-family-heading-line-height);
}

/* Inherit fonts for inputs and buttons */
input,
button,
textarea,
select {
  font-family: inherit;
  font-size: inherit;
}

/* Balance text wrapping on headings */
h1,
h2,
h3,
h4 {
  text-wrap: balance;
  font-family: var(--font-family-heading);
}

/* Prevents orphaned words on last line of paragraph */
p,
li,
figcaption {
  max-width: var(--body-max-width);
  text-wrap: pretty;
}

code {
  font-family: var(--font-family-code);
}

/* A elements that don't have a class get default styles */
a:not([class]) {
  text-decoration-skip-ink: auto;
  color: currentColor;
}

/* Make images easier to work with */
img,
picture {
  max-width: 100%;
  display: block;
}

/* Make sure textareas without a rows attribute are not tiny */
textarea:not([rows]) {
  min-height: 10em;
}

/* Align column numbers */
td,
math,
time[datetime*=":"] {
  font-variant-numeric: tabular-nums lining-nums;
}

/* Anything that has been anchored to should have extra scroll margin */
:target {
  scroll-margin-block: 5rlh;
}

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

/* Keep `hidden` elements hidden, even when a class gives them a display.
   `!important` in this first layer wins over every later one. */
[hidden] {
  display: none !important;
}
}

@layer tokens {
/*
 * Raw palette. Values match web/'s theme (Tailwind's zinc, yellow and red), and
 * only the steps the semantic tokens use are defined. Never reference these
 * from components; use tokens/semantic/colors.css.
 */
:root {
  --color-white: oklch(100% 0 0);
  --color-white-a10: oklch(100% 0 0 / 10%);
  --color-black-a10: oklch(0% 0 0 / 10%);

  --color-zinc-050: oklch(98.5% 0 0);
  --color-zinc-100: oklch(96.7% 0.001 286.375);
  --color-zinc-200: oklch(92% 0.004 286.32);
  --color-zinc-400: oklch(70.5% 0.015 286.067);
  --color-zinc-500: oklch(55.2% 0.016 285.938);
  --color-zinc-800: oklch(27.4% 0.006 286.033);
  --color-zinc-900: oklch(21% 0.006 285.885);
  --color-zinc-950: oklch(14.1% 0.005 285.823);

  --color-yellow-400: oklch(85.2% 0.199 91.936);
  --color-yellow-500: oklch(79.5% 0.184 86.047);
  --color-yellow-600: oklch(55.4% 0.135 66.442);
  --color-yellow-800: oklch(42.1% 0.095 57.708);

  --color-red-400: oklch(70.4% 0.191 22.216);
  --color-red-600: oklch(57.7% 0.245 27.325);
}
}
@layer tokens {
:root {
  /* 8px base unit. Names are the multiple of the base, ×100. */
  --size-000: 0rem; /* 0px */
  --size-025: 0.125rem; /* 2px */
  --size-050: 0.25rem; /* 4px */
  --size-075: 0.375rem; /* 6px */
  --size-100: 0.5rem; /* 8px */
  --size-150: 0.75rem; /* 12px */
  --size-175: 0.875rem; /* 14px */
  --size-200: 1rem; /* 16px */
  --size-250: 1.25rem; /* 20px */
  --size-300: 1.5rem; /* 24px */
  --size-400: 2rem; /* 32px */
  --size-500: 2.5rem; /* 40px */
  --size-600: 3rem; /* 48px */
  --size-650: 3.25rem; /* 52px */
  --size-700: 3.5rem; /* 56px */
  --size-800: 4rem; /* 64px */
  --size-1000: 5rem; /* 80px */
  --size-1200: 6rem; /* 96px */
  --size-1300: 6.5rem; /* 104px */
  --size-1600: 8rem; /* 128px */
  --size-2400: 12rem; /* 192px */
}
}
@layer tokens {
/*
 * Geist 1.5.0 (https://github.com/vercel/geist-font), SIL Open Font License;
 * see /static/fonts/geist/OFL.txt. One variable file covers every weight.
 */
@font-face {
  font-family: "Geist";
  src: url("/static/fonts/geist/geist-1.5.0-variable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  /* Use Geist only if it arrives almost immediately; otherwise keep the
     fallback for this page view rather than swapping and shifting layout. */
  font-display: optional;
}

/*
 * Atkinson Hyperlegible Next v7, latin subset (via Fontsource), SIL Open Font
 * License; see /static/fonts/atkinson-hyperlegible-next/OFL.txt. Made for
 * telling similar letters apart, so it's the face for the RSVP word.
 */
@font-face {
  font-family: "Atkinson Hyperlegible Next";
  src: url("/static/fonts/atkinson-hyperlegible-next/atkinson-hyperlegible-next-v7-latin-variable.woff2")
    format("woff2");
  font-weight: 200 800;
  font-style: normal;
  font-display: optional;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304,
    U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
}
@layer tokens {
:root {
  /* Lines */
  --border-width: 1px;
  /* Rings that need to read at a glance, like a slider thumb's. */
  --border-width-thick: var(--size-025); /* 2px */

  /* Corners */
  --radius-sm: var(--size-050); /* 4px */
  --radius-md: var(--size-075); /* 6px */
  --radius-lg: var(--size-100); /* 8px */
  --radius-xl: var(--size-300); /* 24px */
  /* Fully round ends, whatever the height. */
  --radius-pill: 999rem;

  /* Keyboard focus */
  --focus-ring-width: 2px;
  --focus-ring-offset: 2px;
}
}
@layer tokens {
/*
 * Colors by role. Each is `light-dark(light, dark)`, which follows the
 * `color-scheme` set in base/document.css, so dark mode needs no extra rules.
 */
:root {
  /* Surface */
  --color-surface-primary: light-dark(var(--color-white), var(--color-zinc-950));
  --color-surface-secondary: light-dark(var(--color-zinc-100), var(--color-zinc-900));
  /* A panel floating above the page, like the reader. */
  --color-surface-raised: light-dark(var(--color-white), var(--color-zinc-900));
  /* Behind tracks and other inset parts of a control. */
  --color-surface-muted: light-dark(var(--color-zinc-200), var(--color-zinc-800));
  /* A faint wash of the brand color, behind accent-colored icons or text. */
  --color-surface-accent: color-mix(in oklch, var(--color-primary) 15%, transparent);

  /* Text */
  --color-text-primary: light-dark(var(--color-zinc-950), var(--color-zinc-050));
  --color-text-secondary: light-dark(var(--color-zinc-500), var(--color-zinc-400));
  /* Brand-colored text. Darker than --color-primary in light mode, since that
     yellow is too faint to read on white. */
  --color-text-accent: light-dark(var(--color-yellow-600), var(--color-yellow-400));

  /* Brand */
  --color-primary: light-dark(var(--color-yellow-400), var(--color-yellow-500));
  --color-on-primary: var(--color-yellow-800);

  /* Feedback */
  --color-destructive: light-dark(var(--color-red-600), var(--color-red-400));

  /* Controls */
  --color-control-thumb: var(--color-white);

  /* Shadows */
  --color-shadow: var(--color-black-a10);

  /* Lines */
  --color-border: light-dark(var(--color-zinc-200), var(--color-white-a10));
  --color-focus-ring: light-dark(var(--color-yellow-500), var(--color-yellow-600));
}
}
@layer tokens {
:root {
  /* Sliders and progress bars */
  --track-height-sm: var(--size-050); /* 4px */
  --thumb-size: var(--size-200); /* 16px */

  /* Buttons */
  --control-size-sm: var(--size-400); /* 32px, small pills like speed presets */
  --control-size-lg: var(--size-650); /* 52px, the reader's round play button */

  /* RSVP reader */
  --reader-stage-height: calc(2 * var(--size-1300)); /* 208px, the space the word sits in */
  --reader-guide-length: var(--size-700); /* 56px, each half of the line marking the fixed point */
}
}
@layer tokens {
:root {
  /* Icon sizes */
  --icon-size-sm: var(--size-200); /* 16px, beside small text */
  --icon-size-md: var(--size-250); /* 20px */
}
}
@layer tokens {
:root {
  /* Lifts small things, like a slider's thumb, just off the surface. */
  --shadow-sm: 0 var(--size-025) var(--size-050) var(--color-shadow);
  /* Floats a panel above the page. */
  --shadow-lg: 0 var(--size-250) var(--size-300) calc(-1 * var(--size-075)) var(--color-shadow),
    0 var(--size-100) var(--size-150) calc(-1 * var(--size-075)) var(--color-shadow);
}
}
@layer tokens {
:root {
  /* Gaps, padding and margins. --space-N is N × 4px; a missing N is a step the
     scale skips. */
  --space-0: var(--size-000); /* 0px */
  --space-2: var(--size-100); /* 8px */
  --space-3: var(--size-150); /* 12px */
  --space-4: var(--size-200); /* 16px */
  --space-5: var(--size-250); /* 20px */
  --space-6: var(--size-300); /* 24px */
  --space-8: var(--size-400); /* 32px */
  --space-10: var(--size-500); /* 40px */
  --space-12: var(--size-600); /* 48px */
  --space-16: var(--size-800); /* 64px */
  --space-20: var(--size-1000); /* 80px */
  --space-24: var(--size-1200); /* 96px */
  --space-32: var(--size-1600); /* 128px */
  --space-48: var(--size-2400); /* 192px */

  /* The smallest box screen readers still read, for text that's hidden from
     view but not from them. */
  --visually-hidden-size: 1px;

  /* Page */
  --page-max-width: 72rem; /* 1152px */
  --page-gutter: var(--space-4); /* the least space beside content on narrow screens */
  --narrow-max-width: 48rem; /* 768px, for blocks that look sparse at full width */
  /* Between the big sections of a page: 96px on phones, growing with the
     screen to 192px. */
  --section-gap: clamp(var(--space-24), 14vw, var(--space-48));

  /* Grids */
  --card-min-width: 16rem; /* 256px, the narrowest a card gets before its grid drops a column */
  --panel-max-width: 28rem; /* 448px, for a panel that looks like a dialog */
  --split-min-width: 24rem; /* 384px, the narrowest each half of a two-column split gets before they stack */
}
}
@layer tokens {
:root {
  /* Font families */
  --font-family-base: "Geist", system-ui, sans-serif;
  --font-family-heading: "Geist", system-ui, sans-serif;
  /* The system's own monospace, which also covers IPA symbols. */
  --font-family-code: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  /* The word an RSVP reader shows. */
  --font-family-reading: "Atkinson Hyperlegible Next", "Geist", system-ui, sans-serif;

  /* Font sizes */
  --font-size-xs: var(--size-150); /* 12px */
  --font-size-sm: var(--size-175); /* 14px */
  --font-size-base: var(--size-200); /* 16px */
  --font-size-md: var(--size-250); /* 20px */
  --font-size-lg: var(--size-300); /* 24px */
  --font-size-xl: var(--size-400); /* 32px */
  --font-size-2xl: var(--size-500); /* 40px */
  --font-size-3xl: var(--size-600); /* 48px */
  --font-size-4xl: var(--size-800); /* 64px */
  /* The wordmark's height in the header, from the top of its R to the tail
     of its y. */
  --wordmark-height: var(--size-400); /* 32px */
  /* The RSVP word, before it shrinks to fit a long one. */
  --font-size-reading: var(--size-650); /* 52px */

  /* Font weights. Geist is a variable font, so any weight from 100 to 900 works;
     these are the ones the design uses. */
  --font-weight-regular: 400;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;

  /* Line heights */
  --font-family-base-line-height: 1.6;
  --font-family-heading-line-height: 1.2;

  /* Measure: the longest comfortable line of running text */
  --body-max-width: 75ch;
}
}

@layer base {
/* Opts the page into both schemes; the OS setting picks which one applies. */
:root {
  color-scheme: light dark;
}

/* A column of header, main and footer, with the footer kept at the bottom of
   short pages. */
body {
  display: flex;
  flex-direction: column;
  background-color: var(--color-surface-primary);
  color: var(--color-text-primary);
}

/* Centers each section's content while its background and borders stay full
   width. */
body > :is(header, main, footer) {
  padding-inline: max(var(--page-gutter), (100% - var(--page-max-width)) / 2);
}

main {
  flex: 1;
  padding-block: var(--space-10);
}

:focus-visible {
  outline: var(--focus-ring-width) solid var(--color-focus-ring);
  outline-offset: var(--focus-ring-offset);
}
}

@layer components {
.button {
  display: inline-block;
  padding: var(--space-2) var(--space-4);
  /* Transparent, so every variant is the same size whether or not it shows a
     border. */
  border: var(--border-width) solid transparent;
  border-radius: var(--radius-md);
  background-color: var(--color-primary);
  color: var(--color-on-primary);
  font-weight: var(--font-weight-semibold);
  text-decoration: none;
}

.button:hover {
  filter: brightness(1.05);
}

/* For the second choice beside a main button: outlined, in the text color. */
.button-secondary {
  border-color: var(--color-border);
  background-color: transparent;
  color: var(--color-text-primary);
}

.button-secondary:hover {
  filter: none;
  background-color: var(--color-surface-secondary);
}
}
@layer components {
/*
 * Icons are SVG files used as masks over the text color, so they follow
 * `color` like text does, with no SVG in the markup:
 *
 *   span class="icon icon-zap" aria-hidden="true" {}
 *
 * Each file is named once here, so upgrading Lucide is one edit.
 */
:root {
  --icon-check: url("/static/vendor/lucide-1.61.0/check.svg");
  --icon-chevron-down: url("/static/vendor/lucide-1.61.0/chevron-down.svg");
  --icon-eye: url("/static/vendor/lucide-1.61.0/eye.svg");
  --icon-gauge: url("/static/vendor/lucide-1.61.0/gauge.svg");
  --icon-pause: url("/static/vendor/lucide-1.61.0/pause.svg");
  --icon-play: url("/static/vendor/lucide-1.61.0/play.svg");
  --icon-rotate-ccw: url("/static/vendor/lucide-1.61.0/rotate-ccw.svg");
  --icon-target: url("/static/vendor/lucide-1.61.0/target.svg");
  --icon-zap: url("/static/vendor/lucide-1.61.0/zap.svg");
}

/* Medium by default; set --icon-size on the element for another size. */
.icon {
  display: inline-block;
  flex-shrink: 0;
  inline-size: var(--icon-size, var(--icon-size-md));
  block-size: var(--icon-size, var(--icon-size-md));
  background-color: currentColor;
  mask: var(--icon) center / contain no-repeat;
}

.icon-eye {
  --icon: var(--icon-eye);
}

.icon-gauge {
  --icon: var(--icon-gauge);
}

.icon-pause {
  --icon: var(--icon-pause);
}

.icon-play {
  --icon: var(--icon-play);
}

.icon-rotate-ccw {
  --icon: var(--icon-rotate-ccw);
}

.icon-target {
  --icon: var(--icon-target);
}

.icon-zap {
  --icon: var(--icon-zap);
}
}
@layer components {
/*
 * The extension's Pro reader, as a panel: the word on a line that marks its
 * fixed point, the count and time left, then play, speed and speed presets,
 * with progress along the bottom edge. Light and dark come from the tokens.
 */
.rsvp-demo {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  inline-size: 100%;
  max-inline-size: var(--panel-max-width);
  margin-inline: auto;
  padding: var(--space-5) var(--space-6) var(--space-6);
  /* Clips the progress bar to the rounded corners. */
  overflow: hidden;
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-xl);
  background-color: var(--color-surface-raised);
  box-shadow: var(--shadow-lg);
  font-size: var(--font-size-sm);
  color: var(--color-text-secondary);
}

.rsvp-demo-title {
  overflow: hidden;
  font-weight: var(--font-weight-medium);
  line-height: var(--font-family-heading-line-height);
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Where the word sits. A hairline above and below, fading in toward the
   pivot letter, marks the spot the eyes stay on. */
.rsvp-demo-stage {
  position: relative;
  display: flex;
  align-items: center;
  block-size: var(--reader-stage-height);
  padding-inline: var(--space-4);
}

.rsvp-demo-stage::before,
.rsvp-demo-stage::after {
  content: "";
  position: absolute;
  inset-inline-start: 50%;
  inline-size: var(--border-width);
  block-size: var(--reader-guide-length);
  translate: -50% 0;
  background: linear-gradient(to bottom, transparent, var(--color-text-accent));
}

.rsvp-demo-stage::before {
  inset-block-start: var(--space-2);
}

/* Turned over, so it fades in toward the word from below. */
.rsvp-demo-stage::after {
  inset-block-end: var(--space-2);
  rotate: 180deg;
}

/* Three columns, so the pivot letter stays in the middle whatever the word's
   length. rsvp-demo.js shrinks words too long to fit either side. */
.rsvp-demo-word {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: baseline;
  inline-size: 100%;
  font-family: var(--font-family-reading);
  font-size: var(--rsvp-demo-word-size, var(--font-size-reading));
  font-weight: var(--font-weight-medium);
  line-height: 1;
  white-space: nowrap;
  color: var(--color-text-primary);
}

.rsvp-demo-word > :first-child {
  text-align: end;
}

.rsvp-demo-word > :last-child {
  text-align: start;
}

.rsvp-demo-pivot {
  font-weight: var(--font-weight-bold);
  color: var(--color-text-accent);
}

.rsvp-demo-status {
  font-size: var(--font-size-xs);
  font-variant-numeric: tabular-nums;
  line-height: var(--font-family-heading-line-height);
  text-align: center;
}

/* Play beside the speed slider, under a line. */
.rsvp-demo-controls {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-block-start: var(--space-4);
  padding-block-start: var(--space-5);
  border-block-start: var(--border-width) solid var(--color-border);
}

.rsvp-demo-toggle {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  inline-size: var(--control-size-lg);
  block-size: var(--control-size-lg);
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background-color: var(--color-primary);
  color: var(--color-on-primary);
  cursor: pointer;
}

.rsvp-demo-toggle:hover {
  filter: brightness(1.05);
}

.rsvp-demo-speed {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--space-2);
  min-inline-size: 0;
}

.rsvp-demo-speed-label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  line-height: var(--font-family-heading-line-height);
}

.rsvp-demo-speed-value {
  font-variant-numeric: tabular-nums;
}

.rsvp-demo-speed-value > strong {
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-primary);
}

/* The extension's 100–900 slider. rsvp-demo.js keeps --fill at the value's
   place along it; Firefox draws its own fill with ::-moz-range-progress. */
.rsvp-demo-slider {
  --fill: 37.5%;

  inline-size: 100%;
  block-size: var(--space-5);
  margin: 0;
  appearance: none;
  background: transparent;
  cursor: pointer;
}

.rsvp-demo-slider:disabled {
  cursor: default;
}

.rsvp-demo-slider::-webkit-slider-runnable-track {
  block-size: var(--track-height-sm);
  border-radius: var(--radius-pill);
  background: linear-gradient(
    to right,
    var(--color-primary) var(--fill),
    var(--color-surface-muted) var(--fill)
  );
}

.rsvp-demo-slider::-webkit-slider-thumb {
  inline-size: var(--thumb-size);
  block-size: var(--thumb-size);
  margin-block-start: calc((var(--track-height-sm) - var(--thumb-size)) / 2);
  border: var(--border-width-thick) solid var(--color-primary);
  border-radius: var(--radius-pill);
  appearance: none;
  background-color: var(--color-control-thumb);
  box-shadow: var(--shadow-sm);
}

.rsvp-demo-slider::-moz-range-track {
  block-size: var(--track-height-sm);
  border-radius: var(--radius-pill);
  background-color: var(--color-surface-muted);
}

.rsvp-demo-slider::-moz-range-progress {
  block-size: var(--track-height-sm);
  border-radius: var(--radius-pill);
  background-color: var(--color-primary);
}

.rsvp-demo-slider::-moz-range-thumb {
  box-sizing: border-box;
  inline-size: var(--thumb-size);
  block-size: var(--thumb-size);
  border: var(--border-width-thick) solid var(--color-primary);
  border-radius: var(--radius-pill);
  background-color: var(--color-control-thumb);
  box-shadow: var(--shadow-sm);
}

/* Lined up under the slider, past the play button. */
.rsvp-demo-presets {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-block-start: var(--space-2);
  padding-inline-start: calc(var(--control-size-lg) + var(--space-4));
}

.rsvp-demo-preset {
  min-block-size: var(--control-size-sm);
  padding: 0 var(--space-3);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-pill);
  background-color: transparent;
  color: var(--color-text-secondary);
  font-size: var(--font-size-xs);
  font-variant-numeric: tabular-nums;
  font-weight: var(--font-weight-medium);
  cursor: pointer;
}

.rsvp-demo-preset:hover {
  color: var(--color-text-primary);
}

/* The current speed, filled in the text color. */
.rsvp-demo-preset[aria-pressed="true"] {
  border-color: var(--color-text-primary);
  background-color: var(--color-text-primary);
  color: var(--color-surface-raised);
}

.rsvp-demo-shortcuts {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--space-3);
  margin-block-start: var(--space-3);
  font-size: var(--font-size-xs);
  line-height: var(--font-family-heading-line-height);
}

.rsvp-demo-shortcuts > span {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.rsvp-demo-shortcuts kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: var(--space-5);
  block-size: var(--space-5);
  padding-inline: var(--space-2);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface-secondary);
  color: var(--color-text-primary);
  font-family: var(--font-family-code);
  font-size: var(--font-size-xs);
  line-height: 1;
}

/* A thin bar along the panel's bottom edge. */
.rsvp-demo-progress {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  inline-size: 100%;
  block-size: var(--track-height-sm);
  border: 0;
  border-radius: 0;
  appearance: none;
  background-color: var(--color-surface-muted);
}

.rsvp-demo-progress::-webkit-progress-bar {
  background-color: var(--color-surface-muted);
}

.rsvp-demo-progress::-webkit-progress-value {
  background-color: var(--color-primary);
}

.rsvp-demo-progress::-moz-progress-bar {
  background-color: var(--color-primary);
}
}
@layer components {
.site-footer {
  padding-block: var(--space-8);
  border-block-start: var(--border-width) solid var(--color-border);
  font-size: var(--font-size-sm);
}
}
@layer components {
.site-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4) var(--space-8);
  padding-block: var(--space-4);
  border-block-end: var(--border-width) solid var(--color-border);
}

/* The wordmark, with how to say it beside it. */
.site-brand {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
}

.wordmark {
  display: block;
  color: inherit;
  text-decoration: none;
}

/* static/images/wordmark.svg as a mask: the R in the brand color, the rest of
   the word in the text color. The R ends 99 units into the drawing's 408, and
   the word's baseline is 74.72 units down its 99. The name inside stays for
   copying, hidden behind the drawing. */
.wordmark-mark {
  display: block;
  block-size: var(--wordmark-height);
  aspect-ratio: 408 / 99;
  overflow: hidden;
  background: linear-gradient(
    to right,
    var(--color-text-accent) calc(99 / 408 * 100%),
    var(--color-text-primary) 0
  );
  color: transparent;
  mask: url("/static/images/wordmark.svg") left top / contain no-repeat;
}

/* IPA, quiet beside the name like a dictionary entry, sitting on the word's
   baseline. */
.site-pronunciation {
  margin-block-start: calc(var(--wordmark-height) * 74.72 / 99 - 1cap);
  font-family: var(--font-family-code);
  font-size: var(--font-size-sm);
  color: var(--color-text-secondary);
  text-box: trim-both cap alphabetic;
}

/* Pushes the navigation and the install button to the end of the row. */
.site-header > nav {
  margin-inline-start: auto;
}

/* Phones only have room for the wordmark and the navigation. The page's own
   install button is right below anyway. Custom properties can't be used in
   media queries, so the breakpoint is written out: 30rem is 480px. */
@media (width < 30rem) {
  .site-header > .button,
  .site-pronunciation {
    display: none;
  }
}
}
@layer components {
/* A row of links, used by both the header and the footer. */
.site-nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-6);

  a {
    color: var(--color-text-secondary);
    text-decoration: none;
  }

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

  /* The section you're in: full-strength text, underlined in the brand
     color. Only the header's links set aria-current. */
  a[aria-current] {
    color: var(--color-text-primary);
    text-decoration-line: underline;
    text-decoration-thickness: var(--border-width-thick);
    text-decoration-color: var(--color-text-accent);
    text-underline-offset: var(--space-2);
  }
}
}
@layer components {
/* Off screen until a keyboard user tabs to it, then shown at the top left. */
.skip-link {
  position: absolute;
  inset-block-start: var(--space-2);
  inset-inline-start: var(--space-2);
  padding: var(--space-2) var(--space-4);
  background-color: var(--color-surface-primary);
  color: var(--color-text-primary);
  translate: 0 -200%;
}

.skip-link:focus-visible {
  translate: 0;
}
}
@layer components {
/* A post's tags, as a row of small rounded links. */
.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-block-start: var(--space-3);

  a {
    display: inline-block;
    padding-inline: var(--space-3);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-pill);
    color: var(--color-text-secondary);
    font-size: var(--font-size-sm);
    line-height: var(--font-family-heading-line-height);
    text-decoration: none;
  }

  a:hover {
    border-color: var(--color-text-secondary);
    color: var(--color-text-primary);
  }
}
}
@layer components {
/* Out of sight, but still read out by screen readers. */
.visually-hidden {
  position: absolute;
  inline-size: var(--visually-hidden-size);
  block-size: var(--visually-hidden-size);
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
}

@layer pages {
/* The home page, one block per section, top to bottom. */

/* One rhythm down the page, like a column spaced around: a full gap between
   sections, and half of one above the first and below the last. */
main:has(> .hero) {
  padding-block: calc(var(--section-gap) / 2);
}

/* Sections after the hero are centered, with room between them. */
:is(.features, .pricing, .faq, .call-to-action) {
  text-align: center;
}

:is(.features, .pricing, .faq, .call-to-action) > p {
  margin-inline: auto;
  color: var(--color-text-secondary);
}

:is(.features, .pricing, .faq, .call-to-action) {
  margin-block-start: var(--section-gap);
}

/* Scales with the screen, from 32px on phones up to 40px, so long headings
   like the pricing one fit in two lines. */
:is(.features, .pricing, .faq, .call-to-action) > h2 {
  font-size: clamp(var(--font-size-xl), 8vw, var(--font-size-2xl));
}

:is(.features, .pricing, .faq, .call-to-action) > p {
  margin-block-start: var(--space-4);
}

/* Hero */

/* The copy on the left and the demo on the right, stacking on narrow
   screens. */
.hero {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--split-min-width)), 1fr));
  align-items: center;
  gap: var(--space-12);
}

/* Scales with the screen, from 40px on phones up to 64px. */
.hero-copy > h1 {
  margin-block-start: 0;
  font-size: clamp(var(--font-size-2xl), 5vw, var(--font-size-4xl));
  font-weight: var(--font-weight-bold);
}

/* "RSVP", on its own line. */
.hero-accent {
  display: block;
  color: var(--color-text-accent);
}

.hero-copy > p {
  margin-block-start: var(--space-6);
  font-size: var(--font-size-md);
  color: var(--color-text-secondary);
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-block-start: var(--space-10);
}

/* The call to action's buttons, centered under its heading. */
.call-to-action-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3);
  margin-block-start: var(--space-10);
}

/* Features */

/* As many columns as fit: four on wide screens, down to one on phones. */
.feature-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--card-min-width), 1fr));
  gap: var(--space-8);
  margin-block-start: var(--space-12);
  text-align: start;
}

/* The icon on a faint square of the brand color. */
.feature-icon {
  display: inline-flex;
  padding: var(--space-2);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface-accent);
  color: var(--color-text-accent);
}

.feature > h3 {
  margin-block-start: var(--space-4);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-semibold);
}

.feature > p {
  margin-block-start: var(--space-2);
  font-size: var(--font-size-sm);
  color: var(--color-text-secondary);
}

/* Pricing */

/* Side by side, stacking on phones. Each plan stretches to the row's height.
   Capped and centered, since two cards across the full page are mostly empty. */
.plan-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--card-min-width), 1fr));
  gap: var(--space-8);
  max-width: var(--narrow-max-width);
  margin-block-start: var(--space-12);
  margin-inline: auto;
  text-align: start;
}

/* A column, so the action at the end can sit at the bottom of the card. */
.plan {
  display: flex;
  flex-direction: column;
  padding: var(--space-8);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-lg);
}

.plan > h3 {
  margin-block-start: 0;
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-semibold);
}

.plan-price {
  margin-block-start: var(--space-4);
  font-size: var(--font-size-3xl);
  font-weight: var(--font-weight-bold);
  line-height: var(--font-family-heading-line-height);
}

.plan-period {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-regular);
  color: var(--color-text-secondary);
}

.plan-features {
  display: grid;
  gap: var(--space-3);
  margin-block: var(--space-8);
  font-size: var(--font-size-sm);
}

/* A checkmark before each feature. */
.plan-features > li {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.plan-features > li::before {
  content: "";
  flex-shrink: 0;
  inline-size: var(--icon-size-sm);
  block-size: var(--icon-size-sm);
  background-color: var(--color-text-accent);
  mask: var(--icon-check) center / contain no-repeat;
}

/* The button or note, pushed to the bottom so both plans line up. */
.plan > :last-child {
  margin-block-start: auto;
  text-align: center;
}

.plan-note {
  padding-block: var(--space-2);
  color: var(--color-text-secondary);
}

/* FAQ */

/* A narrow column of questions, each with a line below it. */
.faq-item {
  max-width: var(--narrow-max-width);
  margin-inline: auto;
  border-block-end: var(--border-width) solid var(--color-border);
  text-align: start;
}

.faq > h2 + p + .faq-item {
  margin-block-start: var(--space-12);
}

/* The question, with a chevron at the end in place of the browser's marker,
   which `display: flex` removes. */
.faq-item > summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4);
  padding-block: var(--space-4);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
}

/* Safari still draws its marker without this. */
.faq-item > summary::-webkit-details-marker {
  display: none;
}

.faq-item > summary::after {
  content: "";
  flex-shrink: 0;
  inline-size: var(--icon-size-sm);
  block-size: var(--icon-size-sm);
  background-color: currentColor;
  mask: var(--icon-chevron-down) center / contain no-repeat;
}

/* Points up while the answer shows. */
.faq-item[open] > summary::after {
  rotate: 180deg;
}

.faq-item > p {
  padding-block-end: var(--space-4);
  color: var(--color-text-secondary);
}

/* Call to action */

/* A panel, so the page ends on something that stands out. */
.call-to-action {
  padding: var(--space-16) var(--space-6);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface-secondary);
}

.call-to-action > h2 {
  margin-block-start: 0;
}
}
