/*
 * Design tokens — the roles named in docs/step-6-design-system.md §3–§7.
 *
 * Components reference roles, never values. Every role carries a light and a dark value, so no
 * component hard-codes a mode. Exact values are a STEP 7 production decision within those roles;
 * the contrast requirements in §3.2 and §14 are what they are chosen against.
 *
 * The palette is the LoveBeat warm-editorial direction: a cream ground, a muted berry primary and
 * a set of pastel category tints. Every value below is measured against the contrast requirements
 * in tests/design.test.js before it ships.
 */

:root {
  color-scheme: light dark;

  /* Surfaces and ink */
  --background: #fff9f5;
  --surface: #ffffff;
  --surface-raised: #ffffff;
  --surface-quiet: #f6eee9;
  --text-primary: #302a2b;
  --text-secondary: #6d6263;
  --text-muted: #74696a;
  --border: rgba(48, 42, 43, 0.12);
  --border-soft: rgba(48, 42, 43, 0.07);
  --border-strong: #bc3f5c;

  /* Accent and focus */
  --accent: #bc3f5c;
  --accent-hover: #a13150;
  --accent-ink: #a13150;
  --on-accent: #ffffff;
  --accent-quiet: rgba(188, 63, 92, 0.08);
  --focus: #1a5fd0;

  /* Pastel palette — the category tints and their decorative washes */
  --tint-crush: #fbe7ec;
  --tint-dating: #fbeadc;
  --tint-relationship: #eee8f7;
  --tint-relationship-health: #e4f0ea;
  --tint-ex-breakup: #faf0d4;
  --tint-fun: #e7f1e3;

  --mark-crush: #d1567a;
  --mark-dating: #c2703c;
  --mark-relationship: #7a5bb0;
  --mark-relationship-health: #2f7d63;
  --mark-ex-breakup: #9a7420;
  --mark-fun: #38795a;

  --wash-blush: #f9e6e9;
  --wash-peach: #f8e4d5;
  --wash-lavender: #ece4f5;
  --wash-butter: #f9efd2;
  --wash-mint: #e2f0e8;
  --wash-cream: #fdf3ec;

  /* Hero illustration. Decorative fills only — no text is ever set in these, so they carry no
     contrast requirement of their own. Kept together so the whole scene can be retinted at once. */
  --art-skin: #f6d9c4;
  --art-skin-shade: #eec4a8;
  --art-hair: #7d4f38;
  --art-hair-dark: #653c2a;
  --art-sweater: #f6cdd4;
  --art-sweater-shade: #eab4bf;
  --art-cat: #f4efec;
  --art-cat-dark: #4a4245;
  --art-leaf: #9dc4a8;
  --art-leaf-soft: #c3ddc9;
  --art-wood: #e8cdb6;
  --art-window: #fdf1ea;
  --art-pane: #f6e3e6;
  --art-book-a: #e8b9c2;
  --art-book-b: #f3d9bd;
  --art-book-c: #d9c4e4;
  --art-line: #56413f;
  --art-heart-wash: #f7dbe1;

  /* Signal tags */
  --positive: #2c6844;
  --neutral: #6a6158;
  --caution: #855415;

  /* Result families */
  --family-bright: #b3801d;
  --family-mixed: #27756f;
  --family-unclear: #66499a;
  --family-quiet: #56606c;
  --family-attention: #27497e;
  --family-safety: #494540;
  --info: #27568f;

  /* UI confirmation and fault — never used on a reading (§3.3) */
  --ui-success: #2c6844;
  --ui-error: #9a3327;

  /* Type */
  --font-sans: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
    'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';
  --font-display: Georgia, 'Iowan Old Style', 'Palatino Linotype', 'Times New Roman', serif;

  --text-display: 2.25rem;    /* 36 */
  --text-h1: 1.625rem;        /* 26 */
  --text-h2: 1.375rem;        /* 22 */
  --text-h3: 1.125rem;        /* 18 */
  --text-body-lg: 1.0625rem;  /* 17 */
  --text-body: 1rem;          /* 16 */
  --text-sm: 0.875rem;        /* 14 */
  --text-xs: 0.8125rem;       /* 13 */

  --lh-display: 1.1;
  --lh-h1: 1.2;
  --lh-h2: 1.2;
  --lh-h3: 1.3;
  --lh-body-lg: 1.6;
  --lh-body: 1.55;
  --lh-sm: 1.5;
  --lh-xs: 1.45;

  --weight-display: 700;
  --weight-h1: 700;
  --weight-h2: 650;
  --weight-h3: 600;
  --weight-body: 400;
  --weight-meta: 500;

  /* Spacing — a 4px base scale */
  --space-1: 4px;  --space-2: 8px;  --space-3: 12px; --space-4: 16px;
  --space-5: 20px; --space-6: 24px; --space-7: 32px; --space-8: 40px;
  --space-9: 48px; --space-10: 64px; --space-11: 80px; --space-12: 96px;

  /* Section rhythm — the editorial vertical spacing of the homepage */
  --rhythm: var(--space-10);

  /* Radii, borders, elevation */
  --radius-sm: 10px;
  --radius-md: 16px;
  --radius-lg: 24px;
  --radius-xl: 28px;
  --radius-full: 999px;
  --border-hairline: 1px;
  --border-control: 1.5px;
  --border-selected: 2px;
  --shadow-1: 0 1px 2px rgba(48, 26, 33, 0.05), 0 6px 20px rgba(48, 26, 33, 0.06);
  --shadow-soft: 0 8px 30px rgba(48, 26, 33, 0.06);
  --shadow-lift: 0 14px 34px rgba(48, 26, 33, 0.11);

  /* Layout */
  --width-prose: 68ch;
  --width-content: 720px;
  --width-page: 1180px;
  --width-sheet: 560px;
  --edge: var(--space-4);

  /* Motion */
  --motion-instant: 0ms;
  --motion-fast: 120ms;
  --motion-base: 200ms;
  --motion-sheet: 260ms;
  --motion-analysis: 1200ms;
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);

  /* Result palette — the default. A page names its calculator or its category to override it. */
  --r-wash: var(--wash-blush);
  --r-tint: var(--tint-crush);
  --r-ink: var(--accent-ink);
  --r-mark: var(--accent);

  /* Icons */
  --icon-sm: 16px;
  --icon-md: 20px;
  --icon-lg: 24px;
}

@media (min-width: 480px) {
  :root { --edge: var(--space-5); }
}

