/* Daily AI Sprints landing page.
   Tokens come from DESIGN.md (Solarized Native). Do not introduce a colour here
   that is not in that file, and do not give any colour its only definition
   inside a media query. */

/* ---------- Light palette: the base definition ---------- */
/* ---------- Fonts ----------
   Self-hosted from this origin, so a page that collects email addresses makes
   no third-party request. One variable WOFF2 per family, latin subset, weights
   200 to 800, SIL Open Font License 1.1; the licence text sits beside the files
   in assets/fonts/. swap: the fallback stack is legible on its own, so text
   shows at once and re-renders when the file lands. */
@font-face {
  font-family: "Atkinson Hyperlegible Next";
  src: url("../assets/fonts/atkinson-hyperlegible-next-latin.woff2") format("woff2");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
  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;
}

@font-face {
  font-family: "Atkinson Hyperlegible Mono";
  src: url("../assets/fonts/atkinson-hyperlegible-mono-latin.woff2") format("woff2");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
  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;
}

:root {
  color-scheme: light;

  --canvas: #fdf6e3;
  --surface: #eee8d5;
  --card: #fdf6e3;
  --text: #073642;
  --muted: #4e6168;
  --border-ui: #657b83;
  --divider: #93a1a1;
  --link: #1a649e;
  --link-hover: #14507f;
  --link-visited: #6d3c9e;
  --cta: #cb4b16;
  --cta-hover: #b7420f;
  --on-cta: #ffffff;
  --accent-text: #9a370c;
  --focus: #1a649e;
  --error: #c0201f;
  --success: #4f6b00;

  /* Brand mark, "outline" treatment: the face always matches the page, so the
     frame and hands are the only marks and the logo reads the same weight in
     both themes. The lockup is a closed two-colour system: --logo-line carries
     this block's --link, the blue of "AI Sprints", and --logo-accent carries
     --accent-text, the orange of "Daily". The hour hand that fixes the clock at
     8:00 is the only accented stroke. Nothing in the mark is body-text navy,
     because nothing in the wordmark is either. */
  --logo-face: #fdf6e3;
  --logo-line: #1a649e;
  --logo-accent: #9a370c;

  --font-body: "Atkinson Hyperlegible Next", "Atkinson Hyperlegible", system-ui,
    -apple-system, "Segoe UI", sans-serif;
  --font-eyebrow: "Atkinson Hyperlegible Mono", ui-monospace, SFMono-Regular,
    Consolas, monospace;

  --space-xs: 0.25rem;
  --space-sm: 0.5rem;
  --space-md: 1rem;
  --space-lg: 1.5rem;
  --space-xl: 2rem;
  --space-xxl: 3rem;
  --space-section: 4rem;
  --space-hero: 4rem;

  --radius: 6px;
  --container-max: 1200px;
  --container-narrow: 800px;
  --reading-width: 68ch;
  --target-min: 44px;
}

/* System preference resolves to dark, unless the visitor explicitly chose light. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --canvas: #002b36;
    --surface: #073642;
    --card: #0a3a47;
    --text: #eee8d5;
    --muted: #93a1a1;
    --border-ui: #839496;
    --divider: #586e75;
    --link: #6fb6ee;
    --link-hover: #9ccdf5;
    --link-visited: #c7a6e8;
    --cta: #f08a4b;
    --cta-hover: #f59b63;
    --on-cta: #002b36;
    --accent-text: #f59b63;
    --focus: #b58900;
    --error: #ff9c93;
    --success: #7dc77a;

    --logo-face: #002b36;
    --logo-line: #6fb6ee;
    --logo-accent: #f59b63;
  }
}

/* Explicit dark choice wins regardless of the OS setting. */
:root[data-theme="dark"] {
  color-scheme: dark;

  --canvas: #002b36;
  --surface: #073642;
  --card: #0a3a47;
  --text: #eee8d5;
  --muted: #93a1a1;
  --border-ui: #839496;
  --divider: #586e75;
  --link: #6fb6ee;
  --link-hover: #9ccdf5;
  --link-visited: #c7a6e8;
  --cta: #f08a4b;
  --cta-hover: #f59b63;
  --on-cta: #002b36;
  --accent-text: #f59b63;
  --focus: #b58900;
  --error: #ff9c93;
  --success: #7dc77a;

  --logo-face: #002b36;
  --logo-line: #6fb6ee;
  --logo-accent: #f59b63;
}

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

body {
  margin: 0;
  background: var(--canvas);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 1.125rem;
  line-height: 1.55;
}

h1,
h2,
h3 {
  margin: 0;
  line-height: 1.2;
  text-wrap: balance;
}

h1 {
  font-size: 3.5rem;
}
h2 {
  font-size: 2rem;
}
h3 {
  font-size: 1.5rem;
  line-height: 1.25;
}

p {
  margin: 0;
  max-width: var(--reading-width);
}

/* Body links keep their underline in every state, including hover. */
a {
  color: var(--link);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
}

a:hover {
  color: var(--link-hover);
  text-decoration-thickness: 2px;
}

a:visited {
  color: var(--link-visited);
}

:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}

/* ---------- Layout ---------- */
.container {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--space-md);
}

.band {
  padding-block: var(--space-section);
}

.band--tinted {
  background: var(--surface);
}

/* ---------- Visually hidden ----------
   One definition of the clip technique, for anything the eye does not need
   but assistive technology does. Not display:none and not visibility:hidden:
   either would take the element out of the accessibility tree along with the
   pixels, and would drop a focusable control out of the tab order.

   The theme radios are here for that second reason. They have to stay
   focusable, because their labels are the whole visible control.

   The word inside each theme label is here too. It names the radio, so it
   stays in the accessibility tree at every width, while the sun and moon
   carry the meaning to the eye. */
.visually-hidden,
.theme-choice input,
.theme-choice__word {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- Skip link ---------- */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 10;
  background: var(--card);
  color: var(--link);
  border: 1px solid var(--border-ui);
  border-radius: var(--radius);
  padding: var(--space-sm) var(--space-md);
  min-height: var(--target-min);
  display: inline-flex;
  align-items: center;
  font-weight: 600;
}

.skip-link:focus {
  left: var(--space-md);
  top: var(--space-md);
}

/* ---------- Header ---------- */
/* The header is a masthead, the way a daily paper opens: the lockup centred
   on its own row, then a ruled row holding the navigation and the theme
   control. Joe chose it on September 8, 2026 from ten drawn directions. The
   rule row carries a hairline above and below, so the header needs no
   bottom border of its own. Since September 9, 2026 the rule row sits on
   surface, Joe's choice from four rendered treatments, and the hero below it
   sits on canvas so the row does not run into it. */
.site-header {
  background: var(--canvas);
}

.site-header__mast {
  display: flex;
  justify-content: center;
  padding-block: var(--space-lg) var(--space-md);
}

.site-header__rule {
  background: var(--surface);
  border-top: 1px solid var(--divider);
  border-bottom: 1px solid var(--divider);
}

/* Three columns: the links centred in the middle one, the theme control at
   the end of the third, the first left empty so the links sit on the page's
   true centre rather than the centre of what the control leaves. */
.site-header__row {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  min-height: 52px;
}

/* The site navigation: a nav landmark holding four links, three into the
   landing page and one to the pricing page, set in the eyebrow face as spaced
   capitals so the row reads as a paper's section list. The list wraps rather
   than hiding behind a button: four short labels never need a disclosure
   menu. */
.site-nav {
  grid-column: 2;
}

.site-nav__list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0 var(--space-xl);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* The one set of links in the system without a resting underline. The ruled
   row, the landmark, and the capitals say "navigation" on their own, and a row
   of underlined capitals reads as a row of rules. Hover brings the underline
   in with link-hover, so the affordance is a hover away. Each link carries
   the 44px target. Letter-spacing is in em so it scales with the size;
   DESIGN.md records the resulting pixel value. */
.site-nav-link {
  display: inline-flex;
  align-items: center;
  min-height: var(--target-min);
  padding: 0 var(--space-xs);
  color: var(--text);
  font-family: var(--font-eyebrow);
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
}

/* No visited state on navigation. The same four links sit on every page, so
   after one trip through the site every one of them would be visited purple
   for good. A visited cue only carries meaning on content links a reader may
   or may not have followed. The footer's policy links get the same treatment. */
.site-nav-link:visited {
  color: var(--text);
}

.site-footer__links a:visited {
  color: var(--link);
}

.site-nav-link:hover {
  color: var(--link-hover);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.6em;
}

/* The link to the page being viewed: the wordmark's warm colour plus a 2px
   underline, so the cue does not rest on colour and survives forced-colors
   mode, where the underline is all that is left. It stays a link. Declared
   after the hover rule at equal specificity, so hover does not repaint it. */
.site-nav-link[aria-current="page"],
.site-nav-link[aria-current="page"]:visited,
.site-nav-link[aria-current="page"]:hover {
  color: var(--accent-text);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.6em;
}

/* The whole lockup is one link to home, so the mark and the words cannot be
   tabbed to separately. Centred in the masthead row; the text block keeps its
   own left edge so the tagline lines up under "Daily". The mark hangs from
   the top of the text block rather than centring on it, so its frame can be
   pinned to the type's ink (see .dais-mark); centring put its bottom 3.4px
   short of the dateline baseline. */
.brand {
  display: flex;
  align-items: flex-start;
  gap: var(--space-md);
  min-width: 0;
  color: inherit;
  text-decoration: none;
}

.brand:hover,
.brand:visited {
  color: inherit;
  text-decoration: none;
}

.brand-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  min-width: 0;
}

/* The wordmark at display size, the one type size between h2 and h1. A
   masthead name is the largest type on the page after the h1; at 1.5rem it
   read as a form label beside the navigation. */
.brand-name {
  font-size: 2.75rem;
  font-weight: 700;
  line-height: 1.1;
  white-space: nowrap;
}

/* Two-tone wordmark, the same split Rapid AI Sprints uses: warm on the first
   word, cool on the rest, and neither is body text. Borrowing the link colour
   for "AI Sprints" is safe here only because the entire lockup is itself a
   link to home, so it cannot mislead anyone about what is clickable.
   Light 6.65:1 and 5.79:1, dark 6.97:1 and 6.86:1. */
.brand-name-accent {
  color: var(--accent-text);
}

.brand-name-cool {
  color: var(--link);
}

/* The tagline as a paper's dateline: the eyebrow face in spaced capitals,
   tracked wider than the eyebrow because it stands alone under the name. */
.brand-tagline {
  font-family: var(--font-eyebrow);
  font-size: 0.8125rem;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}

/* The mark carries no fill of its own. Three tokens colour it, which is the
   whole reason one file serves both themes.

   Sized to the lockup the way the headlines mark is sized to its question:
   the frame's outer edge runs from the cap line of "Daily" to the dateline's
   baseline, so the mark and the two lines of type share both edges. At the
   display size (2.75rem, line-height 1.1) over the 0.8125rem dateline
   (line-height 1.4) with the 0.25rem gap between them, that span is 56.8px,
   and the frame's outer edge is 8/512 of the box in from each end (the rect
   at 24 minus half its 32 stroke). That gives a 3.663rem box pushed down
   0.481rem from the top of the text block. The two narrower steps below
   re-derive both numbers for their own sizes. Change the display, tagline
   or gap values and re-measure; the numbers were checked against the
   rendered page at 1280, 700 and 400px on September 10, 2026. */
.dais-mark {
  width: 3.663rem;
  height: 3.663rem;
  margin-top: 0.481rem;
  flex: none;
}

.dais-mark__face {
  fill: var(--logo-face);
  stroke: var(--logo-line);
}

.dais-mark__hand {
  stroke: var(--logo-line);
  stroke-linecap: round;
}

/* The hour hand is the only accented stroke. It is what says 8:00 rather than
   leaving the face a generic clock, so it is the part worth colouring.
   Declared after .dais-mark__hand: same specificity, so source order wins. */
.dais-mark__hand--hour {
  stroke: var(--logo-accent);
}