/* Category palettes. A category page, a hub section and the 404 tiles take these. */
[data-category='crush'] { --r-wash: #faebee; --r-tint: #f2cfd8; --r-ink: #c53459; --r-mark: #c94062; }
[data-category='dating'] { --r-wash: #faf2eb; --r-tint: #f2e0cf; --r-ink: #996129; --r-mark: #b37332; }
[data-category='relationship'] { --r-wash: #f1ebfa; --r-tint: #dfcff2; --r-ink: #7e3ecc; --r-mark: #7e40c9; }
[data-category='relationship-health'] { --r-wash: #ebfaf2; --r-tint: #cff2e0; --r-ink: #228152; --r-mark: #2b9761; }
[data-category='ex-breakup'] { --r-wash: #faf6eb; --r-tint: #f2eacf; --r-ink: #856e23; --r-mark: #9f842d; }
[data-category='fun'] { --r-wash: #f0faeb; --r-tint: #dbf2cf; --r-ink: #407d21; --r-mark: #4f972b; }

/*
 * Result palettes — one per calculator.
 *
 * A reading is the moment the product feels personal, so every calculator carries its own colour
 * through its result page: --r-wash behind the reading, --r-tint on its chips, --r-mark on the
 * decorative marks and --r-ink on accent text. Values are generated from one hue per calculator
 * and every one is measured: text-primary 7:1 on wash and on tint, text-secondary 4.5:1 on wash,
 * --r-ink 4.5:1 on wash and on surface, --r-mark 3:1 on tint — in both modes.
 *
 * These carry no meaning. The reading's own family keeps --family for the marks that do.
 */
[data-calculator='crush-potential'] { --r-wash: #faebf0; --r-tint: #f2cfdb; --r-ink: #c13363; --r-mark: #c9406e; }
[data-calculator='do-they-like-you'] { --r-wash: #faebed; --r-tint: #f2cfd4; --r-ink: #c53448; --r-mark: #c94052; }
[data-calculator='more-than-friends'] { --r-wash: #faebf5; --r-tint: #f2cfe7; --r-ink: #bd3294; --r-mark: #c940a0; }
[data-calculator='make-a-move'] { --r-wash: #faedeb; --r-tint: #f2d4cf; --r-ink: #bd4532; --r-mark: #c95240; }
[data-calculator='first-date-potential'] { --r-wash: #faf0eb; --r-tint: #f2dccf; --r-ink: #a5582c; --r-mark: #bf6836; }
[data-calculator='dating-compatibility'] { --r-wash: #faf4eb; --r-tint: #f2e4cf; --r-ink: #916627; --r-mark: #ab7a30; }
[data-calculator='ghosting-risk'] { --r-wash: #f2ebfa; --r-tint: #dfcff2; --r-ink: #803ecc; --r-mark: #8040c9; }
[data-calculator='relationship-potential'] { --r-wash: #f7ebfa; --r-tint: #ebcff2; --r-ink: #a834c5; --r-mark: #ae40c9; }
[data-calculator='losing-interest'] { --r-wash: #edebfa; --r-tint: #d5cff2; --r-ink: #553ecc; --r-mark: #5740c9; }
[data-calculator='relationship-rut'] { --r-wash: #ebf1fa; --r-tint: #cfdef2; --r-ink: #316cb9; --r-mark: #407bc9; }
[data-calculator='long-distance'] { --r-wash: #ebf5fa; --r-tint: #cfe7f2; --r-ink: #297799; --r-mark: #3189af; }
[data-calculator='marriage-compatibility'] { --r-wash: #faf7eb; --r-tint: #f2eccf; --r-ink: #817122; --r-mark: #97852b; }
[data-calculator='breakup-risk'] { --r-wash: #ebedfa; --r-tint: #cfd4f2; --r-ink: #3e51cc; --r-mark: #4052c9; }
[data-calculator='trust-issues'] { --r-wash: #ebfaf7; --r-tint: #cff2eb; --r-ink: #217d6b; --r-mark: #2b9781; }
[data-calculator='right-for-you'] { --r-wash: #ebfaf3; --r-tint: #cff2e2; --r-ink: #217d52; --r-mark: #2b9765; }
[data-calculator='text-my-ex'] { --r-wash: #faebf9; --r-tint: #f2cfef; --r-ink: #b530ac; --r-mark: #c940c0; }
[data-calculator='reconnection-potential'] { --r-wash: #ebfaed; --r-tint: #cff2d4; --r-ink: #22812f; --r-mark: #2b9739; }
[data-calculator='dating-vibe'] { --r-wash: #effaeb; --r-tint: #d8f2cf; --r-ink: #3a7d21; --r-mark: #48972b; }
[data-calculator='meet-your-type'] { --r-wash: #ebf9fa; --r-tint: #cfeff2; --r-ink: #227b81; --r-mark: #2b9097; }

@media (min-width: 768px) {
  :root {
    --text-display: 3.25rem;  /* 52 */
    --text-h1: 2.125rem;      /* 34 */
    --text-h2: 1.875rem;      /* 30 */
    --text-h3: 1.25rem;       /* 20 */
    --text-body-lg: 1.125rem; /* 18 */
    --edge: var(--space-6);
    --rhythm: var(--space-11);
  }
}

@media (min-width: 1024px) {
  :root {
    --text-display: 3.75rem;  /* 60 */
    --rhythm: var(--space-12);
  }
}

@media (prefers-color-scheme: dark) {
  :root {
    --background: #171213;
    --surface: #211b1d;
    --surface-raised: #271f22;
    --surface-quiet: #241d20;
    --text-primary: #f8f1ee;
    --text-secondary: #c5b7b5;
    --text-muted: #ab9d9c;
    --border: rgba(255, 255, 255, 0.16);
    --border-soft: rgba(255, 255, 255, 0.08);
    --border-strong: #e79dab;

    --accent: #f0919f;
    --accent-hover: #f6abb6;
    --accent-ink: #f0919f;
    --on-accent: #2a1116;
    --accent-quiet: rgba(240, 145, 159, 0.16);
    --focus: #86b4ff;

    --tint-crush: #2e2023;
    --tint-dating: #2d2320;
    --tint-relationship: #262330;
    --tint-relationship-health: #1e2a25;
    --tint-ex-breakup: #2c2719;
    --tint-fun: #1f2a20;

    --mark-crush: #f09ab2;
    --mark-dating: #e7a877;
    --mark-relationship: #bda6ec;
    --mark-relationship-health: #79c7a6;
    --mark-ex-breakup: #dcbb6a;
    --mark-fun: #85c8a2;

    --wash-blush: #2b1f22;
    --wash-peach: #2b2220;
    --wash-lavender: #262231;
    --wash-butter: #2a2619;
    --wash-mint: #1e2a25;
    --wash-cream: #221c1e;

    --art-skin: #d8ab8d;
    --art-skin-shade: #c1906f;
    --art-hair: #6b4230;
    --art-hair-dark: #523325;
    --art-sweater: #b8808d;
    --art-sweater-shade: #9d6775;
    --art-cat: #d6cfcb;
    --art-cat-dark: #35302f;
    --art-leaf: #6f9a7d;
    --art-leaf-soft: #4c6b56;
    --art-wood: #4a3a30;
    --art-window: #2a2225;
    --art-pane: #352a2e;
    --art-book-a: #a86f7c;
    --art-book-b: #b28f68;
    --art-book-c: #8b76a0;
    --art-line: #2a2224;
    --art-heart-wash: #3a2830;

    --positive: #78c294;
    --neutral: #ab9d9c;
    --caution: #e0aa58;

    --family-bright: #ddb257;
    --family-mixed: #64b8b0;
    --family-unclear: #b49ce6;
    --family-quiet: #9aa5b3;
    --family-attention: #8fb0e8;
    --family-safety: #d3cac6;
    --info: #86aee0;

    --ui-success: #78c294;
    --ui-error: #e89184;

    --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.4), 0 6px 20px rgba(0, 0, 0, 0.35);
    --shadow-soft: 0 8px 30px rgba(0, 0, 0, 0.34);
    --shadow-lift: 0 14px 34px rgba(0, 0, 0, 0.46);
  }

  /* Category palettes, dark. */
  [data-category='crush'] { --r-wash: #2b1d20; --r-tint: #3d292e; --r-ink: #d5627f; --r-mark: #c95472; }
  [data-category='dating'] { --r-wash: #2b241d; --r-tint: #3d3329; --r-ink: #d08f4e; --r-mark: #c98f54; }
  [data-category='relationship'] { --r-wash: #231d2b; --r-tint: #32293d; --r-ink: #a172da; --r-mark: #9160cd; }
  [data-category='relationship-health'] { --r-wash: #1d2b24; --r-tint: #293d33; --r-ink: #4ed08f; --r-mark: #54c98f; }
  [data-category='ex-breakup'] { --r-wash: #2b281d; --r-tint: #3d3829; --r-ink: #d0b24e; --r-mark: #c9ae54; }
  [data-category='fun'] { --r-wash: #212b1d; --r-tint: #303d29; --r-ink: #79d04e; --r-mark: #7bc954; }

  /* Result palettes, dark. The same hues, held to the same measured minimums. */
  [data-calculator='crush-potential'] { --r-wash: #2b1d21; --r-tint: #3d2930; --r-ink: #d56288; --r-mark: #c9547b; }
  [data-calculator='do-they-like-you'] { --r-wash: #2b1d1e; --r-tint: #3d292c; --r-ink: #d66675; --r-mark: #c95464; }
  [data-calculator='more-than-friends'] { --r-wash: #2b1d27; --r-tint: #3d2937; --r-ink: #d45eb1; --r-mark: #c954a6; }
  [data-calculator='make-a-move'] { --r-wash: #2b1e1d; --r-tint: #3d2c29; --r-ink: #d36a5a; --r-mark: #c96454; }
  [data-calculator='first-date-potential'] { --r-wash: #2b221d; --r-tint: #3d3029; --r-ink: #d07d4e; --r-mark: #c97f54; }
  [data-calculator='dating-compatibility'] { --r-wash: #2b251d; --r-tint: #3d3529; --r-ink: #d09c4e; --r-mark: #c99a54; }
  [data-calculator='ghosting-risk'] { --r-wash: #231d2b; --r-tint: #32293d; --r-ink: #a272da; --r-mark: #905ccc; }
  [data-calculator='relationship-potential'] { --r-wash: #281d2b; --r-tint: #39293d; --r-ink: #be62d5; --r-mark: #b254c9; }
  [data-calculator='losing-interest'] { --r-wash: #1f1d2b; --r-tint: #2d293d; --r-ink: #8a7adc; --r-mark: #7968cf; }
  [data-calculator='relationship-rut'] { --r-wash: #1d232b; --r-tint: #29323d; --r-ink: #568cd2; --r-mark: #5487c9; }
  [data-calculator='long-distance'] { --r-wash: #1d272b; --r-tint: #29373d; --r-ink: #4ea9d0; --r-mark: #54a6c9; }
  [data-calculator='marriage-compatibility'] { --r-wash: #2b281d; --r-tint: #3d3929; --r-ink: #d0ba4e; --r-mark: #c9b654; }
  [data-calculator='breakup-risk'] { --r-wash: #1d1e2b; --r-tint: #292c3d; --r-ink: #7280da; --r-mark: #606fcd; }
  [data-calculator='trust-issues'] { --r-wash: #1d2b28; --r-tint: #293d39; --r-ink: #4ed0b6; --r-mark: #54c9b2; }
  [data-calculator='right-for-you'] { --r-wash: #1d2b24; --r-tint: #293d34; --r-ink: #4ed093; --r-mark: #54c993; }
  [data-calculator='text-my-ex'] { --r-wash: #2b1d2a; --r-tint: #3d293b; --r-ink: #d256ca; --r-mark: #c954c1; }
  [data-calculator='reconnection-potential'] { --r-wash: #1d2b1e; --r-tint: #293d2c; --r-ink: #4ed05f; --r-mark: #54c964; }
  [data-calculator='dating-vibe'] { --r-wash: #202b1d; --r-tint: #2e3d29; --r-ink: #70d04e; --r-mark: #74c954; }
  [data-calculator='meet-your-type'] { --r-wash: #1d2a2b; --r-tint: #293b3d; --r-ink: #4ec7d0; --r-mark: #54c1c9; }
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --motion-fast: var(--motion-instant);
    --motion-base: var(--motion-instant);
    --motion-sheet: var(--motion-instant);
  }
}

/*
 * Application styles — the thirty components of docs/step-6-ui-specification.md §2, built on the
 * roles in tokens.css. Nothing here invents a colour value or a size; everything references a token.
 */

/* ---------- Reset and base ---------- */

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

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

body {
  margin: 0;
  background: var(--background);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: var(--text-body);
  line-height: var(--lh-body);
  font-weight: var(--weight-body);
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, p, ul, ol, figure, blockquote { margin: 0; }
ul, ol { padding: 0; list-style: none; }
img, svg { max-width: 100%; }
button { font: inherit; color: inherit; }

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--accent-hover); }

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* ---------- 2.1 App shell ---------- */

.skip-link {
  position: absolute; left: var(--space-4); top: var(--space-2);
  transform: translateY(-200%);
  background: var(--surface); color: var(--text-primary);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-1);
  z-index: 50;
}
.skip-link:focus { transform: translateY(0); }

.page { display: flex; flex-direction: column; min-height: 100vh; }
.page > main { flex: 1 0 auto; }

.wrap { width: 100%; max-width: var(--width-page); margin-inline: auto; padding-inline: var(--edge); }
.icon { width: var(--icon-md); height: var(--icon-md); flex: none; }
.wrap--content { max-width: var(--width-content); }
.prose { max-width: var(--width-prose); }

.section { padding-block: var(--space-8); }
.section + .section { padding-top: 0; }
.stack > * + * { margin-top: var(--space-4); }
.stack-lg > * + * { margin-top: var(--space-7); }

/* ---------- Type roles ---------- */

.t-display { font-family: var(--font-display); font-size: var(--text-display); line-height: var(--lh-display); font-weight: var(--weight-display); letter-spacing: -0.01em; }
.t-h1 { font-size: var(--text-h1); line-height: var(--lh-h1); font-weight: var(--weight-h1); letter-spacing: -0.01em; }
.t-h2 { font-size: var(--text-h2); line-height: var(--lh-h2); font-weight: var(--weight-h2); }
.t-h3 { font-size: var(--text-h3); line-height: var(--lh-h3); font-weight: var(--weight-h3); }
.t-body-lg { font-size: var(--text-body-lg); line-height: var(--lh-body-lg); }
.t-sm { font-size: var(--text-sm); line-height: var(--lh-sm); }
.t-xs { font-size: var(--text-xs); line-height: var(--lh-xs); font-weight: var(--weight-meta); }
.t-secondary { color: var(--text-secondary); }
.t-muted { color: var(--text-muted); }
.eyebrow { font-size: var(--text-xs); letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-secondary); font-weight: var(--weight-meta); }

/* ---------- 2.2 Header ---------- */

/*
 * The header carries the brand. It used to be a 72px bar with an 18px wordmark and 14px grey
 * links, which read as an afterthought under a hero this size; now the wordmark is the strongest
 * thing in the bar, the links are set in the body size and the page's own ink, and the call to
 * action stands at the height of the hero's own buttons. The three zones share one centre line.
 */
.header { border-bottom: var(--border-hairline) solid var(--border-soft); background: var(--background); }
.header__bar { display: flex; flex-wrap: nowrap; align-items: center; gap: var(--space-3) var(--space-4); min-height: 72px; padding-block: var(--space-2); }

/* The brand scales through three custom properties, so the header and the situation sheet can
   set it large while the footer and the flow bar keep the size they had. */
.brand {
  --brand-badge: 34px; --brand-mark: var(--icon-md); --brand-name: var(--text-h3); --brand-kind: var(--text-xs); --brand-kind-tracking: 0.1em;
  display: inline-flex; align-items: center; gap: var(--space-3); color: var(--text-primary); text-decoration: none;
}
.brand__badge { display: grid; place-items: center; flex: none; width: var(--brand-badge); height: var(--brand-badge); border-radius: var(--radius-full); background: var(--wash-blush); color: var(--accent); }
.brand__mark { width: var(--brand-mark); height: var(--brand-mark); flex: none; }
.brand__words { display: flex; flex-direction: column; line-height: 1.05; }
.brand__name { font-family: var(--font-display); font-size: var(--brand-name); font-weight: 700; letter-spacing: -0.01em; }
.brand__kind { font-size: var(--brand-kind); letter-spacing: var(--brand-kind-tracking); text-transform: uppercase; color: var(--text-muted); font-weight: var(--weight-meta); }
.brand:hover .brand__badge { background: var(--accent-quiet); }
.header .brand, .sheet__head .brand {
  --brand-badge: 44px; --brand-mark: 22px; --brand-name: 1.5rem; --brand-kind: 0.6875rem; --brand-kind-tracking: 0.2em;
  gap: var(--space-3);
}
.header .brand__words, .sheet__head .brand__words { gap: 2px; }
.header .brand__kind, .sheet__head .brand__kind { color: var(--text-secondary); }

.header__nav { display: none; margin-inline: auto; }
.header__links { display: flex; align-items: center; gap: var(--space-6); }
.header__links a {
  display: inline-flex; align-items: center; min-height: 44px;
  color: var(--text-primary); text-decoration: none;
  font-size: 0.9375rem; font-weight: var(--weight-meta); line-height: 1.2; white-space: nowrap;
  text-underline-offset: 0.45em; text-decoration-thickness: 1.5px; text-decoration-color: var(--accent);
  transition: color var(--motion-fast) var(--ease-standard);
}
.header__links a:hover { color: var(--accent-ink); text-decoration-line: underline; }
.header__links a[aria-current='page'] { color: var(--accent-ink); font-weight: var(--weight-h3); }
/*
 * Below the navigation breakpoint the sheet trigger is the single entry point: showing the
 * primary call to action as well pushed the bar past the viewport at 320-390px.
 */
.header__bar > .header__cta { display: none; flex: none; white-space: nowrap; }
.header__cta .arrow { margin-left: calc(var(--space-1) * -1); }
.header__sheet-trigger { margin-left: auto; flex: none; }
.header .brand { flex: none; }

/* The narrowest phones: the brand and the trigger share 288px, so both draw in a little rather
   than letting the bar wrap onto a second row. */
@media (max-width: 359px) {
  .header .brand { --brand-badge: 40px; --brand-mark: 20px; --brand-name: 1.375rem; gap: var(--space-2); }
  .header__bar > .header__sheet-trigger { padding-inline: var(--space-3); }
}

/*
 * The navigation keeps the breakpoint it already had. Between 1024 and 1199px the brand, seven
 * links and the call to action only just fit on one line, so the bar holds an intermediate size:
 * the links keep their new weight and colour at fifteen pixels, the gaps and the button draw in,
 * and the brand stops short of its full height. From 1200px everything reaches the reference.
 */
@media (min-width: 1024px) {
  .header__bar { min-height: 84px; gap: var(--space-5); }
  .header .brand { --brand-badge: 40px; --brand-mark: 20px; --brand-name: 1.375rem; --brand-kind: 0.6875rem; --brand-kind-tracking: 0.12em; gap: var(--space-2); }
  .header__nav { display: block; }
  .header__links { gap: var(--space-3); }
  .header__bar > .header__cta { display: inline-flex; margin-left: 0; min-height: 48px; padding-inline: var(--space-4); }
  .header__bar > .header__sheet-trigger { display: none; }
}

/* A little more room: the links take their full spacing before the bar reaches its full height. */
@media (min-width: 1120px) {
  .header__bar { gap: var(--space-6); }
  .header .brand { --brand-badge: 48px; --brand-mark: 24px; --brand-name: 1.625rem; --brand-kind: 0.75rem; --brand-kind-tracking: 0.18em; gap: var(--space-3); }
  .header__links { gap: var(--space-5); }
}

@media (min-width: 1200px) {
  .header__bar { min-height: 92px; padding-block: var(--space-3); }
  .header .brand { --brand-badge: 52px; --brand-mark: 26px; --brand-name: 1.75rem; --brand-kind: 0.75rem; --brand-kind-tracking: 0.22em; gap: var(--space-3); }
  .header__links { gap: var(--space-6); }
  .header__bar > .header__cta { min-height: 52px; padding: var(--space-3) var(--space-5); }
}
/* ---------- 2.3 Situation sheet ---------- */

.sheet {
  position: fixed; inset: 0; z-index: 40; border: 0; padding: 0; margin: 0;
  width: 100%; max-width: 100%; height: 100%; max-height: 100%;
  background: var(--surface); color: var(--text-primary);
}
.sheet::backdrop { background: rgba(20, 16, 13, 0.5); }
.sheet__inner { display: flex; flex-direction: column; height: 100%; max-width: var(--width-sheet); margin-inline: auto; padding: var(--space-4) var(--edge) var(--space-8); overflow-y: auto; }
.sheet__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-5); }
.sheet__rows > li + li { margin-top: var(--space-2); }
.sheet__row { display: block; padding: var(--space-4); border-radius: var(--radius-md); border: var(--border-hairline) solid var(--border); text-decoration: none; color: var(--text-primary); }
.sheet__row:hover { background: var(--accent-quiet); }
.sheet__row span { display: block; }

/* ---------- 2.4 Flow header ---------- */

.flow-header { display: flex; align-items: center; gap: var(--space-4); padding-block: var(--space-4); }
.flow-header .brand { pointer-events: none; }
.flow-header__progress { flex: 1 1 auto; }

/* ---------- 2.5 Footer ---------- */

.footer { border-top: var(--border-hairline) solid var(--border-soft); margin-top: var(--space-6); padding-block: var(--space-7); color: var(--text-secondary); font-size: var(--text-sm); background: var(--wash-cream); }
.footer__top { display: grid; gap: var(--space-6); }
.footer__brand .brand { pointer-events: auto; }
.footer__line { margin-top: var(--space-3); color: var(--text-muted); font-size: var(--text-sm); max-width: 26ch; }
.footer__cols { display: grid; gap: var(--space-5); }
.footer h2 { font-size: var(--text-xs); letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-muted); margin-bottom: var(--space-3); }
.footer li + li { margin-top: var(--space-2); }
.footer a { color: var(--text-secondary); text-decoration: none; }
.footer a:hover { color: var(--text-primary); text-decoration: underline; }
.footer__fine { margin-top: var(--space-5); padding-top: var(--space-4); border-top: var(--border-hairline) solid var(--border); color: var(--text-muted); font-size: var(--text-xs); }
.footer__fine p + p { margin-top: var(--space-2); }
@media (min-width: 768px) { .footer__cols { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1024px) { .footer__top { grid-template-columns: minmax(220px, 1fr) 2fr; gap: var(--space-7); } }

/* ---------- 2.6 Hero ---------- */

.hero { padding-block: var(--space-9) var(--space-8); }
.hero__chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.chip { display: inline-flex; align-items: center; gap: var(--space-1); padding: var(--space-1) var(--space-3); border-radius: var(--radius-full); border: var(--border-hairline) solid var(--border); font-size: var(--text-xs); color: var(--text-secondary); }
.hero__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4); }

/* ---------- 2.7 Situation tile / 2.8 Calculator card / 2.23 Recommendation card ---------- */

.grid { display: grid; gap: var(--space-4); }
@media (min-width: 480px) { .grid--tiles { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 768px) { .grid--tiles { grid-template-columns: repeat(3, 1fr); } .grid--cards { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .grid--cards { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1280px) { .grid--cards { grid-template-columns: repeat(3, 1fr); } }

.card {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-5); border-radius: var(--radius-md);
  background: var(--surface); border: var(--border-hairline) solid var(--border);
  text-decoration: none; color: var(--text-primary);
  transition: border-color var(--motion-fast) var(--ease-standard), transform var(--motion-fast) var(--ease-standard);
}
.card:hover { border-color: var(--border-strong); color: var(--text-primary); }
.card:active { transform: translateY(1px); }
.card .arrow { display: inline-grid; place-items: center; width: var(--icon-md); height: var(--icon-md); color: var(--accent-ink); transition: transform var(--motion-fast) var(--ease-standard); }
.card:hover .arrow { transform: translateX(3px); }
.card__title { font-size: var(--text-h3); line-height: var(--lh-h3); font-weight: var(--weight-h3); }
.card__reason, .card__meta { font-size: var(--text-sm); color: var(--text-secondary); }
.card__meta { margin-top: auto; padding-top: var(--space-2); color: var(--text-muted); }

/* ---------- 2.15/2.16/2.17 Buttons ---------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  min-height: 44px; padding: var(--space-3) var(--space-6);
  border-radius: var(--radius-md); border: var(--border-control) solid transparent;
  font-size: var(--text-body); font-weight: var(--weight-h3); line-height: 1.2;
  text-decoration: none; cursor: pointer; background: none;
  transition: background-color var(--motion-fast) var(--ease-standard),
    border-color var(--motion-fast) var(--ease-standard),
    transform var(--motion-fast) var(--ease-standard),
    box-shadow var(--motion-fast) var(--ease-standard);
}
.btn .arrow { flex: none; width: var(--icon-md); height: var(--icon-md); display: inline-grid; place-items: center; transition: transform var(--motion-fast) var(--ease-standard); }
.btn:hover .arrow { transform: translateX(3px); }
.btn--lg { min-height: 52px; padding: var(--space-4) var(--space-7); border-radius: var(--radius-md); }
.btn--primary { background: var(--accent); color: var(--on-accent); box-shadow: var(--shadow-soft); }
.btn--primary:hover { background: var(--accent-hover); color: var(--on-accent); transform: translateY(-2px); box-shadow: var(--shadow-lift); }
.btn--primary:active { background: var(--accent-hover); transform: translateY(1px); }
.btn--secondary { border-color: var(--border-strong); color: var(--accent-ink); background: var(--surface); }
.btn--secondary:hover { background: var(--accent-quiet); color: var(--accent-ink); transform: translateY(-2px); }
.btn--quiet { color: var(--text-secondary); padding-inline: var(--space-3); }
.btn--quiet:hover { color: var(--text-primary); background: var(--accent-quiet); }
.btn[aria-disabled='true'] { opacity: 0.55; cursor: default; }
.btn--block { width: 100%; }

/* ---------- 2.12 Progress ---------- */

.progress { display: flex; flex-direction: column; gap: var(--space-2); }
.progress__track { display: flex; gap: 3px; }
.progress__seg { flex: 1 1 0; height: 6px; border-radius: var(--radius-full); background: var(--border); }
.progress__seg[data-done='true'] { background: var(--accent); }
.progress__text { font-size: var(--text-sm); color: var(--text-secondary); }

/* ---------- 2.13 Question card / 2.14 Answer option ---------- */

.flow { max-width: var(--width-content); margin-inline: auto; }
.question { padding-block: var(--space-6) var(--space-8); }
.question__text { margin-bottom: var(--space-6); }
.question__help { margin-top: calc(var(--space-4) * -1); margin-bottom: var(--space-6); color: var(--text-secondary); font-size: var(--text-sm); }
.options { display: flex; flex-direction: column; gap: var(--space-3); }
.option {
  position: relative; display: flex; align-items: flex-start; gap: var(--space-3);
  min-height: 44px; padding: var(--space-4);
  border: var(--border-control) solid var(--border); border-radius: var(--radius-md);
  background: var(--surface); cursor: pointer;
  transition: border-color var(--motion-fast) var(--ease-standard), background-color var(--motion-fast) var(--ease-standard);
}
.option:hover { border-color: var(--border-strong); }
.option input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.option__mark { flex: none; width: var(--icon-md); height: var(--icon-md); margin-top: 2px; border: var(--border-control) solid var(--border-strong); border-radius: var(--radius-full); display: grid; place-items: center; }
.option__mark::after { content: ''; width: 10px; height: 10px; border-radius: var(--radius-full); background: var(--accent); transform: scale(0); transition: transform var(--motion-fast) var(--ease-standard); }
.option--check .option__mark { border-radius: var(--radius-sm); }
.option--check .option__mark::after { border-radius: 2px; }
.option:has(input:checked) { border-width: var(--border-selected); border-color: var(--accent); background: var(--accent-quiet); }
.option:has(input:checked) .option__mark::after { transform: scale(1); }
.option:has(input:focus-visible) { outline: 2px solid var(--focus); outline-offset: 2px; }
.option:has(input:disabled) { opacity: 0.55; cursor: default; }
.option__text { font-size: var(--text-body); }
.option__tag { margin-left: var(--space-2); font-size: var(--text-xs); color: var(--text-muted); }

.flow__actions { display: flex; align-items: center; gap: var(--space-3); margin-top: var(--space-7); }
.flow__actions .btn--primary { margin-left: auto; }
@media (max-width: 479px) { .flow__actions .btn--primary { flex: 1 1 auto; } }

/* ---------- 2.18 Analysis ---------- */

.analysis { display: flex; flex-direction: column; align-items: center; gap: var(--space-5); padding-block: var(--space-11); text-align: center; }
.analysis__mark { display: flex; gap: var(--space-2); }
.analysis__dot { width: 10px; height: 10px; border-radius: var(--radius-full); background: var(--accent); opacity: 0.35; animation: lb-pulse 1.2s var(--ease-standard) infinite; }
.analysis__dot:nth-child(2) { animation-delay: 0.15s; }
.analysis__dot:nth-child(3) { animation-delay: 0.3s; }
@keyframes lb-pulse { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .analysis__dot { animation: none; opacity: 0.7; }
}

/* ---------- 2.19 Result ---------- */

.result { padding-block: var(--space-7) var(--space-9); }
/* The measure the reading is composed to at desktop widths. A role, not a component value. */
.reading { --width-reading: 52rem; }
.result__eyebrow { display: flex; align-items: center; gap: var(--space-3); }
.result__mark { width: var(--icon-lg); height: var(--icon-lg); flex: none; color: var(--family, var(--accent)); }
.result__interpretation { font-size: var(--text-body-lg); line-height: var(--lh-body-lg); max-width: var(--width-prose); }
.result__block { margin-top: var(--space-8); }
.result__block h2 { margin-bottom: var(--space-4); }

.result[data-family='Bright'] { --family: var(--family-bright); }
.result[data-family='Mixed'] { --family: var(--family-mixed); }
.result[data-family='Unclear'] { --family: var(--family-unclear); }
.result[data-family='Quiet'] { --family: var(--family-quiet); }
.result[data-family='Attention'] { --family: var(--family-attention); }
.result[data-family='archetype'] { --family: var(--accent); }
.result[data-family^='Lean'] { --family: var(--family-mixed); }
.result[data-tier='quiet'] { background: var(--surface-quiet); border-radius: var(--radius-lg); padding-inline: var(--space-5); }

/* ---------- 2.11 Signal strength, on the share card ---------- */

.strength__label { font-size: var(--text-sm); color: var(--text-secondary); }

/* ---------- 2.20 Signals ---------- */

.signals > li { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-3); padding-block: var(--space-3); border-bottom: var(--border-hairline) solid var(--border); }
.signals > li:last-child { border-bottom: 0; }
.tag { display: inline-flex; align-items: center; gap: var(--space-1); flex: none; padding: 2px var(--space-3); border-radius: var(--radius-full); border: var(--border-hairline) solid currentColor; font-size: var(--text-xs); font-weight: var(--weight-meta); }
.tag--positive { color: var(--positive); }
.tag--neutral { color: var(--neutral); }
.tag--caution { color: var(--caution); }
.tag::before { content: ''; width: 8px; height: 8px; background: currentColor; }
.tag--positive::before { border-radius: var(--radius-full); }
.tag--neutral::before { border-radius: 1px; height: 2px; width: 10px; }
.tag--caution::before { border-radius: 1px; transform: rotate(45deg); }
.signals__text { flex: 1 1 16rem; }

/* ---------- 2.21/2.22 Insight and guidance ---------- */

.insight p + p { margin-top: var(--space-4); }
.confidence { margin-top: var(--space-3); font-style: italic; font-size: var(--text-sm); color: var(--text-secondary); }

/* ---------- 2.24 Share ---------- */

.share { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.share__preview { padding: var(--space-5); border-radius: var(--radius-md); border: var(--border-hairline) solid var(--border); background: var(--surface); }
.share__preview p + p { margin-top: var(--space-2); }
.share details > summary { cursor: pointer; }

/* ---------- 2.25 Privacy note / disclaimer strip ---------- */

.note { font-size: var(--text-sm); color: var(--text-secondary); }
.strip { margin-top: var(--space-7); padding: var(--space-4) var(--space-5); border-radius: var(--radius-md); background: var(--surface-quiet); font-size: var(--text-sm); color: var(--text-secondary); }

/* ---------- 2.26 FAQ and disclosure ---------- */

.faq > li { border-bottom: var(--border-hairline) solid var(--border); }
.faq summary { display: flex; justify-content: space-between; gap: var(--space-4); padding-block: var(--space-4); cursor: pointer; font-weight: var(--weight-h3); font-size: var(--text-h3); line-height: var(--lh-h3); list-style: none; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: '+'; flex: none; color: var(--text-secondary); }
.faq details[open] summary::after { content: '\2212'; }
.faq details > div { padding-bottom: var(--space-4); max-width: var(--width-prose); color: var(--text-secondary); }
.disclosure { margin-top: var(--space-8); border: var(--border-hairline) solid var(--border); border-radius: var(--radius-md); padding: var(--space-2) var(--space-5); }
.disclosure summary { padding-block: var(--space-3); cursor: pointer; font-weight: var(--weight-h3); }

/* ---------- 2.27 Alert ---------- */

.alert { display: flex; gap: var(--space-3); padding: var(--space-4); border-radius: var(--radius-md); border: var(--border-hairline) solid var(--border); background: var(--surface); font-size: var(--text-sm); }
.alert--fault { border-color: var(--ui-error); }

/* ---------- Safety-first surface ---------- */
/* The product renders no resource directory, so no chooser, list or card style exists here. */

.safety { background: var(--surface-quiet); border-radius: var(--radius-lg); padding: var(--space-6) var(--space-5); }
.safety h2 { color: var(--text-primary); }

/* ---------- 2.29 Empty state ---------- */

.empty { padding: var(--space-7); border-radius: var(--radius-md); border: var(--border-hairline) dashed var(--border); text-align: center; color: var(--text-secondary); }

/* ---------- Breadcrumb ---------- */

.crumbs { display: flex; flex-wrap: wrap; gap: var(--space-2); padding-block: var(--space-4); font-size: var(--text-sm); color: var(--text-secondary); }
.crumbs a { color: var(--text-secondary); text-decoration: none; }
.crumbs a:hover { color: var(--text-primary); text-decoration: underline; }
.crumbs li + li::before { content: '/'; margin-right: var(--space-2); color: var(--text-muted); }
/* Each crumb is a flex row holding the separator and the link. The link carries a 44px minimum
   for the thumb, so without this the separator — a stretched flex item — paints its glyph at the
   top of that 44px while the link centres its own text, and the slash floats about twelve pixels
   high. Centring the row puts both on one line; no offset is involved. */
.crumbs li { display: inline-flex; align-items: center; }

/* ---------- Utilities ---------- */

[hidden] { display: none !important; }
.center { text-align: center; }

/* ---------- 2.11 Start panel, sticky variant ---------- */

.start-panel { transition: none; }
.start-panel[data-stuck] {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  margin: 0; padding: var(--space-3) var(--edge) calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
  background: var(--surface-raised); box-shadow: var(--shadow-1);
  border-top: var(--border-hairline) solid var(--border);
}
.start-panel[data-stuck] .btn { max-width: var(--width-content); margin-inline: auto; }

/* ============================================================================
 * Homepage — the LoveBeat editorial layer.
 *
 * Everything below is scoped to the homepage (`body.is-home`) or to classes that only the
 * homepage template emits, so the hub, category, calculator and document pages keep their current
 * presentation. Declarations run base first, then components, then the breakpoints in ascending
 * order, so the widest matching rule is always the one that wins.
 * ========================================================================== */

/* ---------- Editorial type and decoration ---------- */

.t-editorial {
  font-family: var(--font-display);
  font-size: var(--text-h2); line-height: var(--lh-h2);
  font-weight: 700; letter-spacing: -0.015em; text-wrap: balance;
}
.display { letter-spacing: -0.025em; text-wrap: balance; }
.display .accent { color: var(--accent-ink); }

.flourish { display: inline-grid; place-items: center; width: 0.7em; height: 0.7em; margin-left: 0.35em; color: var(--accent); vertical-align: baseline; }
.flourish .icon { width: 100%; height: 100%; }

/* A handwritten-style aside. Decorative only — it never carries information of its own. */
.quill {
  font-family: var(--font-display); font-style: italic;
  font-size: var(--text-sm); line-height: 1.45; color: var(--text-muted);
  max-width: 19ch; transform: rotate(-2.5deg);
}
.quill--hero, .quill--hero-2, .quill--moods { display: none; }

.link-quiet {
  display: inline-flex; align-items: center; gap: var(--space-2);
  min-height: 44px; color: var(--accent-ink); font-weight: var(--weight-meta);
  text-underline-offset: 4px;
}
.link-quiet:hover { color: var(--accent-hover); }
.link-quiet .arrow { display: inline-grid; place-items: center; width: var(--icon-md); height: var(--icon-md); transition: transform var(--motion-fast) var(--ease-standard); }
.link-quiet:hover .arrow { transform: translateX(3px); }

/* ---------- Section rhythm ---------- */

/*
 * One rhythm between sections, not two: a plain band carries its space below itself, and only a
 * tinted band adds space above so its colour has room to breathe.
 */
.band { padding-block: 0 var(--rhythm); }
.band--steps { padding-block: calc(var(--rhythm) * 0.42) calc(var(--rhythm) * 0.48); background: var(--wash-cream); border-block: var(--border-hairline) solid var(--border-soft); }
.band--moods { position: relative; }
.band--close { position: relative; padding-top: var(--space-9); }
.band__head { position: relative; margin-bottom: var(--space-7); }
.band__head--row { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--space-4); }
.band__after { margin-top: var(--space-7); }

/* ---------- Hero ---------- */

.is-home .hero {
  position: relative; overflow: hidden;
  padding-block: var(--space-6) calc(var(--rhythm) / 2);
  /* The warm room the hero sits in. Soft blush at the top, settling into the page ground. */
  background: linear-gradient(170deg, var(--wash-blush) 0%, var(--wash-cream) 52%, var(--background) 100%);
  border-bottom-left-radius: var(--radius-lg); border-bottom-right-radius: var(--radius-lg);
}
.hero__grid { position: relative; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-8); align-items: center; }
.hero__copy { position: relative; z-index: 1; }
.hero__lede { margin-top: var(--space-5); color: var(--text-secondary); max-width: 46ch; }
.is-home .hero .eyebrow { color: var(--accent-ink); }
.is-home .hero__chips { margin-top: var(--space-7); gap: var(--space-3); }
.is-home .hero__actions { margin-top: var(--space-8); gap: var(--space-5); }

.is-home .hero__chips .chip {
  gap: var(--space-3); padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md); border-color: var(--border-soft);
  background: var(--surface); box-shadow: var(--shadow-soft); align-items: center;
}
.chip__icon { display: grid; place-items: center; width: 34px; height: 34px; flex: none; border-radius: var(--radius-full); background: var(--wash-blush); color: var(--accent-ink); }
.chip__text { display: flex; flex-direction: column; line-height: 1.25; }
.chip__label { font-size: var(--text-sm); font-weight: var(--weight-h3); color: var(--text-primary); }
.chip__sub { font-size: var(--text-xs); color: var(--text-muted); }

/* The hero scene. Shapes only, so the page still ships no image and makes no request — and every
   fill is a token, so the whole illustration follows the theme into dark mode. */
.hero__art { position: relative; justify-self: center; width: 100%; max-width: 520px; }
/* Stacked, the artwork fills the column and no more: its edges sit on the same boundary the text
   above it uses, so the hero lines up with every band below. */
@media (max-width: 1023px) {
  .hero__art { width: 100%; max-width: 100%; margin-inline: 0; }
}
.hero-scene { display: block; width: 100%; height: auto; }
.hero-scene--img { border-radius: var(--radius-lg); object-fit: contain; }

.hs__window { fill: var(--art-window); }
.hs__pane { stroke: var(--art-pane); stroke-width: 6; stroke-linecap: round; }
.hs__leaf { fill: var(--art-leaf); }
.hs__leaf-soft { fill: var(--art-leaf-soft); }
.hs__pot { fill: var(--art-wood); }
.hs__heart-wash { fill: var(--art-heart-wash); }

.hs__hair { fill: var(--art-hair); }
.hs__hair-dark { fill: var(--art-hair-dark); }
.hs__skin { fill: var(--art-skin); }
.hs__skin-shade { fill: var(--art-skin-shade); }
.hs__eye { fill: var(--art-line); }
.hs__wink, .hs__smile { fill: none; stroke: var(--art-line); stroke-width: 3.2; stroke-linecap: round; }
.hs__cheek { fill: var(--art-sweater-shade); opacity: 0.75; }
.hs__sweater { fill: var(--art-sweater); }
.hs__sweater-shade, .hs__sleeve { fill: var(--art-sweater-shade); }
.hs__hand-line { stroke: var(--art-skin-shade); stroke-width: 2.4; stroke-linecap: round; }

.hs__table { fill: var(--art-wood); }
.hs__table-edge { stroke: var(--art-skin-shade); stroke-width: 2; opacity: 0.5; }
.hs__cuff { fill: var(--art-sweater); }
.hs__mug { fill: var(--surface); stroke: var(--border-soft); stroke-width: 2; }
.hs__mug-handle { stroke: var(--border-strong); stroke-width: 5; fill: none; stroke-linecap: round; }
.hs__mini-heart { fill: var(--accent); }

.hs__book-a { fill: var(--art-book-a); }
.hs__book-b { fill: var(--art-book-b); }
.hs__book-c { fill: var(--art-book-c); }
.hs__page { stroke: var(--surface); stroke-width: 3; stroke-linecap: round; opacity: 0.85; }

.hs__cat-body, .hs__cat-head, .hs__cat-ear { fill: var(--art-cat); }
.hs__cat-patch { fill: var(--art-cat-dark); }
.hs__cat-line, .hs__cat-eye, .hs__cat-tail {
  fill: none; stroke: var(--art-cat-dark); stroke-width: 2.4; stroke-linecap: round;
}
.hs__cat-tail { stroke-width: 7; }

.hs__spark { fill: var(--mark-ex-breakup); }

@media (prefers-reduced-motion: no-preference) {
  .hs__mini-heart { transform-box: fill-box; transform-origin: center; animation: lb-beat 3.6s var(--ease-standard) infinite; }
  .hs__heart-wash { transform-box: fill-box; transform-origin: center; animation: lb-drift 11s ease-in-out infinite; }
}
@keyframes lb-beat { 0%, 88%, 100% { transform: scale(1); } 92% { transform: scale(1.05); } 96% { transform: scale(1.02); } }
@keyframes lb-drift { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }

/* ---------- "Where are you right now?" — six mini-worlds ---------- */

.moods { display: grid; gap: var(--space-4); }
/*
 * Each situation is a person before it is a category.
 *
 * The card used to be a tinted panel with an icon at the top; the tint now becomes a banner and
 * carries the drawing that category's own landing page already uses, so the reader recognises the
 * page before they arrive at it. The body goes white underneath, which is what gives the drawing
 * a ground of its own instead of a wash behind the type.
 */
.mood__card {
  position: relative; height: 100%; gap: 0; padding: 0; overflow: hidden;
  border-radius: var(--radius-lg);
  background: var(--surface); border: var(--border-hairline) solid var(--border-soft);
  box-shadow: var(--shadow-soft);
  transition: transform var(--motion-base) var(--ease-standard),
    box-shadow var(--motion-base) var(--ease-standard);
}
.mood__card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lift); border-color: var(--border-soft); }

/* The banner. Sized from each file's own ink, exactly as the featured cards are, so six drawings
   with six different transparent margins stand at the same height on the same line. */
/*
 * Four to three, not five to four. The six drawings run up to about 1.31 wide for every 1 tall
 * once their transparent margins are discounted, so a narrower banner took the edge off three of
 * them. At four to three every one of the six stands at full height inside its own banner with
 * nothing cropped, and the width guard below catches anything wider added later.
 */
.mood__art {
  position: relative; display: block; flex: none;
  aspect-ratio: 4 / 3; background: var(--tint); overflow: hidden;
}
/*
 * Four to three is a ratio, and a ratio grows with the card.
 *
 * Six cards stacked one under another on a phone are as wide as the screen, so the same ratio that
 * gives the drawing 130px beside five neighbours gives it 267px alone — and the homepage grows by
 * about the height of a screen for it. Below the three-column layout the banner stops at 210px
 * instead, which is still three fifths of the card's width and taller than the drawing stands on
 * any desktop. The picture keeps its shape and its full height inside that banner: only the pastel
 * beside it gets wider. From 1024px up nothing changes at all.
 */
@media (max-width: 1023px) {
  .mood__art { max-height: 210px; }
}
.mood__art picture { display: block; height: 100%; }
.mood__art-img {
  display: block; width: auto;
  height: calc(100% / var(--art-fill, 1));
  max-width: calc(100% / var(--art-fill-w, 1));
  position: absolute; inset-block-start: 50%; inset-inline-start: 50%;
  translate: calc(-50% + var(--art-shift-x, 0%)) calc(-50% + var(--art-shift, 0%));
  object-fit: contain;
}
.mood__art-img[src$="artwork-15.png"] { --art-fill: 0.964; --art-fill-w: 0.928; --art-shift: 0.4%; --art-shift-x: -1.4%; }
.mood__art-img[src$="artwork-27.png"] { --art-fill: 0.9671; --art-fill-w: 0.9762; --art-shift: 1.6%; --art-shift-x: 0.1%; }
.mood__art-img[src$="artwork-33.png"] { --art-fill: 0.9123; --art-fill-w: 0.9689; --art-shift: 2.9%; --art-shift-x: 1.6%; }
.mood__art-img[src$="artwork-17.png"] { --art-fill: 0.9386; --art-fill-w: 0.9762; --art-shift: 1.3%; --art-shift-x: 1.2%; }
.mood__art-img[src$="artwork-43.png"] { --art-fill: 0.9962; --art-fill-w: 0.9854; --art-shift: 0.2%; --art-shift-x: -0.3%; }
.mood__art-img[src$="artwork-20.png"] { --art-fill: 0.9167; --art-fill-w: 1; --art-shift: -0.2%; }

.mood__body { display: flex; flex-direction: column; gap: var(--space-2); flex: 1 1 auto; padding: var(--space-5); }
.mood__head { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-1); }
.mood__icon {
  display: grid; place-items: center; width: 36px; height: 36px; flex: none;
  border-radius: var(--radius-full); background: var(--tint); color: var(--mark);
  transition: transform var(--motion-base) var(--ease-standard);
}
.mood__card:hover .mood__icon { transform: translateY(-2px); }
.mood__icon .icon { width: var(--icon-md); height: var(--icon-md); }
.mood__eyebrow { font-size: var(--text-xs); letter-spacing: 0.09em; text-transform: uppercase; font-weight: var(--weight-meta); color: var(--mark); }
.mood__title { font-family: var(--font-display); letter-spacing: -0.01em; }
.mood__note { color: var(--text-secondary); }
.mood__meta { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-top: auto; padding-top: var(--space-5); color: var(--accent-ink); font-weight: var(--weight-meta); }

.mood[data-mood='crush'] { --tint: var(--tint-crush); --mark: var(--mark-crush); }
.mood[data-mood='dating'] { --tint: var(--tint-dating); --mark: var(--mark-dating); }
.mood[data-mood='relationship'] { --tint: var(--tint-relationship); --mark: var(--mark-relationship); }
.mood[data-mood='relationship-health'] { --tint: var(--tint-relationship-health); --mark: var(--mark-relationship-health); }
.mood[data-mood='ex-breakup'] { --tint: var(--tint-ex-breakup); --mark: var(--mark-ex-breakup); }
.mood[data-mood='fun'] { --tint: var(--tint-fun); --mark: var(--mark-fun); }

/* ---------- "People are wondering…" ---------- */

.features { display: grid; gap: var(--space-5); }
.feature__card {
  display: flex; flex-direction: column; height: 100%;
  border-radius: var(--radius-lg); overflow: hidden;
  background: var(--surface); border: var(--border-hairline) solid var(--border-soft);
  box-shadow: var(--shadow-soft); text-decoration: none; color: var(--text-primary);
  transition: transform var(--motion-base) var(--ease-standard),
    box-shadow var(--motion-base) var(--ease-standard);
}
.feature__card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lift); color: var(--text-primary); }
.feature__art { position: relative; display: block; aspect-ratio: 32 / 15; background: var(--art-bg); overflow: hidden; }
.feature__art .art { display: block; width: 100%; height: 100%; }

/*
 * A character in the banner.
 *
 * The drawings are close to square and the banner is more than twice as wide, so neither fitting
 * the box nor filling it is right: `cover` would take the top of a head off, `contain` with the
 * width would leave the figure small in a wide pastel band. The image takes the banner's height
 * instead and keeps its own width, which lands the character in the middle of the ground with the
 * pastel running out to both edges.
 *
 * Height alone is not the same as presence. Each file carries its own transparent margin, so a
 * drawing with a wide one renders smaller than its neighbour at the same box height. `--art-fill`
 * is the share of the file's height its ink actually occupies, measured from the alpha channel,
 * and dividing by it makes every character the same height on screen. `--art-shift` moves a file
 * whose ink sits off-centre, as a share of that rendered height. Both default to no correction, so
 * a drawing added later renders sensibly before anyone measures it.
 */
.feature__art picture { display: block; height: 100%; }
.feature__art-img {
  display: block; width: auto;
  height: calc(100% / var(--art-fill, 1));
  /* Insurance rather than correction: if a drawing's ink were ever wider than the banner, this
     stops it running off the sides. None of the files here reaches it. */
  max-width: calc(100% / var(--art-fill-w, 1));
  position: absolute; inset-block-start: 50%; inset-inline-start: 50%;
  translate: calc(-50% + var(--art-shift-x, 0%)) calc(-50% + var(--art-shift, 0%));
  object-fit: contain;
}
/* Measured from each file's alpha channel: ink height as a share of canvas height, then the ink
   centre's offset from the canvas centre. Only the drawings this section uses are listed. */
.feature__art-img[src$="artwork-11.png"] { --art-fill: 0.9715; --art-fill-w: 0.9415; --art-shift: 0.1%; --art-shift-x: 1.1%; }
.feature__art-img[src$="artwork-44.png"] { --art-fill: 0.9959; --art-fill-w: 1; --art-shift: 0.2%; }
.feature__art-img[src$="artwork-26.png"] { --art-fill: 0.8309; --art-fill-w: 0.9771; --art-shift: 6.5%; --art-shift-x: -0.2%; }
.feature__art-img[src$="artwork-18.png"] { --art-fill: 0.9581; --art-fill-w: 0.9771; --art-shift: 0.9%; }
.feature__body { display: flex; flex-direction: column; gap: var(--space-2); flex: 1 1 auto; padding: var(--space-5); }
.feature__badge { align-self: flex-start; padding: var(--space-1) var(--space-3); border-radius: var(--radius-full); background: var(--accent); color: var(--on-accent); font-size: var(--text-xs); font-weight: var(--weight-meta); }
.feature__title { font-family: var(--font-display); font-size: var(--text-h3); line-height: var(--lh-h3); font-weight: 700; letter-spacing: -0.01em; }
.feature__blurb { font-size: var(--text-sm); color: var(--text-secondary); }
.feature__meta { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-top: auto; padding-top: var(--space-4); font-size: var(--text-xs); color: var(--text-muted); }
.feature__meta .arrow { display: inline-grid; place-items: center; width: var(--icon-md); height: var(--icon-md); color: var(--accent-ink); transition: transform var(--motion-fast) var(--ease-standard); }
.feature__card:hover .arrow { transform: translateX(3px); }

/* One mood per card, mixed from the same pastel palette as the categories. */
.feature__art[data-art='1'] { --art-bg: var(--wash-blush); --blob-a: var(--tint-crush); --blob-b: var(--wash-peach); --art-mark: var(--mark-crush); --art-spark: var(--mark-ex-breakup); }
.feature__art[data-art='2'] { --art-bg: var(--wash-peach); --blob-a: var(--wash-butter); --blob-b: var(--tint-dating); --art-mark: var(--mark-dating); --art-spark: var(--mark-crush); }
.feature__art[data-art='3'] { --art-bg: var(--wash-lavender); --blob-a: var(--tint-relationship); --blob-b: var(--wash-blush); --art-mark: var(--mark-relationship); --art-spark: var(--mark-relationship); }
.feature__art[data-art='4'] { --art-bg: var(--wash-mint); --blob-a: var(--tint-fun); --blob-b: var(--wash-butter); --art-mark: var(--mark-fun); --art-spark: var(--mark-ex-breakup); }

.art__blob--a { fill: var(--blob-a); }
.art__blob--b { fill: var(--blob-b); }
.art__mark { fill: var(--art-mark); }
.art__mark--soft { opacity: 0.5; }
.art__spark { fill: var(--art-spark); }
.art__bubble { fill: var(--surface); stroke: var(--border-soft); stroke-width: 1.5; }
.art__bubble--fade { opacity: 0.4; }
.art__dot { fill: var(--art-mark); opacity: 0.65; }
.art__trail { fill: var(--art-mark); opacity: 0.45; }
.art__trail--fade { opacity: 0.2; }
.art__ring { fill: none; stroke: var(--art-mark); stroke-width: 1.5; opacity: 0.35; }
.art__ring--fade { opacity: 0.18; }

/* ---------- "How LoveBeat works" ---------- */

.steps { display: grid; gap: var(--space-7); }
.step { position: relative; }

/*
 * The three steps, as a small journey.
 *
 * Each step is a card now: a drawing over the words, on the pastel ground the rest of the homepage
 * uses, with a heart in the gap before the next one. The drawing is sized from its own measured
 * ink rather than its canvas — `--art-fill` is the share of the file the ink occupies and the
 * offsets centre that ink — so three files with three different transparent margins stand at the
 * same height on the same line. Everything here is scoped to `.steps`, because `.step` is also the
 * reading's own "Where this leaves you" panel and that one is not this.
 */
/*
 * `padding: 0` is the whole point of this rule, not a detail of it.
 *
 * `.step` is also the reading's own "Where this leaves you" panel, and that one is a padded panel
 * with its text set directly on it. This card is not: its drawing wants the card's own top edge and
 * its words carry their padding on the panel beneath. Inheriting the panel's padding held the
 * banner forty pixels below the card's top and thirty-two in from its sides, and cost every card
 * eighty pixels of height for space that was never composed. Scoped to `.steps`, so the reading's
 * panel keeps every value it has.
 */
.steps .step {
  display: flex; flex-direction: column; padding: 0;
  border-radius: var(--radius-lg); background: var(--surface);
  border: var(--border-hairline) solid var(--border-soft); box-shadow: var(--shadow-soft);
}
/* The banner rounds its own top corners rather than being clipped by the card, because the card
   has to let the joint out into the gap beside it. */
.steps .step__art {
  position: relative; display: block; flex: none;
  aspect-ratio: 3 / 2; max-height: var(--step-art-max, 240px);
  background: var(--step-tint, var(--wash-blush)); overflow: hidden;
  border-start-start-radius: var(--radius-lg); border-start-end-radius: var(--radius-lg);
}
.steps .step__art picture { display: block; height: 100%; }
.steps .step__art-img {
  display: block; width: auto;
  height: calc(100% / var(--art-fill, 1));
  max-width: calc(100% / var(--art-fill-w, 1));
  position: absolute; inset-block-start: 50%; inset-inline-start: 50%;
  translate: calc(-50% + var(--art-shift-x, 0%)) calc(-50% + var(--art-shift, 0%));
  object-fit: contain;
}
.steps .step__art-img[src$="artwork-49.png"] { --art-fill: 0.9839; --art-fill-w: 0.994; --art-shift: 0.8%; --art-shift-x: 0.1%; }
.steps .step__art-img[src$="artwork-11.png"] { --art-fill: 0.9715; --art-fill-w: 0.9415; --art-shift: 0.1%; --art-shift-x: 1.1%; }
.steps .step__art-img[src$="artwork-31.png"] { --art-fill: 0.9715; --art-fill-w: 0.8464; --art-shift: 0.6%; --art-shift-x: -3.7%; }

/* One pastel per step, in the order the situation cards already read in. */
.steps .step:nth-child(1) { --step-tint: var(--wash-blush); }
.steps .step:nth-child(2) { --step-tint: var(--wash-lavender); }
.steps .step:nth-child(3) { --step-tint: var(--wash-mint); }

.steps .step__panel { display: flex; flex-direction: column; gap: var(--space-2); flex: 1 1 auto; padding: var(--space-5); }
.steps .step__head { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-1); }
.steps .step__n { margin-bottom: 0; }
.steps .step__icon { margin-left: 0; margin-bottom: 0; }
.steps .step__title { margin-top: 0; }
.steps .step__body { max-width: none; }

/*
 * The joint between two steps: a dotted run with a heart sitting on it.
 *
 * Stacked, it stands in the gap above the card; side by side it turns and stands in the gap
 * beside it. It is drawn from the page's own ground so the line appears to pass behind the heart,
 * and the first step never shows one because nothing comes before it.
 */
.steps .step__joint {
  position: absolute; z-index: 1; display: grid; place-items: center;
  width: 26px; height: 26px; color: var(--accent);
  inset-block-start: calc(var(--space-7) / -2); inset-inline-start: 50%;
  translate: -50% -50%;
}
.steps .step:first-child .step__joint { display: none; }
/* Two across, the third step starts a second row and a line between cards would say the wrong
   thing about the order, so the joint waits for a layout it can be honest in. */
@media (min-width: 560px) and (max-width: 1023px) {
  .steps .step__joint { display: none; }
}
.steps .step__joint .icon { width: var(--icon-md); height: var(--icon-md); }
.steps .step__joint::before {
  content: ''; position: absolute; z-index: -1;
  inset-block: calc(var(--space-7) / -2); inset-inline-start: 50%;
  border-left: 2px dotted var(--border-strong); opacity: 0.5;
}
.steps .step__joint::after {
  content: ''; position: absolute; z-index: -1; inset: -3px;
  border-radius: var(--radius-full); background: var(--background);
}
.step__n {
  display: inline-grid; place-items: center; vertical-align: middle;
  width: 42px; height: 42px; margin-bottom: var(--space-4);
  border-radius: var(--radius-full); background: var(--surface);
  border: var(--border-hairline) solid var(--border-soft); box-shadow: var(--shadow-soft);
  font-family: var(--font-display); font-size: var(--text-body); font-weight: 700; color: var(--accent-ink);
}
.step__icon { display: inline-grid; place-items: center; width: 34px; height: 34px; vertical-align: middle; margin-left: var(--space-3); margin-bottom: var(--space-4); border-radius: var(--radius-sm); background: var(--wash-blush); color: var(--accent-ink); }
.step__title { margin-top: var(--space-1); font-family: var(--font-display); font-size: var(--text-h3); line-height: var(--lh-h3); font-weight: 700; }
.step__body { margin-top: var(--space-2); color: var(--text-secondary); max-width: 32ch; }

/* A handwritten phrase the supplied artwork already carries: still in the document, no longer on
   screen. Specific enough to beat the placement rules further down the sheet. */
.quill.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* ---------- Brand manifesto ---------- */

.manifesto { max-width: 900px; margin-inline: auto; text-align: center; }
.manifesto__line { font-size: var(--text-display); line-height: var(--lh-display); letter-spacing: -0.03em; }
.manifesto__lede { margin: var(--space-5) auto 0; font-size: var(--text-body-lg); line-height: var(--lh-body-lg); color: var(--text-secondary); max-width: 40ch; text-wrap: pretty; }
.manifesto__grid { display: grid; gap: var(--space-6); margin-top: var(--space-8); text-align: center; }
.manifesto__grid li { padding-top: var(--space-4); border-top: var(--border-hairline) solid var(--border); }
.manifesto__key { display: block; font-family: var(--font-display); font-size: var(--text-h3); font-weight: 700; }
.manifesto__val { display: block; margin: var(--space-2) auto 0; max-width: 30ch; font-size: var(--text-sm); color: var(--text-secondary); }
.manifesto__note { margin-top: var(--space-8); }

/* ---------- Closing call to action ---------- */

.closer { position: relative; text-align: center; padding: var(--space-10) var(--space-5); border-radius: var(--radius-xl); background: var(--wash-blush); overflow: hidden; }
.closer__title { font-size: var(--text-h1); line-height: var(--lh-h1); }
.closer__lede { margin: var(--space-4) auto 0; max-width: 42ch; color: var(--text-secondary); font-size: var(--text-body-lg); line-height: var(--lh-body-lg); text-wrap: pretty; }
.closer__actions { margin-top: var(--space-8); justify-content: center; }
.quill--closer { margin-inline: auto; margin-bottom: var(--space-5); max-width: 24ch; color: var(--accent-ink); }
.closer__petals { position: absolute; inset-block-start: var(--space-5); inset-inline-end: var(--space-5); display: flex; gap: var(--space-3); color: var(--accent); opacity: 0.28; pointer-events: none; }
.closer__petals .icon:nth-child(2) { align-self: flex-end; }

/*
 * The two card sets below the desktop layout.
 *
 * A drawing beside five neighbours is a detail of a row; the same drawing alone on a phone is the
 * card. Stacked, it pushed the words down a screen and gave the reader a picture to scroll past
 * before reaching the thing they came for, so below the width where the cards sit side by side the
 * banner goes entirely — not hidden behind the words or shrunk, but out of the layout, with no
 * space kept for it. What is left is the card as text: the label, the title, the line under it and
 * the count.
 *
 * The card also stops growing with the screen. A line of body text across a 430px card is wider
 * than it is comfortable to read, and a card that reaches both edges has nothing to sit in, so the
 * card holds at 340px and centres, leaving the page's own gutter either side. On the narrowest
 * phones the gutter decides and the cap never binds.
 *
 * From 1024px up nothing here applies: both sets keep the drawings and the proportions approved
 * for them.
 */
@media (max-width: 1023px) {
  .feature__art, .mood__art { display: none; }
  .features > li, .moods > .mood { justify-self: center; width: 100%; }
  /* Less above and below than beside: the side padding is what keeps the text off the card's edge,
     the vertical padding only spaces four short lines, so it draws in and the card loses the band
     of empty ground it carried at the top and foot. */
  .feature__body, .mood__body { padding: var(--space-4) var(--space-5); gap: var(--space-2); }
  /* The meta row is pushed to the foot of a card the drawing used to make tall. With the drawing
     gone there is no height to fill, so it follows the text instead of floating away from it. */
  .feature__meta, .mood__meta { margin-top: 0; padding-top: var(--space-2); }
  .mood__head { margin-bottom: 0; }
  /* One rhythm between the cards, closer than the drawing-led rows needed. */
  .features, .moods { gap: var(--space-3); }
}
/*
 * The cap is for the width where one card is the whole row.
 *
 * A single card spanning a 430px phone sets a line of body text wider than it is comfortable to
 * read and leaves nothing for it to sit in, so it holds at 340px and centres. Where the grid
 * already puts two cards side by side the columns decide, which is why each set takes the cap only
 * below its own two-column step: 560px for the featured cards, 480px for the situations. Narrower
 * than 340 was measured and rejected — nothing rewrapped, but the cards pull further out of line
 * with the section heading and the rows above and below them, which all run the full measure.
 */
@media (max-width: 559px) { .features > li { max-width: 340px; } }
@media (max-width: 479px) { .moods > .mood { max-width: 340px; } }

/* ---------- Breakpoints, ascending ---------- */

/* Nothing on the homepage may force a horizontal scroll, down to 320px and at 200% zoom. */
@media (max-width: 359px) {
  .step__n { display: grid; margin-bottom: var(--space-3); }
  .step__icon { display: none; }
  .closer { padding-inline: var(--space-4); }
}

@media (max-width: 420px) {
  .btn--lg { padding-inline: var(--space-4); }
  .is-home .hero__actions .btn, .closer__actions .btn { width: 100%; }
  .is-home .hero__actions, .closer__actions { gap: var(--space-4); }
  /* On a narrow phone the reassurance row stacks, so the hero tightens to keep the first
     call to action inside the first screen rather than below it. */
  .is-home .hero { padding-block: var(--space-4) var(--space-8); }
  .is-home .hero__chips { margin-top: var(--space-5); gap: var(--space-2); }
  .is-home .hero__chips .chip { padding: var(--space-2) var(--space-3); }
  .is-home .hero__actions { margin-top: var(--space-6); }
  .hero__grid { gap: var(--space-6); }
  .hero__lede { margin-top: var(--space-4); }
}

@media (min-width: 480px) {
  .moods { grid-template-columns: repeat(2, 1fr); }
}

/*
 * Two steps across, then three.
 *
 * Three across before the page is a thousand pixels wide left each card about two hundred, and a
 * drawing in a card that narrow is a stamp rather than a character. Two carry the tablet range and
 * the third opens the second row, which is the arrangement the rest of the homepage uses.
 */
/*
 * A ratio grows with the card, and a stacked card is as wide as the phone.
 *
 * Three to two gives the drawing 190px beside two neighbours and 216px alone, and three of those
 * one under another cost the homepage most of a screen. Stacked, the banner stops at 165px, which
 * is still the height the "People are wondering" drawings stand at on the same phone; two across
 * it stops a little higher; three across the ratio never reaches either ceiling, so the desktop
 * cards are untouched.
 */
.steps { --step-art-max: 165px; }
@media (max-width: 1023px) {
  .steps { gap: var(--space-6); }
}
@media (min-width: 560px) {
  .steps { grid-template-columns: repeat(2, 1fr); --step-art-max: 190px; }
}
@media (min-width: 1024px) {
  .steps { grid-template-columns: repeat(3, 1fr); gap: var(--space-8); }
  /* Side by side the joint turns: the dotted run crosses the gap and the heart sits on it. */
  .steps .step__joint { inset-block-start: 50%; inset-inline-start: calc(var(--space-8) / -2); }
  .steps .step__joint::before {
    inset-block: auto; inset-inline: calc(var(--space-8) / -2); inset-block-start: 50%;
    border-left: 0; border-top: 2px dotted var(--border-strong);
  }
}

@media (min-width: 560px) {
  .features { grid-template-columns: repeat(2, 1fr); }
  .is-home .hero__chips { flex-wrap: nowrap; }
}

@media (min-width: 768px) {
  .chip__label { white-space: nowrap; }
  .is-home .hero { padding-block: var(--space-6) calc(var(--rhythm) / 2); }

  .manifesto__grid { grid-template-columns: repeat(3, 1fr); }
  .closer { padding: var(--space-11) var(--space-8); }
}

@media (min-width: 1024px) {
  .is-home .hero { padding-block: var(--space-7) calc(var(--rhythm) / 2); }
  /* The copy keeps the page's own left edge, so the hero still lines up with the header and with
     every band below it. Only the artwork leaves the grid: it runs out to the screen edge on the
     right, which is where the extra size comes from. */
  /* A small laptop has no width to spare: the artwork grows only a little here, so the
     reassurance row and both calls to action keep their single line. */
  .hero__grid { grid-template-columns: minmax(0, 1.04fr) minmax(0, 0.96fr); gap: var(--space-7); }
  .hero__art {
    /* Anchored right, grown left. `justify-self: end` pins the right edge to the end of the
       column — the page's own content boundary, the line the header and every band below end on —
       and the width then reaches back over the copy column rather than out past that boundary.
       Reaching back is safe because the artwork carries a tenth of its width as transparent margin
       on the left, so its first ink still lands clear of the copy; the copy sits on z-index 1
       above it in any case. */
    justify-self: end; width: 490px; max-width: none; margin-inline: 0;
  }
  .display { font-size: 3.5rem; }
  .t-editorial { font-size: 2.25rem; }
  .manifesto__line { font-size: 3.25rem; }
  .moods { grid-template-columns: repeat(3, 1fr); }
  .features { grid-template-columns: repeat(4, 1fr); }
  .quill--hero, .quill--hero-2, .quill--moods { display: block; position: absolute; }
  .quill--hero { inset-block-start: 6%; inset-inline-end: 2%; max-width: 13ch; text-align: center; color: var(--accent-ink); }
  .quill--hero-2 {
    inset-block-end: 28%; inset-inline-end: 41%; max-width: 15ch; text-align: right;
    color: var(--accent-ink); transform: rotate(-4deg);
  }
  .quill--moods { inset-block-start: 0; inset-inline-end: var(--edge); max-width: 22ch; text-align: right; transform: rotate(-1.5deg); }
}

/* Between the navigation breakpoint and the full page width the header earns its single row. */
@media (min-width: 1280px) {
  /* Wide enough to give the artwork real size. The copy keeps a comfortable measure, and the
     reassurance notes tighten so they stay on one line beside it. */
  .hero__grid { grid-template-columns: minmax(30rem, 1fr) minmax(0, 1.25fr); }
  .hero__art { width: 690px; }
  .is-home .hero__chips { gap: var(--space-2); }
  .is-home .hero__chips .chip { padding: var(--space-3); gap: var(--space-2); }
  .is-home .hero__chips .chip__icon { width: 30px; height: 30px; }
}

/* Six mini-worlds in one row: the eyebrow keeps a two-line well so every title starts level. */
@media (min-width: 1200px) {
  .display { font-size: var(--text-display); }
  .moods { grid-template-columns: repeat(6, 1fr); gap: var(--space-4); }
  .mood__body { padding: var(--space-4) var(--space-4) var(--space-5); }
  .mood__head { gap: var(--space-2); }
  .mood__icon { width: 30px; height: 30px; }
  .mood__icon .icon { width: var(--icon-sm); height: var(--icon-sm); }
  .mood__eyebrow { min-height: 2.9em; letter-spacing: 0.04em; }
  .mood__title { font-size: var(--text-body-lg); line-height: 1.25; }
}

/* ============================================================================
 * The reading — the LoveBeat editorial layer on a result.
 *
 * Every colour below resolves through the calculator's own palette (--r-wash, --r-tint, --r-mark,
 * --r-ink in tokens.css), so the nineteen readings each look like themselves. The palette is
 * decorative: --family still carries the mark that means something, and no colour here encodes a
 * valence, a score or a direction.
 * ========================================================================== */

.glyph { display: inline-grid; place-items: center; flex: none; }
.glyph svg { width: 100%; height: 100%; display: block; }

.reading .result__eyebrow .eyebrow { color: var(--r-ink); }
.reading__headline { font-family: var(--font-display); letter-spacing: -0.02em; text-wrap: balance; margin: 0; }
.reading .result__interpretation { color: var(--text-secondary); }

/*
 * The visual result layer.
 *
 * One block, between the reading's name and its interpretation, and it differs by mode. Every
 * shape here is decorative and hidden from assistive technology; the word beside it is the
 * accessible text. Nothing draws a point, a bar, a number out of five, or a distance.
 */

/*
 * A decision reading's own bands, as stops. They are laid out as separate chips rather than along
 * a line, because the engine reaches a branch: there is no distance between two stops to read.
 */
.stops { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.stop {
  display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
  max-width: 100%; padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-lg);
  border: var(--border-hairline) solid var(--border);
  font-size: var(--text-xs); color: var(--text-secondary);
}
.stop__name { min-width: 0; overflow-wrap: break-word; }
.stop__mark { flex: none; width: 9px; height: 9px; border-radius: var(--radius-full); border: 2px solid currentColor; }
.stop[data-reached='true'] {
  color: var(--text-primary); font-weight: var(--weight-meta);
  background: var(--surface); border-color: var(--family, var(--r-mark));
}
.stop[data-reached='true'] .stop__mark { background: var(--family, var(--r-mark)); border-color: var(--family, var(--r-mark)); }
.stop__state { font-weight: var(--weight-body); color: var(--text-secondary); }

/* An archetype's identity plate: the type that sits close, named. No emblem, no magnitude. */
.ident { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3) var(--space-4); }
.ident__near { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2); font-size: var(--text-sm); color: var(--text-secondary); }
.ident__near-name { color: var(--r-ink); font-weight: var(--weight-meta); }

/* The reading scene. Shapes only — the page still ships no image and makes no request. */
.reading__art { justify-self: center; width: 100%; max-width: 360px; }
.rscene { display: block; width: 100%; height: auto; }
.rscene__sun { fill: var(--r-tint); }
.rscene__blob { fill: var(--wash-cream); opacity: 0.75; }
.rscene__hill { fill: var(--surface); opacity: 0.72; }
.rscene__beat { fill: none; stroke: var(--r-mark); stroke-width: 4.5; stroke-linecap: round; stroke-linejoin: round; }
.rscene__heart { fill: var(--r-tint); stroke: var(--r-mark); stroke-width: 3; }
.rscene__note { fill: var(--surface); stroke: var(--border-soft); stroke-width: 1.5; }
.rscene__dot { fill: var(--r-mark); }
.rscene__spark { fill: var(--r-mark); opacity: 0.75; }

@media (prefers-reduced-motion: no-preference) {
  .rscene__heart { transform-box: fill-box; transform-origin: center; animation: lb-beat 3.6s var(--ease-standard) infinite; }
}

/* Section headings inside a reading. */
.reading__h { display: flex; align-items: baseline; gap: var(--space-3); margin-bottom: var(--space-5); }

/* Signal rows read as cards, one to a line. */
.reading .signals { display: grid; gap: var(--space-3); }
.reading .signals > .signal {
  display: flex; align-items: flex-start; gap: var(--space-4);
  padding: var(--space-5); border: var(--border-hairline) solid var(--border-soft);
  border-bottom: var(--border-hairline) solid var(--border-soft);
  border-radius: var(--radius-lg); background: var(--surface); box-shadow: var(--shadow-soft);
}

/* "What this may mean" — the one washed block in the body of the reading. */
.panel {
  position: relative; padding: var(--space-7) var(--space-6);
  border-radius: var(--radius-xl); background: var(--r-wash);
  border: var(--border-hairline) solid var(--border-soft);
}
.panel__head { display: flex; align-items: center; gap: var(--space-4); margin-bottom: var(--space-4); }
.panel__icon { width: 40px; height: 40px; padding: 6px; border-radius: var(--radius-md); background: var(--surface); color: var(--r-mark); }
.panel .prose { max-width: var(--width-prose); }

/* The share card, as one row. */
.reading .share { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4); }
.reading .share.stack > * + * { margin-top: 0; }
.reading .share__preview {
  flex: 1 1 18rem; border-radius: var(--radius-lg); background: var(--r-wash);
  border: var(--border-hairline) solid var(--border-soft); box-shadow: none;
  /* The preview quotes the site's own address, which is one unbreakable token. Left to itself a
     flex item may not shrink under that token's width, so at a narrow measure the card pushed the
     page 5px wider than the viewport. It may shrink now, and the address wraps rather than spills. */
  min-width: 0; overflow-wrap: break-word;
}
.reading .share__preview .t-h3 { font-family: var(--font-display); }
.reading details.share { display: block; }
.reading details.share .share { margin-top: var(--space-4); }

/* Where people go next. */
.grid--next .card--next { flex-direction: row; align-items: center; gap: var(--space-4); border-radius: var(--radius-lg); box-shadow: var(--shadow-soft); }
.card--next .card__icon { width: 46px; height: 46px; padding: 11px; border-radius: var(--radius-md); background: var(--r-tint); color: var(--r-mark); }
.card--next .card__body { display: flex; flex-direction: column; gap: var(--space-1); flex: 1 1 auto; min-width: 0; }
.card--next .card__go { width: 34px; height: 34px; padding: 7px; border-radius: var(--radius-full); background: var(--r-tint); color: var(--r-ink); transition: transform var(--motion-fast) var(--ease-standard); }
.card--next:hover { border-color: var(--border-soft); transform: translateY(-3px); box-shadow: var(--shadow-lift); }
.card--next:hover .card__go { transform: translateX(3px); }
.card--next .card__title { font-family: var(--font-display); }

/* Closing actions. */
.reading__actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-5); }
.quill--insight { margin-top: var(--space-5); max-width: 22ch; color: var(--r-ink); }
.quill--close { max-width: 24ch; color: var(--r-ink); }

/* A quiet-tier reading keeps its restraint through the wash, not a second surface. */
.reading[data-tier='quiet'] { background: none; padding-inline: 0; }
.reading[data-tier='quiet'] .lede { background: var(--surface-quiet); }

@media (min-width: 640px) {
  .lede { padding: var(--space-9) var(--space-7); }
  .panel { padding: var(--space-8) var(--space-7); }
}

@media (min-width: 900px) {
  .lede { grid-template-columns: minmax(0, 1.3fr) minmax(0, 0.7fr); gap: var(--space-8); padding: var(--space-10) var(--space-9); }
  .reading__art { max-width: 300px; }
  /* The note below is placed against its card. Without a positioning context here it resolved
     against the page instead, and sat in the header over the site's own call to action. */
  .part--note { position: relative; }
  .quill--insight { position: absolute; inset-block-start: var(--space-7); inset-inline-end: var(--space-7); margin-top: 0; text-align: right; }
}

/* The reading is the one editorial-width surface on a calculator page; everything else stays at
   reading width. The Safety-first view keeps the narrower measure it was designed at. */
.reading { max-width: 1000px; margin-inline: auto; }
.result.safety { max-width: var(--width-content); margin-inline: auto; }
.reading .prose, .reading .result__interpretation { max-width: var(--width-prose); }

.grid--next { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 640px) { .grid--next { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .grid--next { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.reading .result__eyebrow { gap: var(--space-3); }

.reading .disclosure { border-radius: var(--radius-lg); border-color: var(--border-soft); background: var(--surface); }
.reading .disclosure summary { display: flex; justify-content: space-between; gap: var(--space-4); list-style: none; }
.reading .disclosure summary::-webkit-details-marker { display: none; }
.reading .disclosure summary::after { content: '+'; color: var(--r-ink); }
.reading .disclosure[open] summary::after { content: '\2212'; }

.reading .strip { background: var(--r-wash); border-radius: var(--radius-lg); padding: var(--space-5) var(--space-6); }
.reading > .note:last-child { margin-top: var(--space-6); }

/* An archetype is a type, not a direction, so its mark takes the calculator's own colour. */

/* ============================================================================
 * The rest of the site — hub, category, calculator, documents and 404.
 *
 * Same editorial layer as the homepage and the reading: a washed hero panel, cards with icon
 * chips, and the palette of whatever the page names (a calculator, a category, or the brand).
 * ========================================================================== */

/* ---------- The page hero ---------- */

.phero { padding-block: var(--space-5) calc(var(--rhythm) * 0.6); }
.phero__panel {
  display: grid; gap: var(--space-6); align-items: center;
  padding: var(--space-7) var(--space-6);
  border-radius: var(--radius-xl);
  background: var(--r-wash);
  border: var(--border-hairline) solid var(--border-soft);
}
.phero__copy { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
.phero .eyebrow { color: var(--r-ink); }
.phero__title { font-family: var(--font-display); letter-spacing: -0.02em; margin: 0; }
.phero__lede { color: var(--text-secondary); max-width: 46ch; }
.phero__count { font-size: var(--text-sm); font-weight: var(--weight-meta); color: var(--r-ink); }
.phero__art { justify-self: center; width: 100%; max-width: 320px; }
.phero__chips { gap: var(--space-2); }
.chip--meta {
  gap: var(--space-2); padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-full); border-color: var(--border-soft);
  background: var(--surface); color: var(--text-secondary); font-size: var(--text-xs);
}
.chip--meta .chip__icon { width: 22px; height: 22px; background: none; color: var(--r-ink); }

/* ---------- "What this looks at" ---------- */

.looks { display: grid; gap: var(--space-3); }
.look {
  display: flex; align-items: flex-start; gap: var(--space-4);
  padding: var(--space-4) var(--space-5); border-radius: var(--radius-lg);
  background: var(--surface); border: var(--border-hairline) solid var(--border-soft);
  box-shadow: var(--shadow-soft);
}
.look__icon { display: inline-grid; place-items: center; flex: none; width: 40px; height: 40px; padding: 9px; border-radius: var(--radius-md); background: var(--r-tint); color: var(--r-mark); }
.look__icon svg { width: 100%; height: 100%; }
.look__text { flex: 1 1 auto; min-width: 0; }

/* ---------- The listing card ---------- */

.card--calc { padding: 0; overflow: hidden; border-color: var(--border-soft); box-shadow: var(--shadow-soft); gap: 0; }
.card--calc:hover { transform: translateY(-3px); box-shadow: var(--shadow-lift); border-color: var(--border-soft); }
.card__inner { display: flex; flex-direction: column; gap: var(--space-2); flex: 1 1 auto; padding: var(--space-5); }
.card__top { display: flex; align-items: center; gap: var(--space-3); }
.card__chip { display: inline-grid; place-items: center; flex: none; width: 40px; height: 40px; padding: 9px; border-radius: var(--radius-md); background: var(--r-tint); color: var(--r-mark); }
.card__chip svg { width: 100%; height: 100%; }
.card--calc .card__title { font-family: var(--font-display); font-size: var(--text-h3); line-height: var(--lh-h3); }
.card__caption { font-size: var(--text-xs); color: var(--r-ink); font-weight: var(--weight-meta); }
.card--calc .card__meta { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.card__art { display: block; aspect-ratio: 32 / 15; background: var(--art-bg, var(--r-wash)); overflow: hidden; }
.card__art svg { display: block; width: 100%; height: 100%; }
/*
 * The "Start here" card's banner.
 *
 * It fills the card's own corner to corner — the card already clips to its radius — so there is no
 * inner edge and no pale gutter between the picture and the copy beside it. `cover` crops rather
 * than stretches, and the banners are all wide with their subject in the middle, so what a narrow
 * column takes off is sky on either side.
 *
 * The overscale is not decoration: each supplied file carries a pale rounded frame of its own,
 * drawn into the picture. Cropping the width alone never reaches the frame's top and bottom edges,
 * which would then read as two hairlines inside the card. 1.06 is measured against the widest of
 * those frames, and the subjects sit far enough in that none of them loses anything to it.
 */
.card__art picture { display: block; width: 100%; height: 100%; }
.card__art-img { display: block; width: 100%; height: 100%; object-fit: cover; scale: 1.06; }
.grid--lead { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 768px) {
  .card--lead { flex-direction: row; align-items: stretch; }
  .card--lead .card__art { flex: 0 0 40%; aspect-ratio: auto; }
  .card--lead .card__inner { padding: var(--space-7); justify-content: center; }
  .card--lead .card__title { font-size: var(--text-h2); line-height: var(--lh-h2); }
}

/* ---------- Documents ---------- */

.panel--doc { background: var(--surface); }
.panel--doc .prose { max-width: var(--width-prose); }
.doc__after { margin-top: var(--space-8); }

/* ---------- Guides ---------- */

/*
 * A guide reads as a document: the same panel and prose measure, with its section headings given
 * room above them and its lists drawn as lists. The calculator it leads to follows the article as
 * one plain panel, then the other guides as cards.
 */
.guide .prose h2 { margin-top: var(--space-8); }
.guide .prose h3 { margin-top: var(--space-6); }
.guide .prose p, .guide .prose li { line-height: var(--lh-body-lg); }
.guide__list { display: grid; gap: var(--space-3); padding-inline-start: var(--space-5); list-style: disc; }
.guide__list li::marker { color: var(--accent); }
.guide__cta { margin-top: var(--space-7); display: grid; gap: var(--space-3); justify-items: start; background: var(--r-wash, var(--surface)); }
.guide__cta .t-h2 { font-family: var(--font-display); }
.guide__more { margin-top: var(--space-9); display: grid; gap: var(--space-5); }
.guide__more .t-h2 { font-family: var(--font-display); }
.card--guide { height: 100%; }
.card--guide .card__inner { display: flex; flex-direction: column; gap: var(--space-2); height: 100%; }
.card--guide .card__title { font-family: var(--font-display); }
.card--guide:hover { border-color: var(--border-soft); transform: translateY(-3px); box-shadow: var(--shadow-lift); }

/* ---------- The calculator introduction ---------- */

.intro__note { margin-top: var(--space-5); }
.intro__start { margin-top: var(--space-6); }
.is-calculator .strip { background: var(--r-wash); border-radius: var(--radius-lg); padding: var(--space-5) var(--space-6); }

/* ---------- The question flow ---------- */

.flow-header { border-bottom: var(--border-hairline) solid var(--border-soft); margin-bottom: var(--space-6); }
.progress__seg { background: var(--r-tint); }
.progress__seg[data-done='true'] { background: var(--r-mark); }
.question { padding-block: var(--space-4) var(--space-8); }
.question__text { font-family: var(--font-display); font-size: var(--text-h2); line-height: var(--lh-h2); letter-spacing: -0.015em; text-wrap: balance; }
.option {
  border-radius: var(--radius-lg); border-color: var(--border-soft);
  box-shadow: var(--shadow-soft); padding: var(--space-4) var(--space-5);
}
.option:hover { border-color: var(--r-mark); background: var(--r-wash); }
.option__mark { border-color: var(--r-mark); }
.option__mark::after { background: var(--r-mark); }
.option:has(input:checked) { border-color: var(--r-mark); background: var(--r-wash); }
.analysis__dot { background: var(--r-mark); }

/* ---------- Shared refinements on these pages ---------- */

.is-listing .faq, .is-calculator .faq { border-radius: var(--radius-lg); background: var(--surface); border: var(--border-hairline) solid var(--border-soft); padding-inline: var(--space-5); box-shadow: var(--shadow-soft); }
.is-calculator .faq summary::after, .is-listing .faq summary::after { color: var(--r-ink); }
.is-listing .strip, .is-document .strip { background: var(--r-wash); border-radius: var(--radius-lg); padding: var(--space-5) var(--space-6); }
.band__head h2 .flourish { color: var(--r-mark); }

@media (min-width: 640px) {
  .phero__panel { padding: var(--space-8) var(--space-7); }
}

@media (min-width: 900px) {
  .phero__panel { grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr); gap: var(--space-8); }
}

/* The lead card's artwork takes the page palette, so it is never an empty block. */
.card__art { --art-bg: var(--r-wash); --blob-a: var(--r-tint); --blob-b: var(--wash-cream); --art-mark: var(--r-mark); --art-spark: var(--r-ink); }

/* A calculator page holds one measure: the hero and the wide bands match the reading's width. */
.is-calculator .phero__panel { max-width: 1000px; margin-inline: auto; }
.is-calculator .band > .wrap:not(.wrap--content) { max-width: 1000px; }
@media (min-width: 640px) {
  .intro__start .btn--block { width: auto; min-width: 16rem; }
}

/* Nothing on these pages forces a horizontal scroll, down to 320px and at 200% zoom. */
.look__text, .card__title, .card__reason, .faq summary, .question__text { overflow-wrap: anywhere; }
.faq summary { min-width: 0; }

@media (max-width: 420px) {
  .look { padding: var(--space-4); gap: var(--space-3); }
  .look__icon { width: 34px; height: 34px; padding: 7px; }
  .phero__panel, .panel { padding: var(--space-6) var(--space-5); }
  .card__inner { padding: var(--space-4); }
}

/* A document page holds one measure too, and its headings speak in the editorial voice. */
.is-document .phero__panel { max-width: 1000px; margin-inline: auto; }
.is-document .prose h2 { font-family: var(--font-display); letter-spacing: -0.015em; }

/* ---------- The reading: how these signals read, what to watch, what not to do ---------- */

/* What to watch next. */
.watch {
  display: flex; align-items: flex-start; gap: var(--space-4);
  padding: var(--space-6); border-radius: var(--radius-lg);
  background: var(--r-wash); border: var(--border-hairline) solid var(--border-soft);
}
.watch__icon { width: 44px; height: 44px; padding: 10px; flex: none; border-radius: var(--radius-md); background: var(--surface); color: var(--r-mark); }
.watch__body { flex: 1 1 auto; min-width: 0; max-width: var(--width-prose); }

.guidance__avoid { color: var(--text-secondary); }

@media (max-width: 420px) {
  .watch { padding: var(--space-5) var(--space-4); }
}

/* ==========================================================================
   LOVEBEAT — SIGNAL STORY
   The reading as one editorial composition. Panels are spent on three things
   only — the result moment, the note and the step; everything else is carried
   by type, hairlines and whitespace. Nothing here is a quantity. Tokens only.
   ========================================================================== */

/* ---------- rhythm and the three voices ---------- */

.reading .part { margin-top: var(--space-9); }
.reading .part:first-of-type { margin-top: var(--space-8); }
.part__mark { display: inline-flex; flex: none; color: var(--r-mark); translate: 0 1px; }
.part__mark svg { display: block; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linejoin: round; }

.part__h {
  display: flex; align-items: baseline; gap: var(--space-3);
  font-size: var(--text-xs); font-weight: var(--weight-meta);
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--r-ink);
  padding-bottom: var(--space-3); margin-bottom: var(--space-5);
  border-bottom: var(--border-hairline) solid var(--border);
}
.part__h--lead {
  font-family: var(--font-display); font-size: var(--text-h2); font-weight: var(--weight-h2);
  letter-spacing: -0.01em; text-transform: none; color: var(--text-primary);
  border-bottom: 0; padding-bottom: 0; margin-bottom: var(--space-5); text-wrap: balance;
}
.part__h--lead .part__mark { translate: 0 2px; }
.part__h--quiet { color: var(--text-secondary); border-bottom-color: var(--border-soft); letter-spacing: 0.14em; }

/* ---------- the result moment ---------- */

.lede {
  position: relative; overflow: hidden; isolation: isolate;
  display: flex; flex-direction: column; gap: var(--space-4);
  padding: var(--space-6) var(--space-5) var(--space-7);
  border-radius: var(--radius-xl);
  background: linear-gradient(152deg, var(--r-wash) 0%, var(--wash-cream) 82%);
  border: var(--border-hairline) solid var(--border-soft);
}
/* The seal, grown and pushed off the edge: a composition, not a square in a gap. */
.lede__wash {
  position: absolute; z-index: -1; inset-block-start: -18%; inset-inline-end: -14%;
  color: var(--r-mark); opacity: 0.1; pointer-events: none;
}
.lede__wash .seal svg { width: 260px; height: 260px; }
.lede__masthead {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: var(--space-2) var(--space-4);
  padding-bottom: var(--space-3); border-bottom: var(--border-hairline) solid var(--border-soft);
}
.lede__eyebrow {
  font-size: var(--text-xs); font-weight: var(--weight-meta);
  letter-spacing: 0.2em; text-transform: uppercase; color: var(--r-ink);
}
.lede__from { display: flex; flex-wrap: wrap; gap: 0 var(--space-1); align-items: baseline; }
.lede__from-key { font-size: var(--text-xs); color: var(--text-secondary); }
.lede__from-name { font-family: var(--font-display); font-size: var(--text-body); color: var(--text-primary); }
/* A little more air above it than below, so the headline reads as the thing the panel is for. */
.reading__headline {
  font-family: var(--font-display); letter-spacing: -0.03em;
  line-height: var(--lh-display); text-wrap: balance; margin: var(--space-2) 0 0; max-width: 20ch;
}
.seal { display: inline-flex; flex: none; color: var(--r-mark); }
.seal svg { display: block; }
.seal__heart { fill: none; stroke: currentColor; stroke-width: 1.6; }

/* ---------- what this reading is saying ---------- */

.saying {
  font-family: var(--font-display); font-size: var(--text-h3);
  line-height: 1.45; color: var(--text-primary); max-width: 30ch;
  padding-left: var(--space-5); border-left: var(--border-selected) solid var(--r-mark);
}

/* ---------- your love signals ---------- */

.story { display: flex; flex-direction: column; gap: var(--space-7); }
.rubric { display: flex; flex-direction: column; gap: var(--space-5); }
.rubric__h {
  font-size: var(--text-xs); font-weight: var(--weight-meta);
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--text-secondary);
  display: flex; align-items: center; gap: var(--space-4);
}
.rubric__h::after { content: ''; flex: 1 1 auto; height: 0; border-top: var(--border-hairline) solid var(--border-soft); }

/*
 * A reading unit, not a table row: the state, then the line the entry turns on, then the rest.
 *
 * The state is set the largest thing in the entry and stacked above the sentence, so it reads as
 * the pause between one unit and the next rather than as a label on a row. An earlier pass set it
 * beside the sentence in a rail, which held it at the size of a caption and left the right of the
 * page empty; it is the thing a reader is scanning for, so it is now the thing they see.
 */
.ledger, .plain { display: flex; flex-direction: column; gap: var(--space-7); }
.sig { display: flex; flex-direction: column; gap: var(--space-3); }
.sig + .sig { padding-top: var(--space-7); border-top: var(--border-hairline) solid var(--border-soft); }
/*
 * The state is a label, not a headline. Set at display size it out-shouted the sentence under it
 * and a run of entries read as a table of rows; set small, tracked and in the valence's own
 * colour, it is what a reader picks the entry out by, and the sentence is what they then read.
 */
.sig__state {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4);
  font-size: var(--text-sm); font-weight: var(--weight-h3);
  letter-spacing: 0.2em; text-transform: uppercase; line-height: 1.2;
}
/* At a narrow measure the state is two words on two lines before it is ever a scrollbar: the word
   keeps the space it needs and the rule gives its up first. */
.sig__word { min-width: 0; }
.sig__mark { flex: none; font-size: 0.6em; line-height: 1; }
/* The rule that closes the state. It is a typographic terminal, not a measurement of anything:
   the same length under every state, whatever the reading says. */
.sig__state::after {
  content: ''; flex: 0 1 var(--space-9); min-width: 0; height: 0;
  border-top: var(--border-hairline) solid currentColor; opacity: 0.45;
}
.sig[data-valence='positive'] .sig__state { color: var(--positive); }
.sig[data-valence='neutral'] .sig__state { color: var(--neutral); }
.sig[data-valence='caution'] .sig__state { color: var(--caution); }
/* The sentence the entry turns on, and the largest thing in it. */
.sig__line {
  font-family: var(--font-display); font-size: var(--text-h3);
  line-height: var(--lh-h3); color: var(--text-primary); max-width: 38ch; text-wrap: pretty;
}
.sig__text { max-width: 46ch; color: var(--text-secondary); font-size: var(--text-sm); }
/*
 * Where the entry is split, the remainder is the author's continuation clause after the em dash,
 * so it begins in lower case ("… between you — early on, …"). Set on a line of its own it opens
 * that line, and a line that opens in lower case reads as unfinished. The capital is display only:
 * the text stays the author's sentence, so the line and the remainder still join back into it.
 */
.sig__text::first-letter { text-transform: uppercase; }
/* Neutral reads quieter than the other two: it has not settled, it has not gone wrong. */
.sig[data-valence='neutral'] .sig__line { color: var(--text-secondary); }
/*
 * The band's own sentences carry no state, because the content never classified them. They open on
 * a rule instead — the same terminal the state ends on, standing alone. It keeps the rhythm of the
 * section without the product inventing a classification to fill the line.
 */
.sig:not([data-valence])::before {
  content: ''; width: var(--space-10); height: 0;
  border-top: var(--border-selected) solid var(--r-mark); opacity: 0.4;
}
/* Where a calculator wrote its reasons as one passage rather than as sentences, the passage reads
   in the same voice the entries do instead of dropping to plain body copy. */
.part--signals > .prose {
  max-width: none; font-family: var(--font-display);
  font-size: var(--text-body-lg); line-height: 1.6; color: var(--text-primary);
}

/* ---------- the note, and what to watch ---------- */

.pair { display: grid; gap: var(--space-5); margin-top: var(--space-9); }
.pair .part { margin-top: 0; }
.part--note {
  padding: var(--space-6) var(--space-5);
  border-radius: var(--radius-md);
  background: var(--wash-peach);
  border: var(--border-hairline) solid var(--border-soft);
}
.part--note .part__h { border-bottom-color: var(--border-soft); }
/* The card is the measure here. Capping the prose as well left a third of the card empty. */
.note-card__body .prose { max-width: none; font-size: var(--text-sm); }
.note-card__body .prose p + p { margin-top: var(--space-4); }
.part--watch .watch__body { max-width: none; }
.part--watch .prose { font-size: var(--text-sm); }

/* ---------- your next step ---------- */

.part--step { padding: 0; }
.step {
  position: relative;
  padding: var(--space-7) var(--space-5);
  border-radius: var(--radius-lg);
  background: linear-gradient(158deg, var(--r-wash) 0%, var(--wash-cream) 88%);
  border: var(--border-hairline) solid var(--border-soft);
  border-top: 3px solid var(--r-mark);
}
/* Sized to the writing, not to the viewport: the previous card ran 1000px wide with its content
   in a quarter of it. */
.step__inner { display: flex; flex-direction: column; gap: var(--space-4); max-width: 46ch; }
.step__kicker {
  display: flex; align-items: baseline; gap: var(--space-2);
  font-size: var(--text-xs); font-weight: var(--weight-meta);
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--r-ink);
}
.step__h {
  font-family: var(--font-display); font-size: var(--text-h2); font-weight: var(--weight-h2);
  letter-spacing: -0.01em; line-height: var(--lh-h2); color: var(--text-primary); text-wrap: balance;
}
.step__prose { max-width: none; }
.step__arrow { display: inline-flex; color: var(--r-mark); }
.step__avoid { padding-top: var(--space-4); border-top: var(--border-hairline) solid var(--border-soft); }
.step__avoid .part__h {
  border-bottom: 0; padding-bottom: 0; margin-bottom: var(--space-1);
  font-size: var(--text-xs); letter-spacing: 0.14em; color: var(--text-secondary);
}
.step__avoid .part__h .part__mark { display: none; }
.guidance__avoid { color: var(--text-secondary); font-size: var(--text-sm); }

/* ---------- the illustration library ---------- */

/*
 * Ten drawn scenes, used sparingly. They are around 550-610px on their long edge, so every slot
 * caps its width below that and lets the picture contain rather than crop: scaled past its own
 * pixels the line work softens, and cropped it loses the thing it was drawn around. The aspect
 * ratio comes from the file's own width and height attributes, so nothing shifts as it lands.
 */
/*
 * The cap belongs on the `picture`, not on the image inside it.
 *
 * Two ways of writing this look right and are not. Sized at `100%` the image measures 100% of a
 * `picture`, which is an inline box with no width of its own — zero. Sized `auto` it loses the
 * `width` attribute, which the browser applies only as a presentational hint that any author rule
 * outranks — zero again. Either way a lazily loaded image has no area, an image with no area is
 * never fetched, and the drawing simply never appears. So `picture` is the block that carries the
 * width, the image fills it, and the aspect ratio comes from the attributes, which means the slot
 * reserves the right box before the file has landed and the page does not shift when it does.
 */
.artwork { display: flex; justify-content: center; }
.artwork picture, .pause picture { display: block; width: 100%; }
.artwork__img { display: block; width: 100%; height: auto; object-fit: contain; }

/*
 * The closing band's drawing sits in the panel, not under it.
 *
 * The band is a blush panel with its copy centred and a scattering of petals already pinned to one
 * corner, so there is room along the foot of it that the composition was never using. Placed there
 * the drawing is decoration attached to the panel and costs the band no height at all. Set in the
 * flow beneath the buttons it had been a picture parked between two sections, which is the one
 * thing an illustration on this site may not be.
 *
 * It needs the panel to be wide enough to have a margin to sit in, so below that width it goes.
 */
/*
 * The drawing is sized by its character, not by its canvas.
 *
 * `--cta-ink` is the width the visible figure should take; the file carries about six per cent of
 * its width as transparent margin, so the element is that much wider and the ink lands on the
 * number asked for. Nothing is cropped and nothing is stretched: width drives, height follows.
 *
 * Beside the copy the figure can only grow as far as the copy's own left edge. The panel centres a
 * measure of about 520px, so the clear zone on each side is half the panel less 300px — 143px at
 * the breakpoint, 290px once the panel reaches its full width. `--cta-ink` tracks that zone and
 * stops 16px short of the text, which is why it is written as a viewport expression rather than a
 * fixed size: at every width the figure is as large as the composition allows and never larger.
 * The floor keeps it from shrinking below the size it had before at the narrowest desktop.
 */
.artwork--close { --cta-ink: clamp(150px, 42vw, 230px); }

/* On a phone the drawing follows the buttons, which is where the eye already is. It is in the flow
   here rather than pinned to a corner, because a panel this narrow has no corner to spare. The
   panel's foot draws in to pay for most of the height the picture costs. */
.artwork--close { display: flex; justify-content: center; margin-block-start: var(--space-7); }
.artwork--close picture { display: block; width: calc(var(--cta-ink) / 0.9397); max-width: 100%; }
.artwork--close .artwork__img { display: block; width: 100%; height: auto; }
@media (max-width: 899px) {
  .band--close .closer { padding-block-end: var(--space-7); }
}

@media (min-width: 900px) {
  .artwork--close {
    --cta-ink: clamp(130px, 50vw - 320px, 274px);
    display: block; position: absolute; z-index: 0; margin: 0;
    inset-block-end: var(--space-6); inset-inline-start: var(--space-8);
    width: calc(var(--cta-ink) / 0.9397); height: auto;
  }
  .artwork--close picture { width: 100%; max-width: none; }
  /* The copy and the buttons keep their own stacking, so nothing is ever read through the drawing. */
  .band--close .closer > :not(.artwork) { position: relative; z-index: 1; }
}
/*
 * Every banner character, at one size.
 *
 * The hero panels used to hold two different drawings: a small one beside a category or calculator
 * introduction, and a large one standing on the floor of the pages that open with a character. On
 * top of that the files themselves run from 0.885 to 1.764 in ink proportion, so even two drawings
 * given the same box arrived on screen at different sizes. Across the site the same character was
 * rendered anywhere from 198px to 442px tall.
 *
 * Every character sits in the middle of its half of the panel, and height is what reads as size
 * for a drawing of a person, so height is what is held equal here.
 * `--phero-ink` is the height every character's ink is drawn at, and each file divides it by the
 * share of its canvas the ink actually occupies, so the transparent margin a file happens to carry
 * never decides how big its character looks. The width follows from the file's own proportions and
 * is capped at the column, which is the one case a character comes out shorter: a drawing wide
 * enough to need more room than the panel has is scaled to fit rather than allowed to cross into
 * the copy.
 *
 * Every value below is measured from the file's alpha channel, and every one of them has a safe
 * default, so a drawing added later renders whole and unstretched before anyone measures it. The
 * same default is the floor a browser without `:has()` lands on: it reads none of the per-file
 * values, so every character is contained in a square of the shared height and comes out a little
 * smaller than intended — never stretched, never clipped, never out of its panel.
 */
.artwork--phero {
  /* The ceiling is the largest any banner character reached before, so nothing was made smaller to
     make the set agree. Below the desk it falls with the viewport rather than with the column, so
     the character is the same size on every page at a given width, not merely on the widest one. */
  --phero-ink: clamp(min(236px, 58vw), 29vw, 372px);
  width: 100%;
  /* The figure is decoration and already hidden from assistive technology, so it never takes a tap
     from anything it happens to sit over. */
  pointer-events: none;
}
/* The picture carries the file's own proportions, so whichever limit binds, the height follows the
   width and nothing is stretched. The image simply fills that box. */
.artwork--phero picture {
  display: block; height: auto;
  aspect-ratio: var(--art-ar, 1);
  /* Both terms are known, so the box never loses its ratio: the drawing is as wide as the height
     it is aiming for needs, or as wide as the column has, whichever is less. Clamping the width
     instead of the height is what keeps a capped drawing from leaving a band of empty box behind
     it and pushing the panel taller than the pages that did fit. */
  width: min(100%, calc(var(--phero-ink) / var(--art-fill, 1) * var(--art-ar, 1)));
  /* The offsets centre the ink rather than the canvas, on both axes: a file whose drawing sits
     high or off to one side in its own frame would otherwise land off-centre in the panel however
     carefully the box is placed. Both are shares of the picture's own size, so they hold at every
     width. */
  translate: var(--art-shift-x, 0%) var(--art-shift, 0%);
}
/* `contain` is insurance: if a file's ratio were ever missing or wrong the character is letterboxed
   rather than stretched, and centred is where the rest of the set sits. */
.artwork--phero .artwork__img {
  width: 100%; height: 100%;
  object-fit: contain; object-position: center;
}
/* Beside the copy the artwork takes a wider column than an introduction hero used to give it — two
   fifths rather than a third — because a character held to a third cannot reach the shared height
   without the cap scaling it back down. */
@media (min-width: 900px) {
  .phero__panel:has(.artwork--phero) { grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); }
}

/* Measured from each file's alpha channel: canvas proportion, then ink height as a share of canvas
   height, then the ink centre's offset from the canvas centre on each axis. */
.artwork--phero:has(.artwork__img[src$="artwork-11.png"]) { --art-ar: 1.1996; --art-fill: 0.9715; --art-shift-x: 1.1%; --art-shift: 0.1%; }
.artwork--phero:has(.artwork__img[src$="artwork-12.png"]) { --art-ar: 1.1996; --art-fill: 0.9912; --art-shift-x: 1.2%; }
.artwork--phero:has(.artwork__img[src$="artwork-13.png"]) { --art-ar: 1.1996; --art-fill: 0.9781; --art-shift-x: 0.7%; }
.artwork--phero:has(.artwork__img[src$="artwork-14.png"]) { --art-ar: 0.9120; --art-fill: 0.9771; --art-shift-x: -0.7%; }
.artwork--phero:has(.artwork__img[src$="artwork-15.png"]) { --art-ar: 1.0000; --art-fill: 0.9640; --art-shift-x: -1.4%; --art-shift: 0.4%; }
.artwork--phero:has(.artwork__img[src$="artwork-16.png"]) { --art-ar: 1.1996; --art-fill: 0.9364; --art-shift-x: 1.1%; --art-shift: 1.6%; }
.artwork--phero:has(.artwork__img[src$="artwork-17.png"]) { --art-ar: 1.1996; --art-fill: 0.9386; --art-shift-x: 1.2%; --art-shift: 1.3%; }
.artwork--phero:has(.artwork__img[src$="artwork-18.png"]) { --art-ar: 1.0964; --art-fill: 0.9581; --art-shift: 0.8%; }
.artwork--phero:has(.artwork__img[src$="artwork-19.png"]) { --art-ar: 1.1996; --art-fill: 0.9737; --art-shift-x: -0.9%; --art-shift: 0.9%; }
.artwork--phero:has(.artwork__img[src$="artwork-20.png"]) { --art-ar: 1.1996; --art-fill: 0.9189; --art-shift: -0.1%; }
.artwork--phero:has(.artwork__img[src$="artwork-21.png"]) { --art-ar: 1.1996; --art-fill: 0.9846; --art-shift-x: 1.4%; --art-shift: 0.5%; }
.artwork--phero:has(.artwork__img[src$="artwork-24.png"]) { --art-ar: 1.1996; --art-fill: 0.9079; --art-shift-x: 0.7%; --art-shift: 3.1%; }
.artwork--phero:has(.artwork__img[src$="artwork-25.png"]) { --art-ar: 1.1996; --art-fill: 0.9846; --art-shift-x: 1.8%; --art-shift: 0.8%; }
.artwork--phero:has(.artwork__img[src$="artwork-26.png"]) { --art-ar: 1.5000; --art-fill: 0.8309; --art-shift-x: -0.2%; --art-shift: 6.5%; }
.artwork--phero:has(.artwork__img[src$="artwork-27.png"]) { --art-ar: 1.1996; --art-fill: 0.9671; --art-shift-x: 0.1%; --art-shift: 1.6%; }
.artwork--phero:has(.artwork__img[src$="artwork-29.png"]) { --art-ar: 1.1996; --art-fill: 0.9693; --art-shift: 1.1%; }
.artwork--phero:has(.artwork__img[src$="artwork-31.png"]) { --art-ar: 1.1996; --art-fill: 0.9715; --art-shift-x: -3.7%; --art-shift: 0.5%; }
.artwork--phero:has(.artwork__img[src$="artwork-33.png"]) { --art-ar: 1.1996; --art-fill: 0.9123; --art-shift-x: 1.6%; --art-shift: 2.9%; }
.artwork--phero:has(.artwork__img[src$="artwork-34.png"]) { --art-ar: 0.9743; --art-fill: 0.9743; --art-shift-x: -0.3%; --art-shift: 0.7%; }
.artwork--phero:has(.artwork__img[src$="artwork-37.png"]) { --art-ar: 0.9782; --art-fill: 0.9861; --art-shift-x: -0.2%; --art-shift: 0.7%; }
.artwork--phero:has(.artwork__img[src$="artwork-43.png"]) { --art-ar: 0.9231; --art-fill: 0.9962; --art-shift-x: -0.3%; --art-shift: 0.2%; }
.artwork--phero:has(.artwork__img[src$="artwork-44.png"]) { --art-ar: 1.0305; --art-fill: 0.9980; --art-shift: 0.1%; }
.artwork--phero:has(.artwork__img[src$="artwork-46.png"]) { --art-ar: 1.0000; --art-fill: 0.9940; --art-shift: 0.1%; }
.artwork--phero:has(.artwork__img[src$="artwork-48.png"]) { --art-ar: 1.0000; --art-fill: 0.9900; --art-shift-x: 0.2%; --art-shift: -0.1%; }
.artwork--phero:has(.artwork__img[src$="artwork-49.png"]) { --art-ar: 1.0101; --art-fill: 0.9839; --art-shift-x: 0.1%; --art-shift: 0.8%; }

/*
 * The reading's one drawing, in the hero.
 *
 * It opens the reading rather than closing it, and it is inside the panel at every width — the one
 * thing it may never be is a picture parked between two sections.
 *
 * Below the desk the drawing takes a row of its own at the foot of the panel, under the headline,
 * and runs the full measure. It was a narrow right-hand column before, and the
 * arithmetic of that column is why it changed: the panel has 294px of content at 360px and the
 * widest headline in the library needs 184 of them, so a column beside the words could never be
 * more than about 90px — a character small enough to read as a bullet rather than a drawing. Given
 * a row to itself it is three to four times that, and the words above it lose nothing at all.
 *
 * Held by a height, not a box: every file keeps its own proportions, so a portrait and a square
 * arrive at the same weight while the widest landscape is held by the panel's width instead and
 * comes out wider and shorter. Nothing is cropped or stretched at any shape — contain, with both
 * dimensions free, as everywhere else on the site. The ceiling meets the desktop size exactly, so
 * 900px changes the composition without changing how large the character is.
 */
.lede--art {
  --lede-art-max: clamp(224px, 80vw, 320px);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}
.lede--art > .lede__masthead { grid-column: 1; grid-row: 1; }
.lede--art > .reading__headline { grid-column: 1; grid-row: 2; }
.lede__art {
  grid-column: 1; grid-row: 3; min-width: 0;
  display: flex; align-items: flex-end; justify-content: center;
  /* The row reaches the panel's inner edges. Every other child of the hero is read, so it keeps the
     measure's side padding; the drawing is not, and the padding beside it was width the character
     could have been using. It buys the widest files — the ones the panel's width holds rather than
     its height — about a tenth more of themselves at phone widths, and costs the words nothing. */
  margin-inline: calc(var(--space-5) * -1);
}
.lede__art picture { display: block; width: 100%; }
.lede__art-img {
  display: block; width: auto; height: auto;
  max-width: calc(100% / var(--art-fill-w, 1));
  max-height: calc(var(--lede-art-max) / var(--art-fill-h, 1));
  object-fit: contain;
  /* Centred on the row rather than started at its left edge. A compensated image is wider than the
     row on purpose, and left to the normal flow the whole of that extra width fell on one side and
     took the character's right edge into the panel's clip with it. Centred, what hangs over is
     half the transparent margin on each side, which is what the measured fills assume. */
  position: relative; inset-inline-start: 50%; translate: -50% 0;
}
/*
 * The box is not the character.
 *
 * Several files carry transparent margin, so the same box shows a smaller character: artwork-30
 * reaches only 82 per cent of its own canvas across, artwork-36 only 93 per cent of it down.
 * Sizing the box the same for all of them makes those characters quietly smaller than the rest,
 * and no amount of box is the answer, because the margin scales with it.
 *
 * So each limit is divided by how much of its canvas that file actually uses, and what fills the
 * row is the ink rather than the canvas. The measure is the larger half-extent from the centre,
 * not the raw ink width: an off-centre character runs out of room on one side first, and that
 * side is the one that may not be cut. The transparent remainder hangs outside the panel and is
 * clipped, which costs nothing because nothing is drawn there. The values are measured from the
 * files' alpha channels, and the test beside this file measures them again from the same PNGs.
 *
 * Nothing here changes a file's proportions: both limits move together and `contain` still picks
 * whichever binds.
 */
@media (max-width: 899px) {
  .lede__art-img[src$="artwork-30.png"] { --art-fill-w: 0.821; }
  .lede__art-img[src$="artwork-32.png"] { --art-fill-w: 0.821; --art-fill-h: 0.982; }
  .lede__art-img[src$="artwork-13.png"] { --art-fill-w: 0.832; --art-fill-h: 0.978; }
  .lede__art-img[src$="artwork-12.png"] { --art-fill-w: 0.876; }
  .lede__art-img[src$="artwork-29.png"] { --art-fill-w: 0.846; }
  .lede__art-img[src$="artwork-21.png"] { --art-fill-w: 0.905; }
  .lede__art-img[src$="artwork-31.png"] { --art-fill-w: 0.92; --art-fill-h: 0.982; }
  .lede__art-img[src$="artwork-22.png"] { --art-fill-w: 0.923; }
  .lede__art-img[src$="artwork-23.png"] { --art-fill-w: 0.938; --art-fill-h: 0.978; }
  .lede__art-img[src$="artwork-14.png"] { --art-fill-w: 0.962; --art-fill-h: 0.977; }
  .lede__art-img[src$="artwork-11.png"] { --art-fill-w: 0.963; --art-fill-h: 0.974; }
  .lede__art-img[src$="artwork-34.png"] { --art-fill-w: 0.968; --art-fill-h: 0.984; }
  .lede__art-img[src$="artwork-19.png"] { --art-fill-w: 0.971; }
  .lede__art-img[src$="artwork-28.png"] { --art-fill-w: 0.978; --art-fill-h: 0.985; }
  .lede__art-img[src$="artwork-26.png"] { --art-fill-w: 0.98; --art-fill-h: 0.961; }
  .lede__art-img[src$="artwork-24.png"] { --art-fill-w: 0.982; --art-fill-h: 0.969; }
  .lede__art-img[src$="artwork-48.png"] { --art-fill-w: 0.984; }
  .lede__art-img[src$="artwork-35.png"] { --art-fill-h: 0.966; }
  .lede__art-img[src$="artwork-36.png"] { --art-fill-h: 0.93; }
  .lede__art-img[src$="artwork-16.png"] { --art-fill-h: 0.969; }
  .lede__art-img[src$="artwork-17.png"] { --art-fill-h: 0.965; }
}
/*
 * The Safety-first drawing.
 *
 * Last in the section, after the words and after the way back, and never beside them: this page
 * has one thing to say and the picture is not part of it. It stays at every width, because this
 * state never has a second column for anything to crowd.
 *
 * It is drawn at the reading's scale rather than a fraction of it. Held at a sixth of the panel it
 * read as a token on the page that most needs to feel attended to, which is the opposite of what a
 * smaller picture was meant to say. What keeps it from illustrating what the reader described is
 * where it sits and how quietly it is drawn — last, centred, held back in weight — not how small
 * it is. The cap matches the reading hero's, so the character is the size the reader met on every
 * other page, and the section is still words first and picture last.
 */
.safety__art { display: flex; justify-content: center; margin-top: var(--space-8); }
.safety__art picture { display: block; width: 100%; max-width: min(300px, 100%); }
.safety__art-img { display: block; width: 100%; height: auto; object-fit: contain; opacity: 0.9; }

/* ---------- the signature ---------- */

/*
 * The reading's signature. Scoped to the reading: `.closer` is also the homepage's closing band,
 * and an unscoped rule here reached across and relaid it out. Scoping also drops the band's own
 * padding and blush panel, which the signature had been inheriting — it was reading as a fourth
 * surface, sixty-four pixels tall around two lines of type, where the page allows three.
 */
.reading .closer {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-2);
  margin-top: var(--space-9); padding: var(--space-5) 0 0;
  background: none; border-radius: 0; text-align: center;
}
.closer__rule {
  display: flex; align-items: center; justify-content: center;
  width: 100%; max-width: 13rem; margin-bottom: var(--space-3); color: var(--r-mark);
}
.closer__rule::before, .closer__rule::after {
  content: ''; flex: 1 1 auto; height: 0; border-top: var(--border-hairline) solid var(--border);
}
.closer__rule .part__mark { margin-inline: var(--space-3); }
.closer__name {
  font-family: var(--font-display); font-size: var(--text-h3);
  letter-spacing: 0.02em; color: var(--r-ink);
}
.closer__line { font-size: var(--text-sm); color: var(--text-secondary); }

.part--stops, .part--ident { margin-top: var(--space-7); }

/*
 * On a phone the next step comes straight after what the reading is saying.
 *
 * The story still runs in its own order in the document — what happened, why, what it may mean,
 * then what to consider — and a wider screen shows it that way, with the step as its conclusion.
 * Stacked on a phone the same order put the step two thousand pixels under the headline, behind
 * every signal and the note, so a reader had to finish the whole page to find out what it asked of
 * them. Here the step, with the wellbeing note an Attention reading carries just before it, follows
 * the reading's own sentence and its block; the signals, the note and everything after keep their
 * order beneath it. Nothing is hidden or repeated, and none of what moves holds a control, so the
 * keyboard's path through the page is the one it always was.
 */
@media (max-width: 639px) {
  .reading { display: flex; flex-direction: column; }
  .reading > * { order: 1; }
  .reading > .lede, .reading > .part--saying, .reading > .part--stops, .reading > .part--ident,
  .reading > .part:has(> .strip), .reading > .part--step { order: 0; }
  /* In the column the note's own top margin no longer folds into its section's, so it gives it up
     and the gap above it stays the one the section sets. */
  .reading > .part > .strip { margin-top: 0; }
}

/* ---------- wider than a phone ---------- */

@media (min-width: 640px) {
  .lede { padding: var(--space-8) var(--space-7) var(--space-9); }
  .lede__art { margin-inline: calc(var(--space-7) * -1); }
  .lede__wash .seal svg { width: 320px; height: 320px; }
  .saying { font-size: var(--text-h2); max-width: 26ch; }
  .part--note { padding: var(--space-7); }
  .step { padding: var(--space-8) var(--space-7); }
  /* The band is the widest thing on the page, so it is read across rather than down: what the
     step is called on the left, what it asks of you beside it. Held to one narrow column it left
     six tenths of its own width empty, which is what made it read as a card with nothing in it. */
  .step__inner {
    display: grid; max-width: none; align-items: start;
    grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr); gap: var(--space-4) var(--space-9);
  }
  .step__kicker { grid-column: 1; grid-row: 1; }
  .step__h { grid-column: 1; grid-row: 2; }
  /* Tucked under the title it belongs to, rather than floating in the column below it. */
  .step__arrow { grid-column: 1; grid-row: 3; margin-top: calc(var(--space-3) * -1); }
  .step__prose { grid-column: 2; grid-row: 1 / span 3; max-width: 52ch; }
  .step__avoid { grid-column: 1 / -1; grid-row: 4; margin-top: var(--space-3); }
  .pair { grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr); align-items: start; gap: var(--space-7); }
  /* The drawing takes space the band already had, and none that it did not.
     It sits at the foot of the panel, where the "what you don't need to do" line runs short of
     the right edge, so only that line is held clear of it. Reserving across the whole panel was
     tried first and narrowed the guidance column enough to add fifty pixels of height — which is
     the one thing the picture must not cost. */
  /* Side by side, the two read as one spread, so their names start on the same line: the note's
     name sits inside the card's padding, and the margin note takes the same amount above its own. */
  .reading .pair > .part { margin-top: 0; }
  .part--watch { padding-top: var(--space-7); }
  .pair--single { grid-template-columns: minmax(0, 1fr); }
}
@media (min-width: 900px) {
  /*
   * The desk keeps the approved opening, unchanged: two columns, everything read in the first and
   * the drawing in the second, at the size it was approved at. The drawing is held by a height
   * rather than a width, so the library's portraits and its landscapes occupy the same band of the
   * panel and none of them turns the opening into a picture with a caption. The height is what the
   * eye reads as presence, so a portrait and a square arrive at the same weight while the widest
   * landscape is held by the column instead and comes out wider and shorter. Nothing is cropped.
   *
   * It is the same height the narrower widths reach, so crossing 900px moves the character from
   * under the words to beside them without resizing it.
   */
  .lede--art {
    --lede-art-max: 320px;
    grid-template-columns: minmax(0, 1fr) minmax(0, 360px);
    column-gap: var(--space-9);
    align-items: center;
  }
  /*
   * Here the drawing stands on the panel's floor rather than in a row of its own: the cell is
   * stretched over both text rows and the picture is pushed to its bottom-right corner, so however
   * tall the words run the character keeps the same footing. A little air above it stops it meeting
   * the panel's top edge when the words are short.
   */
  .lede__art {
    grid-column: 2; grid-row: 1 / span 2; align-self: stretch;
    justify-content: flex-end;
    margin-inline: 0;
    /* The character stands on the panel's floor rather than above its bottom padding: that band of
       empty ground under the drawing was height the composition never used. */
    margin-block-end: calc(var(--space-10) * -1);
    padding-block-start: 0;
  }
  .lede { padding: var(--space-10) var(--space-9); gap: var(--space-5); }
  .lede__wash { inset-block-start: -22%; inset-inline-end: -8%; }
  .lede__wash .seal svg { width: 420px; height: 420px; }
  /*
   * The page composes as a magazine spread: the hero and the closing band run the full width of
   * the reading, and everything read at length sits in one editorial measure between them. The
   * measure is narrower than the page on purpose — a sentence set to a thousand pixels is not a
   * sentence anyone reads, and an earlier pass left four hundred pixels of nothing beside every
   * signal because the column was as wide as the page while the type was not.
   */
  .reading > .part:not(.part--step), .reading > .pair, .reading > .disclosure, .reading > .closer {
    max-width: var(--width-reading); margin-inline: auto;
  }
  /* The entry runs down the measure: the state, then the line, then what explains it. The state
     keeps the margin to its left clear, so a run of them reads as the spine of the section. */
  /* The entry fills most of the measure it is set in. Held to half of it, the hairlines above and
     below ran on past the end of every sentence, which is what made the column look undersized. */
  .sig__line { max-width: 62ch; }
  .sig__text { max-width: 74ch; }
}
/*
 * Below the design's narrowest width — which is where a phone at 200% zoom lands — a single long
 * word in a display headline is wider than the measure itself, and the hero, which clips rather
 * than scrolls, cut it off mid-word: "The Independent Spirit" lost 36px, "Patterns worth a real
 * conversation" 37px. The headline steps down one size there instead. Nothing is broken mid-word.
 */
@media (max-width: 300px) {
  .reading__headline { font-size: var(--text-h2); line-height: var(--lh-h2); }
}
@media (max-width: 420px) {
  .lede { padding: var(--space-5) var(--space-4) var(--space-6); }
  .lede__art { margin-inline: calc(var(--space-4) * -1); }
  .part--note { padding: var(--space-5) var(--space-4); }
  .step { padding: var(--space-6) var(--space-4); }
  .saying { padding-left: var(--space-4); }
}

/* ==========================================================================
   The reading, composed to the reference
   ========================================================================== */

/*
 * One wide frame, one reading frame.
 *
 * The hero and the next step already ran the full width of the reading while everything else was
 * inset, but the share row and the way onward were inset with the prose — and they are not prose.
 * They are the page's furniture, and the reference lines them up with the two panels, which is
 * also what stops the foot of the page reading as a narrower column than its head.
 */
@media (min-width: 900px) {
  .reading > .part.part--share,
  .reading > .part.part--next { max-width: none; }
}

/*
 * The reasons, as a numbered editorial list.
 *
 * The same sentences, given the shape the reference gives them: a soft blush counter in the
 * margin, the reason's own line set in the display face, and what explains it underneath in the
 * secondary colour. The rule between items belongs to the list rather than to each row, so the
 * last reason does not trail a line under it.
 */
.part--signals .plain { counter-reset: lb-reason; }
.part--signals .plain > li {
  counter-increment: lb-reason;
  position: relative;
  display: block;
  padding-inline-start: 3.5rem;
  padding-block: var(--space-5);
  border-bottom: 0;
}
.part--signals .plain > li + li { border-top: var(--border-hairline) solid var(--border-soft); }
.part--signals .plain > li::before {
  content: counter(lb-reason);
  position: absolute; inset-inline-start: 0; inset-block-start: var(--space-5);
  display: grid; place-items: center;
  width: 2.25rem; height: 2.25rem;
  border-radius: var(--radius-full);
  background: var(--r-tint); color: var(--r-ink);
  font-family: var(--font-display); font-size: var(--text-sm); font-weight: var(--weight-h1);
}
.part--signals .sig { gap: var(--space-2); }
.part--signals .sig__line {
  font-family: var(--font-display); font-weight: var(--weight-h1);
  font-size: var(--text-body); line-height: var(--lh-h3);
}
.part--signals .sig__text { color: var(--text-secondary); font-size: var(--text-sm); }

/*
 * The quiet note, as a callout rather than a card beside another card.
 *
 * Two cards side by side made the note read as one of a pair of widgets. The reference gives it
 * the full measure, a warmer ground than the page and a border light enough that it settles
 * rather than announces — the opposite of an alert.
 */
.reading > .pair { grid-template-columns: minmax(0, 1fr); }
.reading > .pair > .part--note,
.reading > .pair > .part--watch {
  background: var(--wash-blush);
  border: var(--border-hairline) solid var(--border-soft);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
}

/*
 * The next step, as the page's second panel.
 *
 * It carries the same rounding and hairline as the hero so the two read as the page's two
 * moments, with a warmer ground between them. The arrow becomes a mark rather than a glyph
 * floating in the column.
 */
.step {
  background: var(--r-wash);
  border: var(--border-hairline) solid var(--border-soft);
  border-radius: var(--radius-xl);
}
.step__arrow {
  display: inline-grid; place-items: center;
  width: 2.5rem; height: 2.5rem;
  border-radius: var(--radius-full);
  border: var(--border-hairline) solid var(--border-soft);
  color: var(--r-ink);
}

/*
 * The measure.
 *
 * The opening paragraph was set in the display face at the headline's own size, which read as a
 * second headline and gave it 55 characters to a line — short enough that the eye returns more
 * often than it reads. Set one step down and held to a measure rather than to the column, it lands
 * in the sixties, which is where prose is read, and the section stops competing with the hero.
 */
@media (min-width: 900px) {
  .part--saying .saying {
    font-size: var(--text-h3);
    line-height: var(--lh-body);
    max-width: 66ch;
  }
}
/* The other extreme: a signal's explanation ran to the full column and past eighty characters. */
.sig__text, .signals__text { max-width: 64ch; }

/* The opening's smaller voices, brought up to the reference's hierarchy. */
.lede__eyebrow { letter-spacing: 0.22em; }
.lede__from-name { font-size: var(--text-h3); }

/* The note is quiet, not roomy: it keeps its ground and gives back the padding of a card. */
.reading > .pair > .part--note,
.reading > .pair > .part--watch { padding: var(--space-5); }
.part--signals .plain > li { padding-block: var(--space-4); }

/*
 * The share row, as one compact control.
 *
 * The action and what it would send are a single object rather than a card and a button that
 * happen to sit together. Nothing about what it does changes.
 */
.part--share > .part__body {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  border: var(--border-hairline) solid var(--border-soft);
  border-radius: var(--radius-lg);
  background: var(--surface-quiet);
}
.part--share .share__preview { flex: 1 1 18rem; min-width: 0; }
.part--share .btn { flex: none; border-radius: var(--radius-full); }
@media (max-width: 559px) {
  .part--share > .part__body { flex-direction: column; align-items: stretch; }
  .part--share .btn { width: 100%; }
}

/* The note is a callout, not a banner: it keeps a measure even when it has the column to itself. */
.note-card__body .prose, .part--watch .guidance__watch, .part--watch .prose { max-width: 66ch; }

/* The destinations sit on one baseline: uneven card heights read as an accident, not a choice. */
.grid--next > li { display: flex; }
.grid--next .card--next { width: 100%; align-items: flex-start; }
.grid--next .card--next .card__go { align-self: center; }

/*
 * The note and the watch read as prose, not as metadata.
 *
 * Both bodies were set at the small UI size — fourteen pixels inside a panel three hundred tall,
 * which is the size a caption is given, not a paragraph someone is meant to sit with. They carry
 * the same kind of sentence as the reading above them, so they take the same body size and the
 * same leading, and the panels give back a little of their block padding so the words gain the
 * height rather than the card.
 *
 * The kickers stay where they are: small, uppercase, the label on the panel rather than part of
 * what is said in it.
 */
.note-card__body .prose,
.part--watch .prose,
.part--watch .guidance__watch {
  font-size: var(--text-body);
  line-height: var(--lh-body);
}
.reading > .pair > .part--note,
.reading > .pair > .part--watch { padding: var(--space-4) var(--space-5) var(--space-5); }

/* ==========================================================================
   Question-first discovery, and the hands that reach it
   ========================================================================== */

/*
 * The question in the hero.
 *
 * The six questions are the hero's primary action, so they dress like one: a surface, a soft
 * shadow and an accent cue on every row, and no button above them competing for the tap. One
 * column on a phone, where the longest question ("Is this relationship right for me?") needs the
 * whole measure; two columns from the small tablet, inside the copy column on the desktop.
 */
.hero__ask { margin-top: var(--space-6); }
.hero__ask-label {
  margin-bottom: var(--space-3);
  font-size: var(--text-sm); font-weight: var(--weight-h3); color: var(--accent-ink);
}
.wonder {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-2);
}
.wonder__link {
  display: flex; align-items: center; gap: var(--space-3);
  min-height: 52px; padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4);
  border: var(--border-hairline) solid var(--border-soft);
  border-radius: var(--radius-md);
  background: var(--surface); box-shadow: var(--shadow-soft);
  text-decoration: none; color: var(--text-primary);
  transition: border-color var(--motion-fast) var(--ease-standard),
              box-shadow var(--motion-fast) var(--ease-standard),
              transform var(--motion-fast) var(--ease-standard);
}
.wonder__q {
  flex: 1 1 auto; min-width: 0;
  font-family: var(--font-display); font-size: var(--text-h3); line-height: var(--lh-h3);
}
.wonder__cue {
  flex: none; display: inline-grid; place-items: center;
  width: 36px; height: 36px; border-radius: var(--radius-full);
  background: var(--accent); color: var(--on-accent);
  transition: transform var(--motion-fast) var(--ease-standard);
}
.wonder__link:hover { border-color: var(--border-strong); transform: translateY(-2px); box-shadow: var(--shadow-lift); }
.wonder__link:hover .wonder__cue { transform: translateX(3px); }
.wonder__link:active { transform: translateY(1px); }
.wonder__link:focus-visible { outline: var(--border-selected) solid var(--accent); outline-offset: 3px; }
/* The quiet catalogue link sits under the list, and the reassurance row closes the copy. On the
   narrowest phones the sentence wraps; the last word carries the arrow with it onto the second
   line, so the arrow never sits alone at the far edge of the first. */
.is-home .hero__ask .hero__actions { margin-top: var(--space-4); }
.link-quiet--wrap {
  display: inline; min-height: 0;
  /* The 44px hit area comes from the padding rather than a flex box, so the sentence can wrap
     like text. The `lh` form centres exactly; the token form is the fallback. */
  padding-block: var(--space-2);
  padding-block: calc((44px - 1lh) / 2);
}
.link-quiet--wrap .arrow { vertical-align: middle; margin-inline-start: var(--space-2); }
.link-quiet__tail { white-space: nowrap; }
.is-home .hero__ask + .hero__chips { margin-top: var(--space-6); }
@media (min-width: 560px) { .wonder { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* Beside the artwork the copy column is about five hundred pixels: two columns broke every
   question onto two lines, so the list goes back to one column and each question keeps its line. */
@media (min-width: 1024px) { .wonder { grid-template-columns: minmax(0, 1fr); } }
@media (prefers-reduced-motion: reduce) {
  .wonder__link:hover, .wonder__link:hover .wonder__cue { transform: none; }
}

/*
 * Hit areas.
 *
 * The breadcrumb and the footer are how a reader gets back, and both were twenty-two pixels tall —
 * under the twenty-four the guidelines ask for and well under the forty-four a thumb wants. The
 * height moves from the list's padding into the links themselves, so the rows keep the height they
 * already had and the targets grow inside them. Nothing moves on the page.
 */
.crumbs { padding-block: var(--space-1); }
.crumbs a, .crumbs li > span[aria-current] {
  display: inline-flex; align-items: center; min-height: 44px;
}
.footer a { display: inline-flex; align-items: center; min-height: 44px; }
.footer__cols a { min-height: 40px; }

/* ============================================================================
 * Homepage — the supplied-photograph layout.
 *
 * One visual anchor per section and nothing spare: a hero photograph that runs to the edge of the
 * window, six tinted category cards, one featured calculator, three steps, and a closing band.
 * Every picture is a file in `src/assets/hero/` published by the ordinary pipeline and referenced
 * by its built path — nothing inlined, encoded or fetched from anywhere else.
 *
 * This block is last in the stylesheet on purpose: the sections above it still carry the previous
 * homepage's rules, and source order is what settles the few selectors the two have in common.
 * ========================================================================== */

/* ---------- Hero ---------- */

/*
 * The photograph is not a column, it is the room. Stacked it is an ordinary band under the copy,
 * at its own proportions; from 1024 up it is laid from the middle of the band to the right edge
 * of the window and the copy sits over its calm left side.
 */
/*
 * Stacked, the copy is read before the picture: the photograph is a sibling of the text rather
 * than a cell inside it, because from 1024 up it has to escape the wrap and reach the window's
 * edge — so the order is set here rather than by the document.
 */
/*
 * The hero is a contained card, the width of every other section. The band around it carries
 * nothing — no background, no rounding, and above all no clipping: the search panel hangs below
 * the field and has to be able to leave. The photograph is clipped by its own box instead, which
 * is the only thing the clipping was ever for.
 */
.is-home .hero {
  position: relative; overflow: visible;
  background: none; border-radius: 0;
  padding-block: var(--space-6) var(--space-8);
}
.hero__card {
  position: relative; overflow: visible;
  border-radius: var(--radius-xl);
  background: linear-gradient(165deg, var(--wash-blush) 0%, var(--wash-cream) 64%, var(--background) 100%);
}
.hero__copy { position: relative; z-index: 1; padding: var(--space-8) var(--space-6) var(--space-7); }
/* Stacked, the picture is the card's foot and takes the card's bottom corners with it. */
.hero__bleed {
  position: relative; width: 100%; overflow: hidden;
  border-end-start-radius: var(--radius-xl); border-end-end-radius: var(--radius-xl);
}
.hero__bleed-img { display: block; width: 100%; height: auto; }

/* ---------- Hero search field ---------- */

.hero__search {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center;
  gap: var(--space-3); margin-top: var(--space-7); max-width: 420px;
  padding: var(--space-2) var(--space-2) var(--space-2) var(--space-5);
  border: var(--border-hairline) solid var(--border-soft); border-radius: var(--radius-full);
  background: var(--surface); box-shadow: var(--shadow-lift);
}
.hero__search:focus-within { outline: 3px solid var(--focus); outline-offset: 3px; }
.hero__search-mark { display: grid; place-items: center; color: var(--text-muted); }
.hero__search-mark .icon { width: 19px; height: 19px; }
.hero__search-field {
  min-width: 0; padding: var(--space-3) 0; border: 0; background: transparent;
  font: inherit; font-size: var(--text-body); color: var(--text-primary);
}
.hero__search-field::placeholder { color: var(--text-muted); }
.hero__search-field:focus { outline: none; }
.hero__search-field::-webkit-search-cancel-button { display: none; }
.hero__search-go {
  display: grid; place-items: center; width: 44px; height: 44px;
  border: 0; border-radius: var(--radius-full);
  background: var(--accent); color: var(--on-accent); cursor: pointer;
  transition: background var(--ease-standard) 160ms;
}
.hero__search-go:hover { background: var(--accent-hover); }
.hero__search-go:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }

/* The nudge under the field: handwritten in tone, ordinary text in the document. */
.hero__hint {
  display: grid; grid-template-columns: auto 1fr; align-items: center;
  gap: 0 var(--space-3); margin: var(--space-5) 0 0 var(--space-4);
}
.hero__hint-mark { grid-row: 1 / span 2; width: 42px; color: var(--accent); }
.hero__hint-mark svg { display: block; width: 100%; height: auto; }
.hero__hint-lead { align-self: end; color: var(--accent-ink); font-size: var(--text-h3); line-height: 1.15; }
.hero__hint-sub { align-self: start; color: var(--text-muted); font-size: var(--text-sm); }

/* ---------- "Explore Our Calculators" ---------- */

.band__head--mid { text-align: center; margin-bottom: var(--space-6); }
.band__lede { margin-top: var(--space-4); color: var(--text-secondary); max-width: 52ch; }
.band__head--mid .band__lede { margin-inline: auto; }

.cats { display: grid; gap: var(--space-4); }
.cats > li { display: grid; }
/*
 * Each card is its category's own colour: mark, name, line, then the same circular cue at the
 * foot. The description row takes the slack, so six cards of different text lengths still end
 * their cue on one line across.
 */
.cat {
  /*
   * The rows hug their content and the group sits centred, so the spare height on a short card is
   * shared above and below rather than opening as a gap over the cue. Every card in the row is
   * still the height of the tallest, which is what keeps the band reading as one strip.
   */
  display: grid; grid-template-rows: repeat(4, auto); align-content: center;
  justify-items: center; text-align: center;
  gap: var(--space-2); padding: var(--space-5) var(--space-4);
  border-radius: var(--radius-lg); background: var(--surface);
  color: inherit; text-decoration: none;
  transition: transform var(--ease-standard) 160ms, box-shadow var(--ease-standard) 160ms;
}
.cat:hover { transform: translateY(-3px); box-shadow: var(--shadow-lift); }
.cat:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
.cat__icon { display: grid; place-items: center; }
.cat__icon .icon { width: 28px; height: 28px; }
.cat__name { font-size: var(--text-h3); font-weight: var(--weight-h3); color: var(--text-primary); }
.cat__line { font-size: var(--text-sm); color: var(--text-secondary); text-wrap: balance; }
/* The cue is the card's own mark, not a separate target: the whole card is the link. */
.cat__cue {
  display: grid; place-items: center; width: 30px; height: 30px; margin-top: var(--space-1);
  border-radius: var(--radius-full); background: var(--surface);
}
.cat__cue .icon { width: 16px; height: 16px; }

.cat[data-cat="crush"] { background: var(--tint-crush); }
.cat[data-cat="crush"] .cat__icon, .cat[data-cat="crush"] .cat__cue { color: var(--mark-crush); }
.cat[data-cat="dating"] { background: var(--tint-dating); }
.cat[data-cat="dating"] .cat__icon, .cat[data-cat="dating"] .cat__cue { color: var(--mark-dating); }
.cat[data-cat="relationship"] { background: var(--tint-relationship); }
.cat[data-cat="relationship"] .cat__icon, .cat[data-cat="relationship"] .cat__cue { color: var(--mark-relationship); }
.cat[data-cat="relationship-health"] { background: var(--tint-relationship-health); }
.cat[data-cat="relationship-health"] .cat__icon, .cat[data-cat="relationship-health"] .cat__cue { color: var(--mark-relationship-health); }
.cat[data-cat="ex-breakup"] { background: var(--tint-ex-breakup); }
.cat[data-cat="ex-breakup"] .cat__icon, .cat[data-cat="ex-breakup"] .cat__cue { color: var(--mark-ex-breakup); }
.cat[data-cat="fun"] { background: var(--tint-fun); }
.cat[data-cat="fun"] .cat__icon, .cat[data-cat="fun"] .cat__cue { color: var(--mark-fun); }

/* ---------- One featured calculator ---------- */

/*
 * One card, not two. The copy carries the padding and the picture carries none: it runs to the
 * card's own edges and is cut only by the card's corner, so the two read as a single banner
 * rather than a text panel sitting beside a picture panel.
 */
.featured {
  display: grid; gap: 0; align-items: stretch; padding: 0;
  border-radius: var(--radius-xl); overflow: hidden;
  background: linear-gradient(120deg, var(--tint-crush) 0%, var(--wash-blush) 100%);
}
.featured__copy { padding: var(--space-7) var(--space-6); }
.featured__badge { margin-bottom: var(--space-3); color: var(--accent-ink); font-size: var(--text-sm); font-weight: var(--weight-h3); }
.featured__title { margin: 0; }
.featured__lede { margin: var(--space-4) 0 var(--space-6); color: var(--text-secondary); max-width: 40ch; }
/* No radius and no margin of its own — the card's `overflow` is what shapes it. */
.featured__figure { border-radius: 0; overflow: hidden; min-height: 0; }
.featured__figure-img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 38%; }

/* ---------- "How LoveBeat works" ---------- */

/*
 * Three steps reading left to right, a chevron between one and the next. The chevrons are list
 * items so the row stays one grid, and they are hidden from assistive technology, which already
 * has the ordered list.
 */
.steps3 { display: grid; gap: var(--space-6); margin: 0; padding: 0; list-style: none; justify-items: center; }
.steps3__joint { display: none; color: var(--border-strong); opacity: 0.5; }
.steps3__joint .icon { width: 22px; height: 22px; }
.step3 { display: grid; justify-items: center; text-align: center; gap: var(--space-3); max-width: 34ch; }
.step3__mark {
  display: grid; place-items: center; width: 62px; height: 62px;
  border-radius: var(--radius-full); background: var(--wash-blush); color: var(--accent);
}
.step3__mark .icon { width: 26px; height: 26px; }
.step3__title { font-size: var(--text-h3); font-weight: var(--weight-h3); color: var(--text-primary); }
.step3__body { color: var(--text-muted); font-size: var(--text-sm); }

/* ---------- Closing call to action ---------- */

/*
 * The photograph is atmosphere and the words are words: the heading, the line under it and the
 * button are ordinary HTML, never baked into the picture. A wash of the page's own ground sits
 * between the two and stays solid past wherever the copy ends, so the text keeps the contrast the
 * design system already verifies rather than negotiating it with a photograph.
 */
.cta {
  position: relative; isolation: isolate; overflow: hidden;
  min-height: 440px; display: grid; align-items: start;
  border-radius: var(--radius-xl); background: var(--wash-blush);
}
.cta__figure { position: absolute; inset: 0; z-index: -2; }
.cta__figure-img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 60% 100%; }
.cta::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to bottom, var(--background) 0%, var(--background) 56%, transparent 90%);
}
.cta__copy { position: relative; padding: var(--space-8) var(--space-6) 0; max-width: 46ch; }
.cta__eyebrow { color: var(--accent-ink); }
.cta__title { margin: var(--space-3) 0 0; }
.cta__lede { margin: var(--space-3) 0 0; color: var(--text-secondary); }
.cta__action { position: relative; justify-self: start; margin: var(--space-6) var(--space-6) var(--space-8); }

/* ============================================================================
 * Homepage — breakpoints, ascending.
 * ========================================================================== */

/*
 * The banner sits closer to its neighbours than a full section break: it is one component, not a
 * chapter, and the space it had above and below read as a gap in the page.
 */
.band--cats { padding-bottom: calc(var(--rhythm) * 0.62); }
.band--featured { padding-bottom: calc(var(--rhythm) * 0.62); }
/*
 * The closing band runs straight into the footer. The footer changes colour and carries its own
 * rule, so it separates itself; the band adds nothing under its last card, and on this page the
 * footer's own lead-in is trimmed to a hairline gap. Scoped to the homepage — every other page
 * ends on ordinary content and still wants the full lead-in.
 */
.band--cta { padding-bottom: 0; }
.is-home .footer { margin-top: var(--space-4); }

/*
 * One under another on a phone, each card is one row rather than a stack: the mark on the left,
 * the name over its line, the cue on the right. Stacked, the mark and the cue each took a row of
 * their own and the six cards ran well over a screen; in one row a card is only as tall as its two
 * lines of text. The parts, colours and order are the ones every wider layout shows.
 */
@media (max-width: 559px) {
  .cat {
    grid-template-columns: auto minmax(0, 1fr) auto; grid-template-rows: auto auto;
    justify-items: start; text-align: start;
    gap: 0 var(--space-4); padding: var(--space-4) var(--space-5);
  }
  .cat__icon { grid-column: 1; grid-row: 1 / span 2; }
  .cat__name { grid-column: 2; grid-row: 1; align-self: end; }
  .cat__line { grid-column: 2; grid-row: 2; align-self: start; }
  .cat__cue { grid-column: 3; grid-row: 1 / span 2; align-self: center; margin-top: 0; }
}
/* The narrowest phones give the text the room the sides and the gaps can spare — the sides close to
   what the six-across row uses — so the longest name and the longest line still take one line each. */
@media (max-width: 359px) {
  .cat { column-gap: var(--space-2); padding-inline: var(--space-3); }
}
/*
 * The three steps, one under another until they sit side by side at 768, are one row each: the
 * mark on the left, the title over its sentence. Stacked and centred, each mark took a row of its
 * own. The list keeps a reading measure and stays centred in the band.
 */
@media (max-width: 767px) {
  .steps3 { gap: var(--space-4); justify-items: stretch; max-width: 30rem; margin-inline: auto; }
  .step3 {
    grid-template-columns: auto minmax(0, 1fr); align-items: center;
    justify-items: start; text-align: start; gap: 0 var(--space-4); max-width: none;
  }
  .step3__mark { grid-row: 1 / span 2; width: 48px; height: 48px; }
  .step3__mark .icon { width: 22px; height: 22px; }
  .step3__title { grid-column: 2; align-self: end; }
  .step3__body { grid-column: 2; align-self: start; }
}

@media (min-width: 560px) {
  .cats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 768px) {
  .cats { grid-template-columns: repeat(3, minmax(0, 1fr)); }

  .steps3 { grid-template-columns: repeat(5, auto); align-items: start; justify-content: center; gap: var(--space-5); }
  .steps3__joint { display: grid; place-items: center; align-self: center; }
  .step3 { max-width: 25ch; }

  /* Text left, picture right, both the full height of the one card. */
  .featured { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0; padding: 0; }
  .featured__copy { padding: var(--space-8) var(--space-9); align-self: center; }

  /* The closing band puts its button beside the words rather than under them. */
  .cta { min-height: 260px; align-items: center; grid-template-columns: auto minmax(0, 1fr); }
  .cta__figure-img { object-position: center; }
  .cta::before { background: linear-gradient(to right, var(--background) 0%, var(--background) 44%, transparent 88%); }
  .cta__copy { padding: var(--space-8) 0 var(--space-8) var(--space-8); max-width: 32ch; }
  .cta__action { margin: 0; }
}

@media (min-width: 1024px) {
  .cats { grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--space-3); }
  .cat { padding: var(--space-5) var(--space-3); }

  /*
   * Side by side inside the one card. The photograph is laid from just left of centre to the
   * card's own right edge and fills its full height, so its right edge is the card's right edge
   * and its foot is the card's foot — no gap, no second panel, nothing floating.
   */
  .is-home .hero { padding-block: var(--space-7) var(--space-8); }
  /*
   * Side by side, the card's ground runs left to right and settles on the exact blush the
   * photograph's own wash starts from. That is what removes the seam: at the picture's left edge
   * the card is already the colour the scrim begins with, so there is no line to see.
   */
  .hero__card {
    min-height: 400px;
    background: linear-gradient(to right, var(--wash-cream) 0%, var(--wash-blush) 40%, var(--wash-blush) 100%);
  }
  .hero__copy { padding: var(--space-8) var(--space-8); max-width: 33rem; }
  /*
   * The slot is kept wide and the card short, so its shape stays near the file's own 16:9 and
   * `cover` has little to take. What it does take comes off the left, where the file is only
   * blurred background — the woman, the cat and the stack of books all sit in the right of the
   * frame and stay whole.
   */
  .hero__bleed {
    position: absolute; inset-block: 0; inset-inline: 42% 0; width: auto; z-index: 0;
    border-radius: 0;
    border-start-end-radius: var(--radius-xl); border-end-end-radius: var(--radius-xl);
  }
  .hero__bleed-img { width: 100%; height: 100%; object-fit: cover; object-position: 88% 50%; }
  /*
   * The join. The file carries its own soft blur down its left side, and this lays the card's own
   * ground over the first slice of it, so the picture arrives out of the background rather than
   * starting at a vertical edge.
   */
  .hero__bleed::after {
    content: ''; position: absolute; inset-block: 0; inset-inline-start: 0; width: 38%;
    background: linear-gradient(to right, var(--wash-blush) 0%,
      color-mix(in srgb, var(--wash-blush) 62%, transparent) 40%, transparent 100%);
    pointer-events: none;
  }
}

@media (min-width: 1280px) {
  .is-home .hero { padding-block: var(--space-8) var(--space-9); }
  .hero__card { min-height: 420px; }
  .hero__bleed { inset-inline-start: 41%; }
}

@media (max-width: 420px) {
  .cta { min-height: 420px; }
  .cta__copy { padding: var(--space-7) var(--space-5) 0; }
  .cta__action { margin: var(--space-5) var(--space-5) var(--space-7); }
  .featured__copy { padding: var(--space-6) var(--space-5); }
  .hero__search { margin-top: var(--space-6); padding-left: var(--space-4); }
  .hero__hint { margin-left: var(--space-2); }
}

/* ---------- Header, second pass ---------- */

/* The tagline sits under the name rather than beside it, so the mark and two short lines read as
   one block at every width the bar has to hold. */
.brand__kind { text-transform: none; letter-spacing: 0; }
.header__find {
  display: none; place-items: center; width: 40px; height: 40px;
  border-radius: var(--radius-full); color: var(--text-secondary); text-decoration: none;
}
.header__find:hover { background: var(--wash-blush); color: var(--accent-ink); }
.header__find:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.header__find .icon { width: 20px; height: 20px; }
@media (min-width: 1024px) { .header__find { display: grid; } }

/* The tagline is the first thing to go when the bar runs out of room: the name still identifies
   the site, and the line itself is repeated in the footer of every page. */
@media (max-width: 479px) { .header .brand__kind { display: none; } }

/* ---------- "Find a calculator" — the hero's search panel ---------- */

/*
 * The panel hangs off the field rather than pushing the hero open, so the section keeps its
 * height whatever the reader types. It is capped and scrolls rather than growing: three
 * suggestions is the most it ever shows, and on a phone it must not swallow the screen.
 */
.hero__finder { position: relative; z-index: 3; max-width: 420px; }
.find {
  position: absolute; inset-inline: 0; top: calc(100% + var(--space-3)); z-index: 4;
  max-height: min(56vh, 380px); overflow-y: auto;
  padding: var(--space-4);
  border: var(--border-hairline) solid var(--border-soft); border-radius: var(--radius-lg);
  background: var(--surface); box-shadow: var(--shadow-lift);
}
.find[hidden] { display: none; }

.find__lead { font-weight: var(--weight-h3); color: var(--text-primary); }
.find__help { margin-top: var(--space-2); color: var(--text-muted); font-size: var(--text-sm); }

.find__list { display: grid; gap: var(--space-1); margin: 0; padding: 0; list-style: none; }
.find__list:empty { display: none; }
.find__option { margin: 0; }
.find__hit {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center;
  gap: 0 var(--space-3); padding: var(--space-3); min-height: 44px;
  border-radius: var(--radius-md); color: inherit; text-decoration: none;
}
/* Placed explicitly: left to auto-placement the cue takes the first cell and pushes the name
   into the arrow's column. */
.find__hit-name { grid-column: 1; grid-row: 1; font-weight: var(--weight-h3); color: var(--text-primary); }
.find__hit-blurb { grid-column: 1; grid-row: 2; color: var(--text-muted); font-size: var(--text-sm); }
.find__hit-cue { grid-column: 2; grid-row: 1 / span 2; align-self: center; color: var(--accent); }
.find__option:hover .find__hit,
.find__option.is-active .find__hit { background: var(--wash-blush); }
.find__option.is-active .find__hit-name { color: var(--accent-ink); }

/* The empty state's three openers: buttons, because they fill the field rather than navigate. */
.find__examples { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: var(--space-3) 0 0; padding: 0; list-style: none; }
.find__example {
  min-height: 44px; padding: var(--space-2) var(--space-4);
  border: var(--border-hairline) solid var(--border-soft); border-radius: var(--radius-full);
  background: var(--wash-blush); color: var(--accent-ink);
  font: inherit; font-size: var(--text-sm); cursor: pointer;
}
.find__example:hover { background: var(--tint-crush); }
.find__example:focus-visible, .find__hit:focus-visible, .find__browse:focus-visible {
  outline: 3px solid var(--focus); outline-offset: 2px;
}

.find__browse {
  display: inline-flex; align-items: center; gap: var(--space-2);
  margin-top: var(--space-4); padding: var(--space-2) 0; min-height: 44px;
  color: var(--accent-ink); font-size: var(--text-sm); font-weight: var(--weight-h3);
  text-decoration: none;
}
.find__browse:hover { text-decoration: underline; }
.find__list:not(:empty) + .find__browse { border-top: var(--border-hairline) solid var(--border-soft); width: 100%; }

@media (max-width: 559px) {
  .hero__finder { max-width: 100%; }
  .find { max-height: min(50vh, 320px); padding: var(--space-3); }
}

/* ---------- Footer, tightened ---------- */

/*
 * The footer's link rows keep a full thumb target on a phone, where the footer is the last thing
 * a reader scrolls past and taps. From 1024 up the pointer is precise, so the rows close up and
 * the column stops being taller than the list it holds — still well clear of the 24px minimum.
 */
@media (min-width: 1024px) {
  .footer__cols a { min-height: 32px; }
  .footer li + li { margin-top: var(--space-1); }
}

/*
 * On a phone the footer was one long column: eleven links at a full row each, three headings and
 * generous section gaps, so it ran close to a thousand pixels after the page had already ended.
 * Below the tablet layout the links now sit in two columns — Explore on the left, About and Legal
 * stacked on the right — and each row keeps a 36px target with no gap between rows, still well
 * above the 24px minimum and never overlapping. The inline "What that means" link is a link in a
 * sentence, so it goes back to being inline: as a 44px flex box it opened a tall gap mid-sentence.
 * From 768 up nothing changes; the three-column layout already sits on one screen.
 */
@media (max-width: 767px) {
  .footer { padding-block: var(--space-6); }
  .footer__top { gap: var(--space-5); }
  .footer__line { margin-top: var(--space-2); }
  .footer__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); }
  .footer__cols > :first-child { grid-row: span 2; }
  .footer h2 { margin-bottom: var(--space-1); }
  .footer__cols a { min-height: 36px; }
  .footer li + li { margin-top: 0; }
  .footer__fine { margin-top: var(--space-4); padding-top: var(--space-3); }
  .footer__fine a { display: inline; min-height: 0; }
}