/* The "now" marker, added by script (see index.html): a dot on the inside of
   the frame at the visitor's local hour. Muted because it is decoration and
   carries nothing a visitor needs, so it is exempt from contrast. Between
   08:00 and 08:45, while the sprint is live, it takes the accent so the mark
   reads "8, and it is 8 now". The two states are the only ones there are. */
.dais-mark__now {
  fill: var(--muted);
}

.dais-mark__now--live {
  fill: var(--logo-accent);
}

/* Two icon chips side by side at the end of the rule row: the live one filled
   in link, the other outlined in border-ui, both at the 6px radius the rest of
   the page uses. Tailwind, HeroUI and fumadocs all draw this control as a
   pill, and DESIGN.md rules pill shapes out: the squarer geometry is part of
   what makes the page read as Solarized.

   Until September 8, 2026 the two options sat on a surface track with their
   words showing, and that made the control the heaviest object in the header,
   ahead of the navigation it sat beside. Both options are still on screen and
   the live one is still filled in, which is the whole point of the shape.

   position: relative contains the absolutely positioned legend and radios.
   The surface background matches the rule row the control sits in and is
   declared so the design gate can read it. */
.theme-choice {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  margin: 0;
  padding: 0;
  border: 0;
  background: var(--surface);
  grid-column: 3;
  justify-self: end;
}

/* The radios themselves are clipped by the visually-hidden rule above.
   The label is the whole target, so it carries the 44px minimum rather than
   the 1px input it names. The outline is border-ui, not divider: an
   unselected option is still a control, and SC 1.4.11 wants its edge at 3:1. */
.theme-choice label {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--target-min);
  min-height: var(--target-min);
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--border-ui);
  border-radius: var(--radius);
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.4;
  cursor: pointer;
}

.theme-choice svg {
  width: 20px;
  height: 20px;
  flex: none;
  stroke-width: 1.9;
}

/* The live option takes the link blue as a solid fill, with its icon on
   canvas. SC 1.4.11 asks 3:1 of a control carrying state; DESIGN.md holds the
   measured ratios against the header.

   The fill is a hue on purpose. Marking this particular control with a tone
   backfires, because tone is the subject: filling the live option with text
   makes a dark block mark "Light" in the light theme and a bright block mark
   "Dark" in the dark one, so the colour contradicts the option it sits on.
   Blue belongs to neither theme, so it can only mean "this one is on". It is
   blue rather than the warm accent because the header must not carry the
   loudest colour on the page; that belongs to the hero's call to action.

   The tonal chip that Tailwind, HeroUI and fumadocs use is a canvas-on-surface
   step, 1.14:1 here, and a tonal step is not a boundary. Four cues stack in
   this version, fill, outline, position and stroke weight, so nothing rests
   on colour alone and it survives a blurred glance. */
.theme-choice input:checked + label {
  background: var(--link);
  border-color: var(--link);
  color: var(--canvas);
}

.theme-choice input:checked + label svg {
  stroke-width: 2.4;
}

/* The input is clipped to a pixel, so the outline has to be drawn on the
   label the visitor is actually looking at. */
.theme-choice input:focus-visible + label {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}

/* ---------- Hero ---------- */
/* Canvas since September 9, 2026: the header's rule row took surface, and a
   surface hero would run into it. Every band below flipped with it. */
.hero {
  background: var(--canvas);
  padding-block: var(--space-hero);
}

.hero-eyebrow {
  font-family: var(--font-eyebrow);
  font-size: 0.875rem;
  line-height: 1.4;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 var(--space-sm);
}

.hero h1 {
  line-height: 1.1;
}

/* A class, not ".hero p": the eyebrow is also a paragraph in the hero, and
   so is every step in the rail. */
.hero-lede {
  font-size: 1.1875rem;
  line-height: 1.7;
  color: var(--muted);
  margin-block: var(--space-sm) var(--space-lg);
}

.hero-layout {
  display: grid;
  gap: var(--space-xl);
  align-items: start;
}

/* Top-aligned, not centred: the copy block is shorter than the rail, and
   centring it left the headline floating in the middle of the band with the
   eyebrow's cap line meeting nothing. Now it meets the rail's top edge. */
@media (min-width: 1000px) {
  .hero-layout {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: var(--space-hero);
    align-items: start;
  }
}

/* The rail explains the core session rather than introducing another offer.
   border-ui on the edge, like every card. Since the hero moved to canvas on
   September 9, 2026 the card fill matches the band in light and steps 1.22:1
   in dark, so the edge is what a reader with low vision uses to see what
   belongs together. The input is told apart from cards by weight, not by
   tone. */
.session-rail {
  background: var(--card);
  border: 1px solid var(--border-ui);
  border-radius: var(--radius);
  padding: var(--space-lg);
}

.session-rail__title {
  font-family: var(--font-eyebrow);
  font-size: 0.875rem;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 var(--space-sm);
}

.session-rail__list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.session-rail__list li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-md);
  padding-block: calc(var(--space-lg) / 2);
  border-top: 1px solid var(--divider);
}

.session-rail__list li:last-child {
  padding-bottom: 0;
}

.session-rail__list h3 {
  font-size: 1.125rem;
  margin-bottom: var(--space-xs);
}

.session-rail__list p {
  color: var(--muted);
  font-size: 1rem;
  line-height: 1.5;
  margin: 0;
}

.session-rail__num {
  font-family: var(--font-eyebrow);
  font-size: 0.875rem;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0.06em;
  color: var(--accent-text);
  font-variant-numeric: tabular-nums;
}

/* ---------- Actions ---------- */
.action,
.action:visited {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--target-min);
  padding: var(--space-sm) var(--space-lg);
  background: var(--cta);
  color: var(--on-cta);
  border: 0;
  border-radius: var(--radius);
  font-family: inherit;
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.4;
  text-decoration: none;
  cursor: pointer;
}

.action:hover {
  background: var(--cta-hover);
  color: var(--on-cta);
  text-decoration: none;
}

/* The hero's action is the one the page exists for, so it gets a larger label
   and a taller target than the card actions. */
.hero .action {
  min-height: 52px;
  padding: var(--space-md) var(--space-xl);
  font-size: 1.0625rem;
}

/* The outlined secondary action that the two organization cards carried was
   retired September 4, 2026 at Joe's direction: every offer action is the
   solid orange now. */

/* ---------- Membership ---------- */
.pricing-intro {
  margin-bottom: var(--space-xl);
}

.pricing-intro__rule {
  display: block;
  width: 3rem;
  height: 3px;
  margin-bottom: var(--space-md);
  background: var(--accent-text);
}

.pricing-intro h1 {
  font-size: 3rem;
  line-height: 1.1;
  margin-bottom: var(--space-md);
  overflow-wrap: anywhere;
}

.pricing-intro__description {
  max-width: 55ch;
  color: var(--muted);
  font-size: 1.125rem;
  line-height: 1.55;
}

.membership-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-lg);
  margin-block: var(--space-lg) var(--space-md);
  padding: 0;
  list-style: none;
}

.billing-period {
  border: 0;
  padding: 0;
  margin: 0 0 var(--space-xl);
}

.billing-period legend {
  margin-bottom: var(--space-sm);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.5;
}

.billing-period__choices {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
}

.billing-period label {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  min-height: var(--target-min);
  padding: var(--space-sm) var(--space-md);
  border: 2px solid var(--border-ui);
  border-radius: var(--radius);
  font-size: 1rem;
  line-height: 1.5;
  cursor: pointer;
}

.billing-period label:has(input:checked) {
  background: var(--surface);
}

.billing-period input {
  margin: 0;
  width: 1rem;
  height: 1rem;
  flex-shrink: 0;
  accent-color: var(--link);
}

.billing-period__saving {
  margin-left: var(--space-sm);
  font-weight: 600;
}

[data-billing-value] {
  display: none;
}

main:has(.billing-period input[value="month"]:checked) [data-billing-value="month"],
main:has(.billing-period input[value="year"]:checked) [data-billing-value="year"] {
  display: block;
}

main:has(.billing-period input[value="month"]:checked) a.action[data-billing-value="month"],
main:has(.billing-period input[value="year"]:checked) a.action[data-billing-value="year"] {
  display: inline-flex;
}

main:has(.billing-period input:checked) .billing-period__prompt {
  display: none;
}

.membership-card .price-equivalent {
  font-size: 1rem;
  line-height: 1.5;
  margin-block: calc(-1 * var(--space-sm)) var(--space-lg);
}

.pricing-terms {
  margin-top: var(--space-lg);
}

.pricing-terms .terms {
  margin: 0;
}

.checkout-form > .action {
  margin-top: var(--space-lg);
}

/* Each card is a flex column so actions align within each grid row even when
   the offer descriptions have different lengths. */
.membership-card {
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow-wrap: anywhere;
  background: var(--card);
  border: 1px solid var(--border-ui);
  border-radius: var(--radius);
  padding: var(--space-lg);
}

.membership-card p {
  color: var(--muted);
  margin-block: var(--space-sm);
}

/* Pricing type follows the larger hierarchy approved from the mockup. */
.membership-card__name {
  font-size: 1.75rem;
  line-height: 1.25;
}

.membership-card__kicker {
  font-family: var(--font-eyebrow);
  font-size: 0.875rem;
  line-height: 1.4;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 0 0 var(--space-xs);
}

/* Scoped to the card on purpose. A bare .price loses to the .membership-card p
   rule above, which is one class plus an element and therefore more specific,
   so the price rendered in muted grey rather than accent for as long as both
   rules have existed. The design-system gate caught it; no human review did. */
.membership-card .price {
  color: var(--accent-text);
  font-size: 2.75rem;
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  margin-block: var(--space-sm) var(--space-lg);
}

.membership-card .price--custom {
  font-size: 2rem;
}

.price__period {
  display: block;
  margin-top: var(--space-sm);
  color: var(--muted);
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.5;
}

.membership-card .action {
  margin-top: auto;
  align-self: flex-start;
  max-width: 100%;
}

.terms {
  color: var(--muted);
  font-size: 0.9375rem;
}

/* What the money actually buys. Approved 2026-08-16, and it has to sit above
   the checkout link rather than below it. */
.access-terms {
  color: var(--muted);
  font-size: 0.9375rem;
  margin-block: 0 var(--space-lg);
}

/* ---------- Questions ---------- */
.faq-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-lg) var(--space-xxl);
  margin-top: var(--space-lg);
}

.faq-grid > div {
  border-top: 1px solid var(--divider);
  padding-top: var(--space-md);
}

.faq-grid h3 {
  font-size: 1.125rem;
  margin-bottom: var(--space-xs);
}

.faq-grid p {
  color: var(--muted);
  font-size: 1rem;
  line-height: 1.5;
}

/* ---------- Team ---------- */
.section-intro {
  color: var(--muted);
  margin-block: var(--space-sm) var(--space-xl);
}

.team-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
  gap: var(--space-lg);
  padding: 0;
  list-style: none;
}

/* card on the team band's surface. Until September 9, 2026 the band was
   canvas and the cards surface; the ground flip swapped both. */
.bio-card {
  display: flex;
  flex-direction: column;
  background: var(--card);
  border: 1px solid var(--border-ui);
  border-radius: var(--radius);
  padding: var(--space-lg);
}

/* Photo beside name and credential, all left-aligned, so the card reads as one
   layout top to bottom. */
.bio-card__header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-md);
  margin-bottom: var(--space-lg);
}

/* Below about 14rem of remaining width the text drops under the photo instead
   of wrapping into a six-line column beside it. */
.bio-card__header > div {
  flex: 1 1 14rem;
  min-width: 0;
}

.bio-photo {
  width: 96px;
  height: 96px;
  flex: none;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--divider);
}

.bio-card h3 {
  margin: 0;
}

/* Muted, not accent: the one warm colour on this page belongs to prices and
   the wordmark, and a job title is not a call to action. */
.bio-role {
  color: var(--muted);
  font-size: 0.9375rem;
  line-height: 1.5;
  margin-block: var(--space-xs) 0;
  max-width: none;
}

/* A left rule, not a background tint: the step from card to surface is about
   1.15:1 and would not read as a boundary on its own. */
.bio-quote {
  margin: 0 0 var(--space-lg);
  padding-left: var(--space-md);
  border-left: 3px solid var(--divider);
  font-style: italic;
}

.bio-quote p {
  color: var(--text);
}

/* A standalone link, not one inside a sentence, so it carries the full 44px
   target the system promises rather than the inline-link exemption. */
.bio-link {
  display: inline-flex;
  align-items: center;
  min-height: var(--target-min);
  margin-top: auto;
  align-self: flex-start;
  font-weight: 600;
}

/* ---------- Newsletter ----------
   Lives in the footer. A small opt-in beside the legal lines, the way most
   sites keep one, rather than a band of its own competing with the offers. */
.newsletter-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  max-width: 30rem;
}

.newsletter-form__title {
  font-size: 1.125rem;
  margin: 0 0 var(--space-xs);
}

.newsletter-form label {
  font-size: 0.9375rem;
  font-weight: 600;
}

.field-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
}

input[type="email"] {
  flex: 1 1 16rem;
  min-height: var(--target-min);
  padding: var(--space-sm);
  font-family: inherit;
  font-size: 1.125rem;
  color: var(--text);
  background: var(--card);
  /* 2px, where cards carry 1px: the one input on the page is told apart from
     the cards around it by weight, so both can share the border-ui tone. */
  border: 2px solid var(--border-ui);
  border-radius: var(--radius);
}

input[type="email"][aria-invalid="true"] {
  border-width: 2px;
  border-color: var(--error);
}

.field-hint {
  color: var(--muted);
  font-size: 0.9375rem;
}

.field-error {
  color: var(--error);
  font-size: 0.9375rem;
  font-weight: 600;
}

.field-error:empty {
  display: none;
}

.form-status {
  color: var(--success);
  font-weight: 600;
}

.form-status:empty {
  display: none;
}

.consent {
  color: var(--muted);
  font-size: 0.9375rem;
}

/* ---------- Contact request form ----------
   On the enterprise contact page, under the offer card, since dais-2gw. The same
   controls as the AI Briefings input, stacked in one column with a textarea.
   The global input[type="email"] rule above carries a 16rem flex-basis meant
   for the footer's field-row; inside this column that basis would become a
   16rem height, so every control here resets it. */
.contact-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  max-width: 36rem;
  margin-top: var(--space-xl);
}

/* An h2 drawn at the card-name size, the way /pricing/ draws its card names. */
.contact-form__title {
  font-size: 1.5rem;
  line-height: 1.25;
}

.contact-form .field {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.contact-form label {
  font-size: 0.9375rem;
  font-weight: 600;
}

.contact-form input[type="text"],
.contact-form input[type="email"],
.contact-form textarea {
  flex: none;
  width: 100%;
  min-height: var(--target-min);
  padding: var(--space-sm);
  font-family: inherit;
  font-size: 1.125rem;
  /* Form controls do not inherit line-height. Set body's 1.55 here so these
     controls match the body style DESIGN.md names for them, instead of
     joining the text-input drift recorded under dais-wio. */
  line-height: 1.55;
  color: var(--text);
  background: var(--card);
  border: 2px solid var(--border-ui);
  border-radius: var(--radius);
}

.contact-form textarea {
  min-height: 8rem;
  resize: vertical;
}

.contact-form input[aria-invalid="true"],
.contact-form textarea[aria-invalid="true"] {
  border-color: var(--error);
}

.contact-form .action {
  align-self: flex-start;
}

.checkout-form {
  margin-top: var(--space-lg);
}

/* ---------- Footer ----------
   Surface, so the bands keep alternating all the way down: hero tinted,
   the four live-hour bands canvas first, team canvas, questions canvas
   behind a rule, footer tinted. Two adjacent bands of the same tone read as
   one section, which is why the questions band carries a rule now that the
   membership band has moved to /pricing/. The border remains because the
   tonal step is only about 1.14:1 and is not a boundary on its own. */
.site-footer {
  background: var(--surface);
  border-top: 1px solid var(--divider);
  padding-block: var(--space-xl);
}

.site-footer__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 30rem);
  gap: var(--space-xl) var(--space-xxl);
  align-items: start;
}

.site-footer p {
  color: var(--muted);
  font-size: 0.9375rem;
  margin-block: var(--space-xs);
}

/* Each footer link stands alone on its line, so it gets the full target. The
   consent line's privacy link is inline in a sentence and keeps the
   exemption. */
.site-footer__meta a {
  display: inline-flex;
  align-items: center;
  min-height: var(--target-min);
}

/* The policy links: a plain list under the copyright lines, not a nav
   landmark, so the header navigation stays the only one on the page. Body
   links at body-small size; the muted copyright lines above them are label
   size, and one step up keeps the links readable as links. */
.site-footer__links {
  margin: var(--space-sm) 0 0;
  padding: 0;
  list-style: none;
}

.site-footer__links a {
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.5;
}

/* ---------- Live-hour sections ----------
   Five bands, one per stage of the rail, alternating surface, canvas,
   surface, canvas, surface since the ground flip of September 9, 2026.
   Shared pieces first, then one block per section. Image sources and
   permissions are in assets/live-hour/CREDITS.md. */

/* The rail numeral, repeated as the section's step. Same style as the rail. */
.step-num {
  font-family: var(--font-eyebrow);
  font-size: 0.875rem;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0.06em;
  color: var(--accent-text);
  font-variant-numeric: tabular-nums;
  margin: 0 0 var(--space-sm);
}

/* Short mono labels inside the sections: guest labels, the screen-share
   bar. The hero eyebrow, in a different colour context. */
.eyebrow {
  font-family: var(--font-eyebrow);
  font-size: 0.875rem;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0;
}

/* Captions and small notes, at the body-small size. */
.figure-note {
  color: var(--muted);
  font-size: 1rem;
  line-height: 1.5;
}

figcaption.figure-note {
  margin-top: var(--space-md);
}

/* Photographs sit at the card's radius with a border-ui edge, like every
   other object whose edge must be seen against a tonal step. */
.portrait__photo {
  display: block;
  width: 100%;
  height: auto;
  object-fit: cover;
  border: 1px solid var(--border-ui);
  border-radius: var(--radius);
}

/* Square by contract (dais-yci): every guest supplies or is given a square
   portrait of at least 800px, so the block never crops a photo it does not
   control. */
.portrait__photo {
  aspect-ratio: 1 / 1;
}

.portrait,
.room,
.stage {
  margin: 0;
}

/* 01 AI Headlines: the rail question as the display line beside a headlines
   mark drawn in the brand clock's language (same frame, same stroke, same two
   colours, a headline stroke over two columns of text strokes inside), and
   Joe's paragraph as the answer behind an accent rule. The section name drops to h4 size so the question
   leads.

   The row shares one top edge, and the mark is sized to the two-line
   question so the two read as one object: its outer frame runs from the cap
   height of the first line to the baseline of the second. At the display
   size (2.75rem, line-height 1.1) the face's cap top sits 9.3px below the
   line box and the second baseline 87.1px below it, and the frame's outer
   edge is 8/512 of the box in from each end (the rect at 24 minus half its
   32 stroke). That gives a 5.02rem box pushed down 0.46rem, both checked
   against the rendered page. Change the display token and re-derive both
   numbers. Until September 10, 2026 the frame stroke was 24, the inset
   12/512, and the box 5.1rem; the strokes went up with the brand mark's
   (Joe's 1C). The question column takes three parts to the paragraph's two,
   which keeps the question on two lines from 940px up. */
.headlines__heading {
  font-size: 1.125rem;
  line-height: 1.25;
  margin: 0 0 var(--space-xl);
}

.headlines {
  display: grid;
  grid-template-columns: 5.02rem minmax(0, 3fr) minmax(0, 2fr);
  gap: var(--space-xl);
  align-items: start;
}

.headlines__mark {
  width: 5.02rem;
  height: 5.02rem;
  margin-top: 0.46rem;
  display: block;
}

.headlines__mark-face {
  fill: var(--surface);
  stroke: var(--link);
}

/* The strokes take the logo's line colour, not body-text navy, so the mark is
   one blue object with one rust stroke, exactly what the clock is. */
.headlines__mark-line {
  stroke: var(--logo-line);
  stroke-linecap: round;
}

.headlines__mark-line--lead {
  stroke: var(--accent-text);
}

.headlines__question {
  margin: 0;
  font-size: 2.75rem;
  line-height: 1.1;
  font-weight: 700;
  color: var(--text);
  text-wrap: balance;
}

.headlines__answer {
  margin: 0;
  color: var(--muted);
  font-size: 1.125rem;
  line-height: 1.55;
  border-left: 3px solid var(--accent-text);
  padding-left: var(--space-lg);
}

/* The story list: direction 5C, Joe's choice of September 12, 2026 from
   brainstorming/headlines-directions-2026-09-09.html. Up to three of the day's
   stories on the full container measure, under the aligned row above, which it
   does not touch.

   Full measure is the whole point of the direction. At Joe's 980px window each
   title lands on one line, so the three read as a list of headlines. The four
   side-column directions were rejected because a 2fr column there is about
   360px, which wraps every title and makes the list read as three paragraphs.
   Do not move this into a column beside the question.

   Rows are already rows, so nothing here needs a mobile breakpoint. */
.story-list {
  margin-top: var(--space-xxl);
}

/* The dateline reuses the live-hour eyebrow. It is not decoration: because the
   page keeps serving the last published edition when no fresh selection
   exists, this line is what tells the reader which day these three belong to.
   It is rendered with the stories, never from the browser clock. */
.story-list__dateline {
  margin: 0 0 var(--space-sm);
}

/* The link to the fuller feed sits under the closing rule, not beside the
   dateline. A Fable 5.1 review of both treatments found the reasons, and Joe
   chose this one on September 12, 2026: "more" is a continuation word and
   belongs after the list, where the reader meets it as the stories run out,
   while "all" is an index word for a header. At the top it was the fourth bold
   blue link and the first one the eye reached, it was the brightest object in
   the dark theme's head row, and at 400px the head row had about 60px of
   slack, so a longer weekday would have wrapped it. */
.story-list__foot {
  display: flex;
  justify-content: flex-end;
  margin-top: var(--space-sm);
}

/* Below the headlines in both size and weight, so the three stories stay the
   boldest things in the section. A standalone link, so it carries the full
   44px target the system promises, the same rule .bio-link follows. */
.story-list__more {
  display: inline-flex;
  align-items: center;
  min-height: var(--target-min);
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.4;
}

.story-list__items {
  list-style: none;
  margin: 0;
  padding: 0;
}

.story-list__items > li {
  border-top: 1px solid var(--divider);
  padding-block: var(--space-md);
}

.story-list__items > li:last-child {
  border-bottom: 1px solid var(--divider);
}

.story-list__title {
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1.35;
}

/* The source domain in small mono beside the title, so a reader knows where a
   click lands before making it. nowrap keeps the domain whole when the title
   above it wraps. */
.story-list__source {
  font-family: var(--font-eyebrow);
  font-size: 0.875rem;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0.06em;
  color: var(--muted);
  white-space: nowrap;
}

/* 02 Guest of the Day */
.guest {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
  gap: var(--space-xxl);
  align-items: start;
}

.guest-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.guest-card__name {
  font-size: 2rem;
  line-height: 1.2;
}

.guest-card__line {
  color: var(--muted);
}

.technique {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  border-top: 1px solid var(--divider);
  padding-top: var(--space-md);
}

/* The base reset covers h1 to h3; h4 keeps the browser's 1.33em margins
   unless a component clears them. */
.technique h4 {
  margin: 0;
  font-size: 1.5rem;
  line-height: 1.25;
}

/* 03 Group Check-In: the room and the three things members discuss. */
.checkin {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: var(--space-xxl);
  align-items: start;
}

/* The supplied Group Check-In render includes the surrounding page ground and
   its caption. Crop those pixels in CSS so the checked-in source image stays
   untouched while the real caption can adapt to either site theme. */
.room__image-viewport {
  aspect-ratio: 653 / 508;
  background-image: url("../assets/live-hour/group-check-in-zoom.png");
  background-position: 2.13% 9.87%;
  background-repeat: no-repeat;
  background-size: 107.1975% auto;
}

.room > figcaption {
  position: relative;
  background: var(--surface);
}

.call-image {
  overflow: hidden;
  border: 1px solid var(--border-ui);
  border-radius: var(--radius);
}

.compare {
  margin: var(--space-md) 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--divider);
}

.compare li {
  padding-block: var(--space-md);
  border-bottom: 1px solid var(--divider);
}

.compare h4 {
  margin: 0 0 var(--space-xs);
}

.compare p {
  color: var(--muted);
  font-size: 1rem;
  line-height: 1.5;
}

/* 04 The Sprint: two halves under one banner, each opening with a rule, a
   heading, and one sentence. The first half is the ballot, the second the
   screen share. */
.sprint-part {
  margin-top: var(--space-xl);
  padding-top: var(--space-lg);
  border-top: 1px solid var(--divider);
}

.sprint-part h3 {
  margin-bottom: var(--space-xs);
}

/* The ballot and its spotlight, Joe's choice of September 4, 2026: the four
   rows down the left, and the voted challenge repeated large in a card on
   the right, so the half is balanced and the outcome is unmissable. The list
   has no closing rule of its own, because the next half opens with one and
   two rules a breath apart read as a mistake. */
.ballot-wrap {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: var(--space-xxl);
  align-items: start;
}

.ballot {
  margin: 0;
  padding: 0;
  list-style: none;
}

.ballot li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-md);
  align-items: start;
  padding: var(--space-md) var(--space-sm);
  border-top: 1px solid var(--divider);
}

.ballot__mark {
  width: 24px;
  height: 24px;
  flex: none;
  margin-top: 2px;
  color: var(--border-ui);
}

/* Category over the challenge, so the rows read at the list's width. */
.ballot__body {
  display: grid;
  gap: var(--space-xs);
}

.ballot__cat {
  font-family: var(--font-eyebrow);
  font-size: 0.875rem;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  padding-top: 0.3rem;
}

.ballot__status {
  font-family: var(--font-eyebrow);
  font-size: 0.875rem;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent-text);
  white-space: nowrap;
  padding-top: 0.3rem;
}

/* The voted row: filled check and bold text in the list; the card and the
   words live in the spotlight beside it. Never colour alone. */
.ballot li.is-chosen .ballot__mark {
  color: var(--accent-text);
}

.ballot__mark-check {
  stroke: var(--canvas);
}

.ballot li.is-chosen .ballot__text {
  font-weight: 700;
}

.spotlight {
  display: grid;
  gap: var(--space-sm);
  background: var(--card);
  border: 1px solid var(--border-ui);
  border-radius: var(--radius);
  padding: var(--space-lg);
}

.spotlight__mark {
  width: 32px;
  height: 32px;
  margin: 0;
  color: var(--accent-text);
}

.spotlight .ballot__status {
  padding-top: 0;
}

.spotlight__cat {
  font-family: var(--font-eyebrow);
  font-size: 0.875rem;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin: var(--space-sm) 0 0;
}

.spotlight__text {
  font-size: 1.5rem;
  line-height: 1.25;
  font-weight: 700;
  margin: 0;
}

.stage__image-viewport {
  aspect-ratio: 1170 / 734;
  background-image: url("../assets/live-hour/sprint-zoom.png");
  background-position: 50% 45.08%;
  background-repeat: no-repeat;
  background-size: 119.6581% auto;
}

.stage > figcaption {
  position: relative;
  background: var(--canvas);
}

.leave {
  margin-top: var(--space-xl);
  color: var(--muted);
}

@media (max-width: 760px) {
  /* minmax(0, 1fr), not 1fr: a bare 1fr is minmax(auto, 1fr), and a wide
     child would hold the column open past 320px. */
  .guest,
  .checkin {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-lg);
  }

  .ballot-wrap,
  .headlines {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-lg);
  }

  .headlines__mark {
    width: 5rem;
    height: 5rem;
    margin-top: 0;
  }

  .headlines__question {
    font-size: 2rem;
  }

  .guest-card__name {
    font-size: 1.625rem;
  }

  .ballot__cat,
  .ballot__status {
    padding-top: 0;
  }

  .ballot__status {
    white-space: normal;
  }

}

/* ---------- Not-found page ----------
   One band on the homepage's hero-layout grid: copy on the left, picture on
   the right from 1000px, stacked copy-then-picture below that. The page is
   three sentences and a photograph, and the first cut gave it two bands like
   the landing page; the 4rem of padding either side of the seam pushed the
   recovery links below the fold on a 1440x900 laptop, and the 40rem picture
   sat alone on the left with the right half of the band empty. In its own
   column the picture needs no cap: the column is at most about 560px wide, so
   a 1280px file still has twice the pixels it needs on a 2x display. Below
   1000px it fills the container, which is what every other photograph here
   does once it stacks.

   The picture is the page's joke and the heading is the page's message, so the
   words baked into the photograph are decoration. Its edge and radius are the
   ones every other photograph on the site uses. */
.not-found-image {
  display: block;
  width: 100%;
  height: auto;
  order: -1;
  border: 1px solid var(--border-ui);
  border-radius: var(--radius);
}

/* Below the 1000px breakpoint the picture comes first. Joe's call on
   September 13, 2026: on a phone the joke is the point of this page, and the
   message and the two links sit immediately under it either way. Source order
   stays copy first, so a screen reader still hears the heading, the sentence
   and the links before the picture, and nothing inside the picture is
   focusable, so no control can be tabbed out of the order it appears in. From
   1000px the grid takes over, copy left and picture right, and order returns
   to source order so the two agree again. */
@media (min-width: 1000px) {
  .not-found-image {
    order: 0;
  }
}

/* The lede's 1.5rem bottom margin was sized for the button that follows it on
   the homepage. Here a second heading follows, and the two pairs, heading
   and sentence then heading and links, need more air between them than
   inside them. */
.not-found-copy .hero-lede {
  margin-bottom: var(--space-xl);
}

.not-found-next {
  margin-top: var(--space-sm);
}

/* ---------- Responsive ---------- */

/* The masthead stays centred at every width. Below 760px the rule row stops
   centring its links: they take the left edge and wrap to two lines, the
   theme control keeps the right edge, and the wordmark and mark step down so
   the lockup fits a phone. Same DOM order as the wide layout, so the tab order
   never differs from what is on screen. The list wraps onto a third line only
   when the viewport forces it; nothing hides behind a button. */
@media (max-width: 760px) {
  .site-header__row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-xs) var(--space-md);
    padding-block: var(--space-xs);
  }
  /* flex-basis 0, not auto: with auto the list's one-line width is the
     basis, wider than the row, so the nav took a row of its own and pushed
     the theme control to a second. With 0 it takes what the theme control
     leaves and wraps its links inside that. */
  .site-nav {
    flex: 1 1 0;
    min-width: 0;
  }
  .site-nav__list {
    justify-content: flex-start;
    gap: 0 var(--space-md);
    /* The links' 4px side padding would set their letters 4px inside the
       edge the hero text sits on. Pull the list back so the letters share it. */
    margin-inline-start: calc(-1 * var(--space-xs));
  }
  .theme-choice label {
    min-width: 48px;
  }
  .brand-name {
    font-size: 2.25rem;
  }
  /* Cap line to dateline baseline is 49.6px at 2.25rem over the 13px
     dateline; box and offset re-derived as for the wide size. */
  .dais-mark {
    width: 3.203rem;
    height: 3.203rem;
    margin-top: 0.39rem;
  }
}

@media (max-width: 480px) {
  .brand {
    gap: var(--space-sm);
  }
  .brand-name {
    font-size: 1.625rem;
  }
  /* The dateline has to end inside the name. At 1.625rem the name is about
     193px wide and the 13px tagline about 222px, so it steps down too. */
  .brand-tagline {
    font-size: 0.75rem;
    letter-spacing: 0.12em;
  }
  /* Cap line to dateline baseline is 39px at 1.625rem over the 12px
     dateline; box and offset re-derived as for the wide size. */
  .dais-mark {
    width: 2.514rem;
    height: 2.514rem;
    margin-top: 0.3125rem;
  }
}

@media (max-width: 760px) {
  h1 {
    font-size: 2.25rem;
  }
  h2 {
    font-size: 1.625rem;
  }
  .hero {
    padding-block: var(--space-xxl);
  }
  .band {
    padding-block: var(--space-xl);
  }
  .membership-grid {
    grid-template-columns: minmax(0, 1fr);
  }
  .membership-card {
    padding: min(var(--space-lg), 5vw);
  }

  .pricing-intro h1 {
    font-size: 2.25rem;
  }
  .faq-grid,
  .site-footer__layout {
    grid-template-columns: 1fr;
  }
  .field-row {
    flex-direction: column;
  }
  /* The 16rem flex-basis above is a width. In a column it would become a
     height, and the field rendered 256px tall. */
  input[type="email"] {
    flex-basis: auto;
  }
  .action,
  .theme-choice label,
  input[type="email"],
  .contact-form input[type="text"] {
    min-height: 48px;
  }
  .team-grid {
    grid-template-columns: 1fr;
  }
}

/* ---------- Motion ----------
   Hover transitions only. A theme change must repaint instantly: cross-fading
   the whole page reads as a smear, and it also leaves the page in a half-applied
   palette that automated contrast checks will sample and fail on. The
   theme-switching class is added for one frame while the palette swaps. */
@media (prefers-reduced-motion: no-preference) {
  a,
  .action {
    transition: background-color 150ms ease-out, color 150ms ease-out;
  }
}

:root.theme-switching *,
:root.theme-switching *::before,
:root.theme-switching *::after {
  transition: none !important;
}

/* ---------- Forced colors ----------
   Preserve system colours rather than simulating Solarized. Backgrounds are
   dropped in this mode, so the action fill and the input border need explicit
   boundaries to stay perceivable. */
@media (forced-colors: active) {
  .action {
    border: 1px solid ButtonText;
    background: ButtonFace;
    color: ButtonText;
    forced-color-adjust: none;
  }

  .action:hover {
    background: Highlight;
    color: HighlightText;
  }

  .membership-card,
  .bio-card,
  .session-rail,
  .theme-choice label,
  input[type="email"],
  .contact-form input[type="text"],
  .contact-form textarea {
    border: 1px solid CanvasText;
  }

  /* Forced colours drop tonal boundaries, so keep the call-image edge. */
  .call-image {
    border: 1px solid CanvasText;
  }

  .ballot li.is-chosen .ballot__mark {
    color: CanvasText;
  }

  .ballot__mark-check {
    stroke: Canvas;
  }

  .skeleton span {
    border: 1px solid GrayText;
  }

  /* The inverted chip has nothing to invert once backgrounds are dropped, and
     the radios themselves are clipped, so without this the live option would
     be unmarked. Highlight and HighlightText are the system's own "this one
     is selected" pair, which is why they are worth opting back in for. */
  .theme-choice input:checked + label {
    background: Highlight;
    color: HighlightText;
    forced-color-adjust: none;
  }

  /* Backgrounds are dropped here, so the mark has to fall back to system
     colours or it disappears into the page. */
  .dais-mark__face {
    fill: Canvas;
    stroke: CanvasText;
  }

  /* --hour is named explicitly rather than left to source order, so the accent
     hand cannot survive into a mode that has dropped the palette. The 8:00
     still reads because the hour hand is the thicker of the two. */
  .dais-mark__hand,
  .dais-mark__hand--hour {
    stroke: CanvasText;
  }

  /* GrayText is the system's own "secondary" tone, which is what muted means.
     The live state loses its accent like the hour hand does, and still reads
     because the live dot is larger. */
  .dais-mark__now {
    fill: GrayText;
  }

  .dais-mark__now--live {
    fill: CanvasText;
  }

  :focus-visible {
    outline: 3px solid Highlight;
  }
}
