/* =============================================================================
   Dental Deals — v2 · SITE CHROME + PRIMITIVES
   -----------------------------------------------------------------------------
   Ports to: app/assets/stylesheets/marketing/site.css

   Chrome: .site-banners, .site-nav
   Primitives: .wrap, .btn, .card, .pill, .chip, .eyebrow, .display*, .lede*,
               .section*, .field*, .ico, .stat-tile, .accordion, .modal

   Rules held here:
     · Every button is a pill (--radius-pill) at every size.
     · Every card is --radius-card, border: none, on --shadow-card.
     · Every input is --radius-input / --border-input with the mint focus ring.
     · The ONLY borders are the nav hairline, input fields, and a 1px --hairline
       divider. Nothing else carries a line.
     · No coloured left-accent stripes. Tinted background + even radius instead.
     · No hex literal below this line. Tokens only.
   ============================================================================= */

html, body { margin: 0; padding: 0; }
body.is-locked { overflow: hidden; }

/* ═══ LAYOUT ════════════════════════════════════════════════════════════════ */
.wrap        { max-width: var(--wrap-max);    margin: 0 auto; padding: 0 var(--wrap-pad); }
.wrap-narrow { max-width: var(--wrap-narrow); margin: 0 auto; padding: 0 var(--wrap-pad); }
@media (max-width: 1023px) { .wrap, .wrap-narrow { padding: 0 24px; } }
@media (max-width: 640px)  { .wrap, .wrap-narrow { padding: 0 18px; } }
@media (max-width: 480px)  { .wrap, .wrap-narrow { padding: 0 16px; } }

section { position: relative; }
.bg-quiet { background: var(--surface-quiet); }
.bg-ink   { background: var(--surface-ink); color: var(--text-on-ink); }

.section        { padding: var(--sp-26) 0; }
.section--sm    { padding: var(--sp-16) 0; }
.section--lg    { padding: var(--sp-30) 0; }
.section--flush { padding-top: 0; }
.section-head   { max-width: 720px; margin-bottom: var(--sp-14); }
.section-head--wide { max-width: 820px; }
.section-head > * + * { margin-top: var(--sp-4); }
.section-head .lede-lg { margin-top: var(--sp-4); }
.section-head--center { margin-inline: auto; text-align: center; }
.section-head--center .lede, .section-head--center .lede-lg { margin-inline: auto; }

@media (max-width: 767px) {
  .section     { padding: var(--sp-16) 0; }
  .section--sm { padding: var(--sp-12) 0; }
  .section--lg { padding: var(--sp-18) 0; }
  .section-head { margin-bottom: var(--sp-8); }
}

.divider { border: 0; border-top: var(--border-hairline) solid var(--hairline); margin: var(--sp-8) 0; }

/* ═══ TYPE ROLES ════════════════════════════════════════════════════════════ */
.eyebrow {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--font-sans);
  font-size: var(--e-eyebrow); font-weight: var(--fw-semibold);
  letter-spacing: var(--tk-eyebrow); text-transform: uppercase;
  color: var(--text-tertiary);
}
/* The 6px mint dot. Kept, retinted to brand-500, globally on all 14 marketing
   pages — the one brand signature that survives losing forest green. Called
   once here, never per page. */
.eyebrow::before {
  content: ""; flex: 0 0 auto;
  width: 6px; height: 6px; border-radius: var(--radius-pill);
  background: var(--brand-500);
}
.eyebrow--plain::before { display: none; }
.eyebrow--ink { color: var(--text-on-ink-soft); }
.eyebrow--ink::before { background: var(--brand-400); }

.display {
  margin: 0; font-family: var(--font-display);
  font-size: var(--e-hero-size); line-height: var(--e-hero-lh);
  letter-spacing: var(--e-hero-tk); font-weight: var(--fw-bold);
  color: var(--text); text-wrap: balance;
}
.display-md {
  margin: 0; font-family: var(--font-display);
  font-size: var(--e-section-size); line-height: var(--e-section-lh);
  letter-spacing: var(--e-section-tk); font-weight: var(--fw-bold);
  color: var(--text); text-wrap: balance;
}
.display-sm {
  margin: 0; font-family: var(--font-display);
  font-size: var(--e-subsection-size); line-height: var(--e-subsection-lh);
  letter-spacing: var(--e-subsection-tk); font-weight: var(--fw-bold);
  color: var(--text); text-wrap: balance;
}
.display--ink, .display-md--ink, .display-sm--ink { color: var(--text-on-ink); }
.display em, .display-md em, .display-sm em { font-style: normal; color: var(--brand-700); }
.display--ink em { color: var(--brand-400); }

.lede {
  margin: 0; font-size: var(--e-lede); line-height: var(--lh-body);
  color: var(--text-secondary); max-width: 580px; text-wrap: pretty;
}
.lede-lg {
  margin: 0; font-size: var(--e-lede); line-height: var(--lh-body);
  color: var(--text-secondary); max-width: 640px; text-wrap: pretty;
}
.lede--ink, .lede-lg--ink { color: var(--text-on-ink-soft); }
.prose { font-size: var(--e-body); line-height: 1.6; color: var(--text-secondary); text-wrap: pretty; }
.prose strong, .prose b { color: var(--text); font-weight: var(--fw-semibold); }
.meta      { font-size: var(--e-meta); color: var(--text-tertiary); }
.meta-micro{ font-size: var(--e-micro); color: var(--text-tertiary); }
.tnum      { font-variant-numeric: tabular-nums; }
.emph      { color: var(--text); font-weight: var(--fw-semibold); }

/* Icon glyphs are sized by --ico, not font-size: this is a box dimension, not
   text, and routing it through font-size would put non-text on the type scale. */
.ico { display: inline-flex; width: var(--ico, 1em); height: var(--ico, 1em); flex: 0 0 auto; line-height: 0; }
.ico svg { width: 100%; height: 100%; display: block; }
.ico--16 { --ico: 16px; }
.ico--18 { --ico: 18px; }
.ico--20 { --ico: 20px; }
.ico--24 { --ico: 24px; }
.ico--28 { --ico: 28px; }

/* ═══ BUTTONS — pills, every size ═══════════════════════════════════════════ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  height: 44px; padding: 0 20px;
  border: 0; border-radius: var(--radius-pill);
  font-family: var(--font-sans); font-size: var(--e-body-sm);
  font-weight: var(--fw-semibold); letter-spacing: -0.005em;
  background: var(--action-quiet-bg); color: var(--text);
  white-space: nowrap; cursor: pointer; text-decoration: none;
  transition: background-color var(--dur-hover-out) linear, color var(--dur-hover-out) linear, box-shadow var(--dur-lift) var(--ease-out);
}
.btn:hover { background: var(--action-quiet-hover); color: var(--text); }
.btn:active { transition-duration: var(--dur-press); }
.btn .ico { --ico: 16px; }
.btn-lg { height: 52px; padding: 0 26px; font-size: var(--e-body); }
.btn-sm { height: 36px; padding: 0 16px; font-size: var(--e-meta); }
.btn-xs { height: 30px; padding: 0 13px; font-size: var(--e-micro); }
.btn--block { width: 100%; }

.btn-primary { background: var(--action-bg); color: var(--text-on-brand); }
.btn-primary:hover { background: var(--action-bg-hover); color: var(--text-on-brand); }

/* Demoted from primary. Only where a page genuinely needs a second weight of
   button; never the page's primary action. */
.btn-ink { background: var(--action-ink-bg); color: var(--text-on-ink); }
.btn-ink:hover { background: var(--action-ink-bg-hover); color: var(--text-on-ink); }

.btn-outline { background: var(--surface); color: var(--text); box-shadow: inset 0 0 0 var(--border-input) var(--hairline); }
.btn-outline:hover { background: var(--gray-50); box-shadow: inset 0 0 0 var(--border-input) var(--gray-300); }

/* On an ink band. */
.btn-onink { background: var(--white); color: var(--gray-950); }
.btn-onink:hover { background: var(--gray-100); color: var(--gray-950); }
.btn-ghost-ink { background: transparent; color: var(--text-on-ink); box-shadow: inset 0 0 0 var(--border-input) var(--hairline-on-ink); }
.btn-ghost-ink:hover { background: rgba(255, 255, 255, 0.08); color: var(--text-on-ink); }

.btn-link {
  height: auto; padding: 0; background: transparent; color: var(--text-accent);
  font-weight: var(--fw-semibold);
}
.btn-link:hover { background: transparent; color: var(--brand-600); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: 0.45; pointer-events: none; }
.btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.btn-onink:focus-visible, .btn-ghost-ink:focus-visible { box-shadow: 0 0 0 3px rgba(255,255,255,0.35); }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
.btn-row--center { justify-content: center; }
@media (max-width: 480px) {
  .btn-row { gap: var(--sp-2); }
  .btn-row .btn { flex: 1 1 100%; }
}

/* Disabled-with-reason wrapper (broker page, seller accounts). */
.btn-blocked { position: relative; display: inline-block; cursor: not-allowed; }
.btn-blocked .btn { opacity: 0.45; pointer-events: none; user-select: none; }
.btn-blocked::after {
  content: attr(data-tooltip);
  position: absolute; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%);
  background: var(--gray-950); color: var(--white);
  font-size: var(--e-micro); font-weight: var(--fw-medium); white-space: nowrap;
  padding: 6px 11px; border-radius: var(--radius-pill);
  pointer-events: none; opacity: 0; transition: opacity var(--dur-menu) var(--ease-out);
}
.btn-blocked:hover::after { opacity: 1; }

/* ═══ PILLS / CHIPS / BADGES ════════════════════════════════════════════════ */
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  height: 24px; padding: 0 10px; border-radius: var(--radius-pill);
  font-size: var(--text-2xs); font-weight: var(--fw-semibold);
  letter-spacing: var(--tk-wide); text-transform: uppercase;
  background: var(--gray-50); color: var(--text-secondary);
}
.pill--success { background: var(--status-success-bg); color: var(--status-success-text); }
.pill--info    { background: var(--status-info-bg);    color: var(--status-info-text); }
.pill--warning { background: var(--status-warning-bg); color: var(--status-warning-text); }
.pill--danger  { background: var(--status-danger-bg);  color: var(--status-danger-text); }
.pill--teal    { background: var(--status-teal-bg);    color: var(--status-teal-text); }
.pill--brand   { background: var(--brand-50);          color: var(--brand-700); }
.pill--ink     { background: var(--gray-950);          color: var(--white); }
/* Coral: new / urgent only. */
.pill--new     { background: var(--coral-50);          color: var(--coral-600); }
.pill--onink   { background: rgba(255,255,255,0.14);   color: var(--text-on-ink); }

.chip {
  display: inline-flex; align-items: center; gap: 6px;
  height: 32px; padding: 0 14px; border: 0; border-radius: var(--radius-pill);
  font-family: var(--font-sans); font-size: var(--e-meta); font-weight: var(--fw-medium);
  background: var(--gray-50); color: var(--text-secondary); cursor: pointer;
  transition: background-color var(--dur-hover-out) linear, color var(--dur-hover-out) linear;
}
.chip:hover { background: var(--gray-100); color: var(--text); }
/* Reads --action-bg, not --brand-500 directly: an active chip is a filled
   brand-coloured control carrying white text, so it needs the same accessible
   fill the primary button does. */
.chip[aria-pressed="true"], .chip.is-on { background: var(--action-bg); color: var(--text-on-brand); }
.chip[aria-pressed="true"]:hover, .chip.is-on:hover { background: var(--action-bg-hover); color: var(--text-on-brand); }
.chip:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.chip-row { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.chip__x { display: inline-flex; font-size: var(--e-meta); opacity: 0.7; }
.chip__x:hover { opacity: 1; }

/* ═══ CARDS ═════════════════════════════════════════════════════════════════ */
.card {
  background: var(--surface); border: none; border-radius: var(--radius-card);
  box-shadow: var(--shadow-card); padding: var(--sp-7);
}
.card--tile   { border-radius: var(--radius-tile); }
.card--flush  { padding: 0; overflow: hidden; }
.card--quiet  { background: var(--surface-quiet); box-shadow: none; }
.card--tint   { background: var(--surface-tint); box-shadow: none; }
.card--ink    { background: var(--surface-ink); color: var(--text-on-ink); box-shadow: none; }
.card--pad-lg { padding: var(--sp-10); }

/* Clickable cards lift. Rows inside a card tint instead (--row-hover). */
.card--link { display: block; color: inherit; transition: box-shadow var(--dur-card) var(--ease-out), transform var(--dur-card) var(--ease-out); }
.card--link:hover { box-shadow: var(--shadow-lift); transform: translateY(var(--lift-y)); color: inherit; }
.card--link:focus-visible { outline: none; box-shadow: var(--shadow-lift), var(--focus-ring); }

.card-row { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-4) var(--sp-5); }
.card-row + .card-row { border-top: var(--border-hairline) solid var(--hairline); }
a.card-row, button.card-row { width: 100%; color: inherit; background: none; border: 0; text-align: left; transition: background-color var(--dur-hover-out) linear; }
a.card-row:hover, button.card-row:hover { background: var(--row-hover); color: inherit; }

@media (max-width: 640px) {
  .card { padding: var(--sp-5); }
  .card--pad-lg { padding: var(--sp-6); }
}

/* ═══ STAT TILES ════════════════════════════════════════════════════════════ */
.stat-tile { border-radius: var(--radius-tile); background: var(--surface); box-shadow: var(--shadow-card); padding: var(--sp-4) var(--sp-5); }
.stat-tile__k { font-size: var(--e-eyebrow); font-weight: var(--fw-semibold); letter-spacing: var(--tk-eyebrow); text-transform: uppercase; color: var(--text-tertiary); margin-bottom: 6px; }
.stat-tile__v { font-family: var(--font-display); font-size: var(--e-stat); font-weight: var(--fw-bold); letter-spacing: var(--tk-tight); color: var(--text); font-variant-numeric: tabular-nums; line-height: var(--lh-tight); }
.stat-tile__v small { font-family: var(--font-sans); font-size: var(--e-meta); font-weight: var(--fw-medium); color: var(--text-tertiary); letter-spacing: 0; }
.stat-tile__d { font-size: var(--e-micro); font-weight: var(--fw-semibold); color: var(--status-success-text); margin-top: 4px; }
.stat-tile__d--down { color: var(--status-danger-text); }
.stat-tile__d--flat { color: var(--text-tertiary); }

.stat-tile--ink { background: rgba(255,255,255,0.05); box-shadow: none; }
.stat-tile--ink .stat-tile__k { color: var(--text-on-ink-quiet); }
.stat-tile--ink .stat-tile__v { color: var(--text-on-ink); }
.stat-tile--ink .stat-tile__d { color: var(--brand-400); }
.stat-tile--ink .stat-tile__d--down { color: var(--coral-500); }
.stat-tile--quiet { background: var(--gray-50); box-shadow: none; }

/* ═══ GRIDS ═════════════════════════════════════════════════════════════════ */
.grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-6); }
.grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-6); }
.grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--sp-5); }
@media (max-width: 1023px) { .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px)  { .grid-2, .grid-3, .grid-4 { grid-template-columns: minmax(0, 1fr); } }

/* ═══ FORM PRIMITIVES ═══════════════════════════════════════════════════════ */
.field { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
/* Label and its required marker are ONE group, so they must sit together.
   This row was `justify-content: space-between` to make room for a right-hand
   accessory (A2's `Forgot?` link opposite the Password label). The marker is not
   that accessory: space-between pushed the asterisk to the far edge, ~330px from
   the word it modifies, reading as an unrelated element above the input.
   The accessory now opts in with `margin-left: auto`, which keeps that pattern
   working without dragging `.req` along with it. */
.field__label { display: flex; align-items: baseline; justify-content: flex-start; gap: 4px; font-size: var(--e-meta); font-weight: var(--fw-semibold); color: var(--text-secondary); }
.field__label > a, .field__label > button, .field__label__end { margin-left: auto; }
.field__label .req { color: var(--status-danger-text); }
.field__hint { font-size: var(--e-micro); color: var(--text-tertiary); }
.field__err { display: none; font-size: var(--e-micro); font-weight: var(--fw-medium); color: var(--status-danger-text); }
.field.is-invalid .field__err { display: flex; align-items: center; gap: 5px; }

.input, .textarea {
  width: 100%; min-width: 0; height: 46px; padding: 0 14px;
  background: var(--surface); color: var(--text);
  border: var(--border-input) solid var(--hairline); border-radius: var(--radius-input);
  font-family: var(--font-sans); font-size: var(--e-body-sm); line-height: 1.4;
  transition: border-color var(--dur-menu) var(--ease-out), box-shadow var(--dur-menu) var(--ease-out);
}
.textarea { height: auto; min-height: 120px; padding: 12px 14px; resize: vertical; }
/* Placeholder and unselected-value text is TEXT the user has to read, so it is
   held to 4.5:1 and takes the tertiary step (#767676, 4.54:1 on white). It was
   --text-quaternary (#A3A3A3, 2.52:1), which failed WCAG 1.4.3 and was also a
   regression: the source's `.calc__input::placeholder` used --base-text-tertiary
   (#737373), a passing value. --text-quaternary stays reserved for NON-text
   marks only, where the ratio does not apply: row chevrons, list ::markers, TOC
   numerals. Never put it on a run of words. */
.input::placeholder, .textarea::placeholder { color: var(--text-tertiary); }
.input:focus, .textarea:focus { outline: none; border-color: var(--focus-border); box-shadow: var(--focus-ring); }
.field.is-invalid .input, .field.is-invalid .textarea { border-color: var(--status-danger-text); }
.field.is-invalid .input:focus, .field.is-invalid .textarea:focus { box-shadow: 0 0 0 3px var(--status-danger-bg); }
.input-prefixed { position: relative; display: flex; align-items: center; }
.input-prefixed__mark { position: absolute; left: 14px; font-size: var(--e-body-sm); font-weight: var(--fw-medium); color: var(--text-tertiary); pointer-events: none; }
.input-prefixed .input { padding-left: 30px; }

.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-4); }
@media (max-width: 640px) { .field-row { grid-template-columns: minmax(0, 1fr); } }

/* Custom select. No native <select> anywhere in this system. */
.select { position: relative; }
.select__btn {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2);
  width: 100%; height: 46px; padding: 0 14px; text-align: left;
  background: var(--surface); color: var(--text);
  border: var(--border-input) solid var(--hairline); border-radius: var(--radius-input);
  font-family: var(--font-sans); font-size: var(--e-body-sm); cursor: pointer;
  transition: border-color var(--dur-menu) var(--ease-out), box-shadow var(--dur-menu) var(--ease-out);
}
.select__btn[data-empty="true"] { color: var(--text-tertiary); }
.select__btn .ico { color: var(--text-tertiary); --ico: 16px; transition: transform var(--dur-menu) var(--ease-out); }
.select__btn:focus-visible { outline: none; border-color: var(--focus-border); box-shadow: var(--focus-ring); }
.select.is-open .select__btn { border-color: var(--focus-border); box-shadow: var(--focus-ring); }
.select.is-open .select__btn .ico { transform: rotate(180deg); }
.select__menu {
  position: absolute; z-index: 60; top: calc(100% + 6px); left: 0; right: 0;
  max-height: 264px; overflow-y: auto; padding: 6px;
  background: var(--surface); border-radius: var(--radius-input);
  box-shadow: var(--shadow-menu);
  opacity: 0; transform: translateY(-4px); pointer-events: none;
  transition: opacity var(--dur-menu) var(--ease-out), transform var(--dur-menu) var(--ease-out);
}
.select.is-open .select__menu { opacity: 1; transform: none; pointer-events: auto; }
.select__opt {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2);
  width: 100%; padding: 9px 11px; border: 0; border-radius: 9px; text-align: left;
  background: transparent; color: var(--text);
  font-family: var(--font-sans); font-size: var(--e-body-sm); cursor: pointer;
  transition: background-color var(--dur-hover-out) linear;
}
.select__opt:hover { background: var(--row-hover); }
/* Keyboard roving focus IS the active-option indicator: the options are real
   buttons, so focus moves natively and no aria-activedescendant bookkeeping is
   needed. Uses the ring rather than the hover tint so a keyboard user can tell
   focus from a stray pointer hover. */
.select__opt:focus-visible { outline: none; background: var(--row-hover); box-shadow: var(--focus-ring); }
.select__opt[aria-selected="true"] { background: var(--brand-50); color: var(--brand-700); font-weight: var(--fw-semibold); }
.select__opt .ico { --ico: 15px; opacity: 0; }
.select__opt[aria-selected="true"] .ico { opacity: 1; }

/* Checkbox — drawn, not native, so it renders identically in every WebView. */
.check { display: flex; align-items: flex-start; gap: 10px; cursor: pointer; }
.check input { -webkit-appearance: none; appearance: none; flex: 0 0 auto; width: 18px; height: 18px; margin: 2px 0 0; border: var(--border-input) solid var(--gray-300); border-radius: 5px; background: var(--surface); cursor: pointer; position: relative; transition: background-color var(--dur-press) linear, border-color var(--dur-press) linear; }
.check input:checked { background: var(--brand-500); border-color: var(--brand-500); }
.check input:checked::after { content: ""; position: absolute; left: 5px; top: 1.5px; width: 4px; height: 8px; border: solid var(--white); border-width: 0 2px 2px 0; transform: rotate(45deg); }
.check input:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.check__label { font-size: var(--e-meta); line-height: 1.5; color: var(--text-secondary); }
.check__label a { text-decoration: underline; text-underline-offset: 2px; }

/* ═══ NOTES / CALLOUTS ══════════════════════════════════════════════════════
   No coloured left-accent stripes, anywhere, ever. A tinted background with an
   even radius on all four sides already reads as its own region. */
.note {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5); border-radius: var(--radius-tile);
  background: var(--gray-50); color: var(--text-secondary);
  font-size: var(--e-meta); line-height: 1.55;
}
.note .ico { color: var(--text-tertiary); --ico: 18px; margin-top: 1px; }
.note__title { display: block; font-weight: var(--fw-semibold); color: var(--text); margin-bottom: 2px; }
.note--brand   { background: var(--surface-tint); color: var(--brand-700); }
.note--brand .ico { color: var(--brand-500); }
.note--brand .note__title { color: var(--brand-700); }
.note--success { background: var(--status-success-bg); color: var(--status-success-text); }
.note--success .ico, .note--success .note__title { color: var(--status-success-text); }
.note--warning { background: var(--status-warning-bg); color: var(--status-warning-text); }
.note--warning .ico, .note--warning .note__title { color: var(--status-warning-text); }
.note--danger  { background: var(--status-danger-bg); color: var(--status-danger-text); }
.note--danger .ico, .note--danger .note__title { color: var(--status-danger-text); }
.note--info    { background: var(--status-info-bg); color: var(--status-info-text); }
.note--info .ico, .note--info .note__title { color: var(--status-info-text); }
.note--hairline { background: var(--surface); border: var(--border-hairline) solid var(--hairline); }

/* ═══ ACCORDION ═════════════════════════════════════════════════════════════ */
.accordion { display: flex; flex-direction: column; }
.accordion__item { border-bottom: var(--border-hairline) solid var(--hairline); }
.accordion__q {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-5);
  width: 100%; padding: var(--sp-5) 0; border: 0; background: transparent; text-align: left;
  font-family: var(--font-display); font-size: var(--e-card-title-sm); font-weight: var(--fw-semibold);
  letter-spacing: var(--tk-snug); color: var(--text); cursor: pointer;
}
.accordion__q .ico { --ico: 20px; color: var(--text-tertiary); margin-top: 2px; transition: transform var(--dur-card) var(--ease-out); }
.accordion__item.is-open .accordion__q .ico { transform: rotate(45deg); color: var(--brand-500); }
.accordion__a { display: grid; grid-template-rows: 0fr; transition: grid-template-rows var(--dur-card) var(--ease-out); }
.accordion__item.is-open .accordion__a { grid-template-rows: 1fr; }
.accordion__a > div { overflow: hidden; }
.accordion__a p { margin: 0 0 var(--sp-5); font-size: var(--e-body-sm); line-height: 1.65; color: var(--text-secondary); max-width: 660px; text-wrap: pretty; }
.accordion__a a { text-decoration: underline; text-underline-offset: 2px; }

/* ═══ STICKY BANNERS + NAV ══════════════════════════════════════════════════
   Two sticky banners can sit above the nav in one stack: impersonation and
   admin-mode. They are not decorative; the chrome reserves room for them. */
.site-chrome { position: sticky; top: 0; z-index: 50; }
.site-banner {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-2);
  padding: 10px var(--sp-5); font-size: var(--e-meta); font-weight: var(--fw-medium);
  text-align: center;
}
.site-banner .ico { --ico: 16px; }
.site-banner a { text-decoration: underline; text-underline-offset: 2px; color: inherit; }
.site-banner--impersonate { background: var(--status-danger-text); color: var(--white); }
.site-banner--admin { background: var(--status-warning-bg); color: var(--status-warning-text); }
.site-banner__btn {
  height: 28px; padding: 0 12px; margin-left: var(--sp-2); border: 0;
  border-radius: var(--radius-pill); background: var(--white); color: var(--gray-950);
  font-family: var(--font-sans); font-size: var(--e-micro); font-weight: var(--fw-semibold);
  cursor: pointer; text-decoration: none; display: inline-flex; align-items: center;
}

/* ═══ NAV — Dental Acquisitions ═══════════════════════════════════════════════
   Reads var() only. Every colour resolves to one of the six brand literals in
   marketing/colors_and_type.css; a hex here breaks the single-source rule and
   marketing_brand_test.rb will fail the build.

   Two things about this component are counter-intuitive and cost real time to
   rediscover, so they are written down:

   1. The bar is FULL-BLEED, not .wrap. .wrap is max-width:1240px + 32px padding,
      which at a 1536px viewport puts the first pixel at x=180. The design puts it
      at x=49. Using .wrap here shoves the wordmark 130px inboard.
   2. The link group is CENTRED IN THE VIEWPORT, not laid out after the logo.
      Measured on NEW Section 1.png: the group spans x=406..1135, centre 770,
      against a viewport centre of 768. Hence the 1fr/auto/1fr grid, whose outer
      tracks are equal by definition. The 139px gap between Pricing and Sign In is
      an OUTPUT of that centring, not a value to hardcode.

   Colour roles are inverted from the pre-rebrand nav, which is the easiest thing
   here to get backwards: inactive links are now FULL-STRENGTH charcoal and the
   active link is TEAL. Active is signalled by hue, not by weight. */
/* NO bottom hairline. The design's Section 1 has none: the bone bar sits directly
   on the bone hero with no rule between them (verified by scanning the PNG for a
   darker row under the bar and finding nothing). Against any other ground the bone
   fill is itself the separation, so a rule is redundant there too.

   --nav-hairline is still used, by the drawer's top edge, the user menu and the
   drawer's row dividers, so it stays declared. */
.site-nav {
  position: relative;
  background: var(--nav-bg);
}
.site-nav__inner {
  display: grid;
  grid-template-columns: 1fr auto 1fr;   /* logo | links | cta */
  align-items: center;
  gap: var(--sp-4);
  height: var(--nav-h);
  padding: 0 var(--nav-pad);
}
.site-nav__logo { display: inline-flex; flex: 0 0 auto; justify-self: start; }
/* colors_and_type.css sets a global `img { max-width: 100% }`. Inside a grid track
   that is narrower than the wordmark, that silently overrides its width and the
   mark shrinks (measured 175px at a 1280px viewport) or vanishes entirely
   (0px at 1100px). max-width:none makes the wordmark incompressible, so a layout
   that no longer fits OVERFLOWS visibly instead of quietly deleting the logo.
   The breakpoint below is what stops that overflow ever happening. */
.site-nav__logo img { max-width: none; }

/* ── Link row ─────────────────────────────────────────────────────────────── */
.site-nav__links {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--nav-gap);
  justify-self: center;
}
.site-nav__links a {
  position: relative;
  display: inline-flex;
  align-items: center;
  height: 40px;
  font-family: var(--font-brand);
  font-size: var(--e-nav-link);
  font-weight: var(--fw-medium);
  color: var(--nav-ink);
  white-space: nowrap;
  transition: color var(--dur-hover-out) linear;
}
/* The active underline, always present but transparent, so a link becoming
   active never shifts the row. Overhangs the label by 5px each side, as the
   design does. Mirrors .brokering-topnav-label in the dashboard theme. */
.site-nav__links a::after {
  content: "";
  position: absolute;
  left: -4px; right: -4px; bottom: 5px;
  height: 2px;
  background: transparent;
  transition: background-color var(--dur-hover-out) linear;
}
.site-nav__links a:hover { color: var(--nav-ink-active); }
/* Active is driven by ONE attribute on the list, not a class per link. */
.site-nav__links a.is-active,
.site-nav__links[data-current="buyers"]      > a[data-nav="buyers"],
.site-nav__links[data-current="sellers"]     > a[data-nav="sellers"],
.site-nav__links[data-current="brokers"]     > a[data-nav="brokers"],
.site-nav__links[data-current="professionals"] > a[data-nav="professionals"],
.site-nav__links[data-current="market_data"] > a[data-nav="market_data"],
.site-nav__links[data-current="resources"]   > a[data-nav="resources"],
.site-nav__links[data-current="pricing"]     > a[data-nav="pricing"] { color: var(--nav-ink-active); }
.site-nav__links a.is-active::after,
.site-nav__links[data-current="buyers"]      > a[data-nav="buyers"]::after,
.site-nav__links[data-current="sellers"]     > a[data-nav="sellers"]::after,
.site-nav__links[data-current="brokers"]     > a[data-nav="brokers"]::after,
.site-nav__links[data-current="professionals"] > a[data-nav="professionals"]::after,
.site-nav__links[data-current="market_data"] > a[data-nav="market_data"]::after,
.site-nav__links[data-current="resources"]   > a[data-nav="resources"]::after,
.site-nav__links[data-current="pricing"]     > a[data-nav="pricing"]::after { background: var(--nav-ink-active); }

/* ── Right cluster ────────────────────────────────────────────────────────── */
.site-nav__cta {
  display: flex;
  align-items: center;
  gap: var(--nav-auth-gap);
  justify-self: end;
}
.site-nav__auth { display: flex; align-items: center; }
.site-nav__auth a {
  font-family: var(--font-brand);
  font-size: var(--e-nav-link);
  font-weight: var(--fw-medium);
  color: var(--nav-ink);
  white-space: nowrap;
  transition: color var(--dur-hover-out) linear;
}
.site-nav__auth a:hover { color: var(--nav-ink-active); }

.site-nav__cta-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--nav-cta-h);
  padding: 0 var(--nav-cta-pad);
  border-radius: var(--radius-sm);       /* 4px. Not a pill. */
  background: var(--nav-cta-bg);
  color: var(--nav-cta-ink);
  font-family: var(--font-brand);
  font-size: var(--e-nav-link);
  font-weight: var(--fw-semibold);
  white-space: nowrap;
  transition: background-color var(--dur-hover-out) linear;
}
.site-nav__cta-btn:hover { background: var(--nav-cta-bg-hover); color: var(--nav-cta-ink); }
.site-nav__cta-btn:focus-visible { outline: none; box-shadow: var(--nav-focus-ring); }
.site-nav__links a:focus-visible,
.site-nav__auth a:focus-visible { outline: none; box-shadow: var(--nav-focus-ring); }

/* ── Signed-in dropdown ───────────────────────────────────────────────────── */
.site-nav__user { position: relative; }
.site-nav__user > summary {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: 6px 8px; border-radius: var(--radius-sm);
  cursor: pointer; list-style: none;
}
.site-nav__user > summary::-webkit-details-marker { display: none; }
.site-nav__user > summary::marker { content: ""; }
/* Border step, not a fill: a hover fill has to know which surface it sits on,
   and --base-bg-hover is banned outright. */
.site-nav__user > summary:hover { box-shadow: inset 0 0 0 1px var(--nav-hairline); }
.site-nav__user__text { display: flex; flex-direction: column; align-items: flex-end; }
.site-nav__user__name {
  font-family: var(--font-brand); font-size: var(--e-meta);
  font-weight: var(--fw-semibold); color: var(--nav-ink); line-height: 1.35;
  max-width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.site-nav__user__role {
  font-family: var(--font-brand); font-size: var(--e-micro);
  color: var(--nav-ink-muted); line-height: 1.3;
}
.site-nav__user__avatar {
  width: 32px; height: 32px; border-radius: var(--radius-pill);
  background: var(--nav-bg); color: var(--nav-ink-active);
  display: flex; align-items: center; justify-content: center;
  font-size: var(--e-micro); font-weight: var(--fw-bold); flex: 0 0 auto;
}
.site-nav__user__menu {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 60;
  min-width: 220px; padding: 6px;
  background: var(--white); border: var(--border-hairline) solid var(--nav-hairline);
  border-radius: var(--radius-input); box-shadow: var(--shadow-menu);
  display: none;
}
.site-nav__user[open] .site-nav__user__menu { display: block; }
.site-nav__user__menu a, .site-nav__user__menu button {
  display: flex; align-items: center; gap: var(--sp-2);
  width: 100%; padding: 9px 10px; border: 0; background: none;
  border-radius: var(--radius-sm); cursor: pointer; text-align: left;
  font-family: var(--font-brand); font-size: var(--e-body-sm);
  font-weight: var(--fw-medium); color: var(--nav-ink);
}
.site-nav__user__menu a:hover, .site-nav__user__menu button:hover { color: var(--nav-ink-active); }
.site-nav__user__menu .ico { --ico: 17px; color: var(--nav-ink-muted); }
.site-nav__user__sep { height: 1px; background: var(--nav-hairline); margin: 5px 4px; }

/* ── Hamburger ────────────────────────────────────────────────────────────── */
.site-nav__toggle {
  display: none; align-items: center; justify-content: center;
  width: 40px; height: 40px; padding: 0; border: 0; background: none;
  cursor: pointer; flex-direction: column; gap: 4px;
}
.site-nav__toggle span {
  display: block; width: 17px; height: 2px; border-radius: 2px;
  background: var(--nav-ink);
  transition: transform var(--dur-card) var(--ease-out), opacity var(--dur-card) var(--ease-out);
}
.site-nav.is-open .site-nav__toggle span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.site-nav.is-open .site-nav__toggle span:nth-child(2) { opacity: 0; }
.site-nav.is-open .site-nav__toggle span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* ═══ NAV — responsive ════════════════════════════════════════════════════════
   The wordmark steps by WIDTH only; height stays auto, so the 2.942 aspect holds
   at every step and the artwork is never distorted. Each --nav-h leaves the
   lockup roughly 15px of breathing room top and bottom.

   EVERY STEP MUST SIT BELOW THE DESKTOP VALUE (164px / 90px). After the 1.25x
   scale correction these still held the pre-correction numbers, so the first
   tablet step rendered the wordmark at 176px and the bar at 96px, i.e. LARGER
   than desktop, and the nav grew as the viewport shrank.

   The tagline is part of the raster lockup, so it scales with the mark and stays
   visible at every width, reaching about 9px on a phone. That is deliberate and
   was explicitly approved; it is not a bug to "fix" by cropping the asset. */
/* ── The two nav breakpoints, arithmetic not taste ─────────────────────────
   RECOMPUTED 2026-09-06, when /professionals made the row SEVEN links. Measured
   label widths at 14px: For Buyers 67, For Sellers 66, For Brokers 72, For
   Professionals 107, Market Data 77, Resources 65, Pricing 44 = 498px of labels.
   The right cluster measures 182 (Sign In + Get Started) and the wordmark 164.

     required = 2*nav-pad + 164 wordmark + 2*16 grid gap + (498 + 6*nav-gap) + 182

   At the desktop gap of 42 that is 1204px, against 1047 for the old six-link
   row. Left alone, the nav would have overflowed from 1060 to 1204: the wordmark
   carries max-width:none precisely so that failure is VISIBLE rather than a
   silently shrinking logo, and it would have been visible on every laptop in
   that band.

   Two steps rather than one, because a single breakpoint at 1220 would have
   taken the desktop nav off an iPad Air in landscape (1180) for the sake of one
   extra label:

     >= 1220   gap 42, the design's own spacing
     1120-1219 gap 22, which keeps all seven labels on a 1180 tablet
     <= 1119   the drawer

   1120 rather than the 1100 the arithmetic alone allows. MEASURED at 1100 the
   row fits with 2px to spare, which is not slack, it is luck: a scrollbar or a
   font that renders a hair wider eats it. 1120 measures 22px, in line with the
   13px the six-link row was given.

   The drawer now starts 60px higher than it did (1119, was 1059). That is the
   whole cost of the seventh link.

   If any label, the wordmark width or the button changes size, redo BOTH sums.
   The pre-correction value here was 1299px, and before that an inherited 1100px
   that left 1100-1287 rendering a collapsed logo. */
@media (max-width: 1219px) {
  .site-nav { --nav-gap: 22px; }
}
@media (max-width: 1119px) {
  .site-nav { --e-wordmark-w: 190px; --nav-h: 82px; --nav-pad: 28px; }
  /* Scoped to the bar's own row on purpose. A bare .site-nav__cta-btn would also
     match the drawer's Get Started, which carries the same base class; that only
     works out via source order, which is too fragile to rely on. */
  .site-nav__links, .site-nav__user, .site-nav__auth,
  .site-nav__cta > .site-nav__cta-btn { display: none; }
  .site-nav__toggle { display: inline-flex; }
  /* The grid loses its middle occupant, so stop reserving a centre track. */
  .site-nav__inner { grid-template-columns: 1fr auto; }
}
@media (max-width: 899px) {
  .site-nav { --e-wordmark-w: 190px; --nav-h: 76px; --nav-pad: 22px; }
}
@media (max-width: 639px) {
  .site-nav { --e-wordmark-w: 190px; --nav-h: 68px; --nav-pad: 18px; }
}

/* ═══ NAV — drawer ════════════════════════════════════════════════════════════ */
.site-nav__drawer {
  display: none;
  padding: var(--sp-4) 0 var(--sp-6);
  background: var(--nav-bg);
  border-top: var(--border-hairline) solid var(--nav-hairline);
}
.site-nav.is-open .site-nav__drawer { display: block; }
.site-nav__drawer__links { display: flex; flex-direction: column; padding: 0 var(--nav-pad); }
.site-nav__drawer__links a {
  padding: 15px 0;
  font-family: var(--font-brand);
  font-size: var(--e-card-title-sm);
  font-weight: var(--fw-semibold);
  color: var(--nav-ink);
  border-bottom: var(--border-hairline) solid var(--nav-hairline);
}
.site-nav__drawer__links a:last-child { border-bottom: 0; }
.site-nav__drawer__links a.is-active,
.site-nav__drawer__links[data-current="buyers"]      > a[data-nav="buyers"],
.site-nav__drawer__links[data-current="sellers"]     > a[data-nav="sellers"],
.site-nav__drawer__links[data-current="brokers"]     > a[data-nav="brokers"],
.site-nav__drawer__links[data-current="professionals"] > a[data-nav="professionals"],
.site-nav__drawer__links[data-current="market_data"] > a[data-nav="market_data"],
.site-nav__drawer__links[data-current="resources"]   > a[data-nav="resources"],
.site-nav__drawer__links[data-current="pricing"]     > a[data-nav="pricing"],
.site-nav__drawer__links[data-current="about"]       > a[data-nav="about"],
.site-nav__drawer__links[data-current="contact"]     > a[data-nav="contact"] { color: var(--nav-ink-active); }
.site-nav__drawer__cta {
  display: flex; flex-direction: column; align-items: stretch;
  gap: var(--sp-3); padding: var(--sp-4) var(--nav-pad) 0;
}
.site-nav__cta-btn--block { display: flex; width: 100%; }
.site-nav__drawer__signin {
  display: flex; align-items: center; justify-content: center;
  height: 50px;
  font-family: var(--font-brand); font-size: var(--e-nav-link);
  font-weight: var(--fw-semibold); color: var(--nav-ink);
  border: var(--border-hairline) solid var(--nav-hairline);
  border-radius: var(--radius-sm);
}
.site-nav__drawer__signin:hover { color: var(--nav-ink-active); }
.site-nav__drawer__cta .btn { width: 100%; }

/* ═══ WORDMARK ═══════════════════════════════════════════════════════════════
   Width-driven, height auto. The tagline lockup's aspect is 3.77 and fixed;
   setting both dimensions is how the artwork gets stretched, which the brand
   sheet forbids. Per-surface width overrides belong on the container, not here.

   A per-surface override sets a different WIDTH (see .smap-hero__logo img), never
   a height: the old footer set height:26px and rendered the lockup's tagline at
   about 4px.

   Markup: app/views/shared/_wordmark.html.erb. Contract: the twin of this block
   in app/assets/tailwind/components/wordmark.css — the two bundles share no
   cascade, so the rules are stated in both. Keep them in sync. */
.da-wordmark { width: var(--e-wordmark-w); height: auto; display: block; }

/* Ground swap for `on: :auto` (onboarding is the marketing-bundle surface that
   goes dark). Both assets are in the DOM and exactly one displays; dark mode is
   class-driven off current_user.theme, so this cannot be a media query, and the
   artwork is six colours, so it cannot be a filter. `.dark` serves both dark
   variants. display:none, not visually-hidden: the alt must be announced once. */
.da-wordmark--on-dark { display: none; }
.dark .da-wordmark--on-light { display: none; }
.dark .da-wordmark--on-dark { display: block; }

/* The other forms carry their own aspect and must not inherit --e-wordmark-w. */
.da-wordmark--symbol { width: 24px; }
.da-wordmark--square { width: 96px; }
.da-wordmark--wordmark { width: 160px; }
/* max-width: none on the surfaces whose track can go narrower than the mark.
   colors_and_type.css sets a global img { max-width: 100% }, which OVERRIDES
   the width token inside a constrained flex or grid track and shrinks the
   wordmark to nothing with no error and no overflow to notice (measured at 0px
   in the nav at a 1100px viewport). Incompressible means a layout that stops
   fitting overflows visibly instead of quietly deleting the brand.
   .onboarding-nav__inner is `1fr auto 1fr` with a 32px gap, so its first track
   is exactly such a case. The nav sets its own further down this file. */
.auth-top__logo .da-wordmark,
.onboarding-nav__logo .da-wordmark { max-width: none; }

/* ═══ FOOTER — Dental Acquisitions ═══════════════════════════════════════════
   The site-wide ink band under every marketing page and the explore map. Lives
   here rather than in pages.css because the explore layout loads site.css only.

   Colour comes entirely from the --foot-* roles in colors_and_type.css: no
   literal below this line, same rule the nav block holds to.

   The reversed lockup is an ASSET, not a filter. logo-light.png used to be
   knocked out with `filter: invert(1) !important` from pages/explore.css, which
   turned the green in ".deals" magenta; the two-colour Dental Acquisitions
   lockup would fare worse. Marketing ships a genuinely repainted dark-ground
   file instead, and `on: :dark` picks it (see shared/_wordmark.html.erb).

   Type roles only, no raw sizes: the column labels borrow the eyebrow role, the
   links the nav-label role, the legal bar the micro role. */
.da-foot {
  background: var(--foot-bg);
  border-top: var(--border-hairline) solid var(--foot-hairline);
  padding: var(--sp-16) 0 var(--sp-8);
  font-family: var(--font-brand);
}
.da-foot__inner { padding: 0 var(--nav-pad); }

/* 1.7fr on the brand column, from the design. The link columns are equal and
   minmax(0, 1fr), never a bare 1fr: a bare 1fr floors at min-content, and
   "Valuation calculator" would then set a track wider than its share. */
.da-foot__grid {
  display: grid;
  grid-template-columns: 1.7fr repeat(4, minmax(0, 1fr));
  gap: var(--sp-10);
}
/* Native drops the middle three columns, leaving the lockup and Legal. Without
   this the two survivors would sit in a five-track grid with three empty columns
   of dead space between them.

   A CLASS, not :has(). The condition is known at render time, and :has() is
   missing from the older WebKit that Hotwire Native runs on, which is the one
   place this rule has to work. */
.da-foot__grid--lean { grid-template-columns: 1.7fr minmax(0, 1fr); }

.da-foot__lockup { display: block; }
.da-foot__note {
  max-width: 30ch;
  margin: var(--sp-5) 0 0;
  font-size: var(--e-nav-link);
  line-height: 1.55;
  color: var(--foot-note);
}

.da-foot__col { display: block; }
.da-foot__head {
  margin: 0 0 var(--sp-5);
  /* Explicit, not inherited: site.css sets a display face on h1-h3 globally, and
     these column labels are chrome rather than editorial headings. */
  font-family: var(--font-brand);
  font-size: var(--e-eyebrow);
  font-weight: var(--fw-semibold);
  /* 0.16em, wider than --tk-eyebrow's 0.12em: these labels are the quietest text
     on the page and the extra tracking is what keeps them legible at 11px. */
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--foot-heading);
}
.da-foot__col a {
  display: block;
  padding: 5px 0;
  font-size: var(--e-nav-link);
  color: var(--foot-link);
  transition: color var(--dur-hover-out) linear;
}
.da-foot__col a:hover { color: var(--foot-ink); }
.da-foot__col a:focus-visible { outline: none; box-shadow: var(--nav-focus-ring); }

.da-foot__legal {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--sp-5);
  margin-top: var(--sp-14);
  padding-top: var(--sp-6);
  border-top: var(--border-hairline) solid var(--foot-hairline);
  font-size: var(--e-micro);
  line-height: 1.5;
  color: var(--foot-legal);
}

/* Four link columns do not fit beside the brand column much below 1100px, and
   two-up is the design's own fallback. The brand column then spans both. */
@media (max-width: 1099px) {
  .da-foot { padding: var(--sp-14) 0 var(--sp-8); }
  .da-foot__grid,
  .da-foot__grid--lean { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-10); }
  .da-foot__brand { grid-column: 1 / -1; }
}

@media (max-width: 639px) {
  .da-foot__grid,
  .da-foot__grid--lean { grid-template-columns: minmax(0, 1fr); gap: var(--sp-8); }
  .da-foot__legal { margin-top: var(--sp-10); }
}

/* ═══ MODAL / SLIDEOVER SHELLS ══════════════════════════════════════════════ */
.scrim { position: fixed; inset: 0; z-index: 300; background: rgba(34, 34, 34, 0.34); opacity: 0; pointer-events: none; transition: opacity var(--dur-menu) var(--ease-out); }
.scrim.is-open { opacity: 1; pointer-events: auto; }
.modal {
  position: fixed; z-index: 310; top: 50%; left: 50%;
  width: min(520px, calc(100vw - 32px)); max-height: calc(100vh - 48px); overflow-y: auto;
  transform: translate(-50%, -50%) scale(0.98); opacity: 0; pointer-events: none;
  background: var(--surface); border-radius: var(--radius-card); box-shadow: var(--shadow-modal);
  padding: var(--sp-7);
  transition: opacity var(--dur-menu) var(--ease-out), transform var(--dur-menu) var(--ease-out);
}
.modal.is-open { opacity: 1; transform: translate(-50%, -50%) scale(1); pointer-events: auto; }
.modal__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-4); margin-bottom: var(--sp-4); }
.modal__title { margin: 0; font-family: var(--font-display); font-size: var(--e-card-title); font-weight: var(--fw-bold); letter-spacing: var(--tk-tight); color: var(--text); }
.modal__x { width: 34px; height: 34px; flex: 0 0 auto; border: 0; border-radius: var(--radius-pill); background: var(--gray-50); color: var(--text-secondary); display: flex; align-items: center; justify-content: center; cursor: pointer; transition: background-color var(--dur-hover-out) linear; }
.modal__x:hover { background: var(--gray-100); }

/* ── Centred modal, for a sheet whose subject IS a figure ────────────────────
   The funnel's save-your-estimate sheet leads with the valuation range, so its
   header centres and the close control floats out of the text flow rather than
   sitting in the .modal__head flex row. */
.modal--center { text-align: center; }
.modal__head--center { margin-bottom: var(--sp-6); }
/* The icon medallion for a confirmation state ("check your email"). pages/auth.css has
   .auth-icon-circle for the same job, but that sheet is only on the auth layout, and this
   modal renders on the onboarding one. */
.modal__medallion {
  display: flex; align-items: center; justify-content: center;
  width: 56px; height: 56px; margin: 0 auto var(--sp-5);
  border-radius: var(--radius-pill); background: var(--brand-50); color: var(--brand-700);
}
.modal__medallion .ico { --ico: 26px; }
/* button_to renders a <form>; keep it inline so "or resend" reads as one sentence. */
.modal__resend { display: inline; }
.modal__x--float { position: absolute; top: var(--sp-4); right: var(--sp-4); }
.modal__title--figure {
  font-size: var(--e-num-md); line-height: var(--lh-tight);
  letter-spacing: var(--tk-tight); font-variant-numeric: tabular-nums;
}
.modal__sub { margin: 6px 0 0; font-size: var(--e-body-sm); line-height: 1.5; color: var(--text-secondary); }
/* Forms inside a centred modal read left-aligned; the centring is for the header. */
.modal__form { display: flex; flex-direction: column; gap: var(--sp-4); text-align: left; }
.modal__foot { margin: var(--sp-5) 0 0; font-size: var(--e-meta); color: var(--text-secondary); }
.modal__foot a { font-weight: var(--fw-semibold); color: var(--text); }
.modal__foot a:hover { color: var(--brand-700); text-decoration: underline; text-underline-offset: 2px; }
.modal__note { margin: var(--sp-3) 0 0; font-size: var(--e-micro); color: var(--text-tertiary); }

/* ── OAuth divider ──────────────────────────────────────────────────────────
   One rule for the "or with email" separator. It lives HERE, not in
   pages/auth.css, because site.css is loaded by the auth layout AND the
   onboarding layout, so the devise screens and the funnel's signup sheet can
   share it. It was previously hand-built from inline Tailwind <hr>s in
   devise/sessions/new and again in devise/registrations/new. */
.auth-divider {
  display: flex; align-items: center; gap: var(--sp-3);
  margin: var(--sp-5) 0 var(--sp-4);
  font-size: var(--e-eyebrow); font-weight: var(--fw-semibold);
  letter-spacing: var(--tk-eyebrow); text-transform: uppercase;
  color: var(--text-tertiary); white-space: nowrap;
}
.auth-divider::before, .auth-divider::after {
  content: ""; flex: 1 1 auto; height: var(--border-hairline); background: var(--hairline);
}
@media (max-width: 640px) {
  .modal { top: auto; bottom: 0; left: 0; width: 100vw; max-height: 92vh; border-radius: var(--radius-card) var(--radius-card) 0 0; transform: translateY(16px); padding: var(--sp-5); }
  .modal.is-open { transform: none; }
}

/* ═══ HIDDEN GUARD ══════════════════════════════════════════════════════════
   The UA's `[hidden] { display: none }` is the weakest possible display
   declaration, so ANY author rule setting display on the same element wins and
   the element paints with the attribute still present. `.rcard`, `.otp-row`,
   `.auth-back` and `.acct-head__gear` are all class selectors, which outrank a
   bare attribute selector, so a non-important guard loses too.

   Symptoms this caused: two "Back" links side by side on A02/A04, twelve OTP
   cells on A07 with the invalid-state digits showing, all nine resources
   articles painted under a Load-more button, and the settings gear on the
   signed-OUT account screen.

   ASSERTING ON THIS: never test `el.hidden` — the property is set correctly even
   when the element paints, so a probe reading it passes while the screen is
   wrong. Test computed display, or `el.checkVisibility()`. */
[hidden] { display: none !important; }

/* ═══ PROTOTYPE STATE BAR ═══════════════════════════════════════════════════
   Not product chrome. One file per screen, every error / empty / signed-in
   state switchable in place, so the 39 screens don't fork into 90 files. Drop
   this block and the [data-state-bar] markup when porting to Rails. */
/* The bar is fixed, so it does not participate in layout and cannot be avoided
   by padding on a CENTRED container: .auth-main is `align-items: center` inside a
   min-height:100vh column, and when the card outgrows the padded content box the
   overflow is symmetric, so bottom padding stops reserving anything and content
   lands under the bar. That put A04's required terms checkbox and A07's only
   submit button under an unclickable overlay at initial scroll.
   Reserving on <body> works regardless of how a screen centres, and covers the
   shells that are not .auth-main (M13 uses .acct-screen). */


/* ═══ ACCESSIBILITY ═════════════════════════════════════════════════════════ */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
a:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible, [tabindex]:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 2px; border-radius: 6px; }
.input:focus-visible, .textarea:focus-visible, .select__btn:focus-visible { outline: none; }
::selection { background: var(--brand-100); color: var(--gray-950); }

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

/* ═══════════════════════════════════════════════════════════════════════════
   LEGACY CHROME — pre-v2 rules kept alive for views not yet rewritten.

   🚨 Retire an entry only when its consumer has been ported, not before.

   The v2 site.css drops 62 class names. 31 of them are still used by a view
   that renders on one of the four layouts loading this bundle, so their rules
   are carried over verbatim below. Every selector here is scoped by a class the
   v2 bundle does not style, so nothing shadows a v2 rule.

   Retire-when:
     .auth-*, .email-chip*, .role-pick*, .step-dots*  -> pages/auth.css      (auth stage)
     .d, .k, .v, .hero__cta, .page-hero               -> pages.css + pages/index.css
                                                         (shared-blocks + pages stages)
     .pill--*, .btns, .btn-disabled-wrapper, .stat,
     .text-muted, .underline                          -> the marketing pages stage
     .marketing-chrome, .banner, .banner-impersonate   -> KEEP. These are layout and
       shared-partial chrome (layouts/marketing, layouts/explore,
       shared/_impersonation_banner, shared/_admin_mode_banner), and the v2 bundle
       has no replacement for them.

   Note: `.btns` has no bare rule here because it never had one. Its only styling
   was `.cta-block .btns`, and all five consumers sit inside `.final-cta`, so it
   is already unstyled today. Preserved as-is rather than "fixed" here.
   ═══════════════════════════════════════════════════════════════════════════ */
.text-muted { color: var(--base-text-tertiary); }

/* .hero__cta .btn-ghost retired: the hero's secondary is .btn-outline now, and
   v2 never defined .btn-ghost (only .btn-ghost-ink, for dark bands). */


.btn-disabled-wrapper {
  display: inline-block;
  cursor: not-allowed;
  position: relative;
}

.btn-disabled-wrapper .btn {
  opacity: .45;
  pointer-events: none;
  cursor: not-allowed;
  user-select: none;
}

.btn-disabled-wrapper::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  background: var(--color-gray-950);
  color: #fff;
  font-size: var(--text-sm);
  font-weight: var(--fw-medium);
  white-space: nowrap;
  padding: 5px 10px;
  border-radius: 6px;
  pointer-events: none;
  opacity: 0;
  transition: opacity .15s;
}

.btn-disabled-wrapper:hover::after {
  opacity: 1;
}

.pill--active { background: #ecfdf5; color: #065f46; }

.pill--offer  { background: #fff7ed; color: #9a3412; }

.pill--navy   { background: #eef2f9; color: var(--color-brand-navy); }

.stat { padding: 18px 20px; border: 1px solid var(--base-border-tertiary); border-radius: 10px; background: #fff; }

.stat .k { font-size: var(--text-xs); font-weight: var(--fw-semibold); letter-spacing: .08em; text-transform: uppercase; color: var(--base-text-tertiary); margin-bottom: 8px; }

.stat .v { font-size: var(--text-2xl); font-weight: var(--fw-bold); letter-spacing: -0.02em; color: var(--color-gray-950); font-variant-numeric: tabular-nums; }

.stat .d { font-size: var(--text-xs); font-weight: var(--fw-semibold); color: var(--color-green-700); margin-top: 4px; }

.stat .d.down { color: var(--color-red-700); }

.marketing-chrome {
  position: sticky;
  top: 0;
  z-index: 50;
}

.marketing-chrome .site-nav {
  
  position: static;
  top: auto;
}

.auth-top {
  display: flex; align-items: center;
  padding: 20px 32px;
  background: var(--color-gray-50);
}

.auth-main {
  min-height: calc(100vh - 68px);
  display: flex; align-items: center; justify-content: center;
  padding: 32px 16px 64px;
  background: var(--color-gray-50);
}

@media (max-width: 640px) {
  .auth-top { padding: 16px 20px; }
  /* Width, not height. pages/auth.css owns the wordmark's size; this block
     used to set a 24px height sized for the old two-line logo, which is the
     rule that renders the new lockup's tagline at 4px. */
  .auth-top__logo .da-wordmark { width: 165px; }
}

.auth-icon-circle {
  width: 56px; height: 56px; border-radius: 50%;
  background: rgba(34,197,94,.12);
  display: flex; align-items: center; justify-content: center;
}

.role-pick { display: block; cursor: pointer; }

.role-pick__inner {
  position: relative; display: flex; align-items: flex-start; gap: 12px;
  padding: 14px; border: 1px solid var(--color-gray-300); border-radius: 12px;
  background: #fff; transition: border-color .15s, background .15s, box-shadow .15s;
}

.role-pick__icon {
  width: 36px; height: 36px; border-radius: 8px;
  background: var(--color-gray-100); color: var(--color-gray-700);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  transition: background .15s, color .15s;
}

.role-pick__check {
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--color-gray-950); color: #fff;
  display: none; align-items: center; justify-content: center; flex-shrink: 0;
}

.role-pick:has(:checked) .role-pick__inner,
.role-pick--locked .role-pick__inner {
  border-color: var(--color-gray-950); background: var(--color-gray-50);
  box-shadow: 0 0 0 3px rgba(20,20,20,.06);
}

.role-pick:has(:checked) .role-pick__icon,
.role-pick--locked .role-pick__icon { background: var(--color-gray-950); color: #fff; }

.role-pick:has(:checked) .role-pick__check,
.role-pick__check--on { display: flex; }

.role-pick--locked { cursor: default; }

.step-dots { display: flex; gap: 6px; }

.step-dots__dot { flex: 1; height: 4px; border-radius: 999px; background: var(--color-gray-300); }

.step-dots__dot--active { background: var(--color-gray-950); }

.step-dots__dot--done { background: var(--color-green-700, oklch(52.7% .154 150.069)); }

.email-chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 6px 6px 12px; border-radius: 999px;
  background: var(--color-gray-100); border: 1px solid var(--color-gray-300);
  font-size: var(--text-base); color: var(--color-gray-800);
  max-width: 100%;
}

.email-chip__email { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

@media (max-width: 760px) {
  .section { padding: 64px 0; }
  .section--sm { padding: 48px 0; }
  .section--lg { padding: 80px 0; }
  .section-head { margin-bottom: 32px; }
  .display { font-size: clamp(32px, 8vw, 44px); }
  .display-md { font-size: clamp(26px, 6.5vw, 36px); }
  .display-sm { font-size: clamp(22px, 5.5vw, 28px); }
}

.page-hero { padding: 120px 0 80px; border-bottom: 1px solid var(--base-border-tertiary); }

.page-hero h1 { margin: 16px 0 20px; }

.page-hero .lede { font-size: var(--text-xl); }

@media (max-width: 760px) {
  .page-hero { padding: 56px 0 48px; }
  .page-hero .lede, .page-hero .lede-lg { font-size: var(--text-lg); }
}

.banner {
  background: var(--base-bg-base);
  color: var(--base-text-secondary);
  padding: 16px;
  display: flex;
  align-items: center;
  font-size: var(--text-md);
  line-height: 20px;
  justify-content: center;
  gap: 8px;

  & svg {
    height: 20px;
    width: 20px;
    color: var(--base-icon);
    flex-shrink: 0;
  }

  & h4 a, & p a {
    display: inline;
    margin-right: 0px;
  }

  & p {
    font-weight: var(--fw-regular);
    color: var(--base-text-secondary);
  }

  &.banner-impersonate {
    background: var(--bg-danger-hover);
    color: var(--text-on-danger);

    & a {
      color: var(--text-on-danger);
    }

    & > * + * {
      margin-left: 8px;
    }
  }
}

.banner.banner-impersonate a.underline {
  text-decoration: underline;
  text-underline-offset: 2px;
}

.banner.banner-impersonate .btn {
  display: inline-flex;
  text-decoration: none;
  justify-content: center;
  align-items: center;
  gap: 4px;
  border-radius: var(--radius-lg);
  box-shadow:
    rgba(0, 0, 0, 0) 0px 0px 0px 0px,
    rgba(0, 0, 0, 0) 0px 0px 0px 0px,
    rgba(0, 0, 0, 0) 0px 0px 0px 0px,
    rgba(0, 0, 0, 0) 0px 0px 0px 0px,
    oklab(0.999994 0.0000455678 0.0000200868 / 0.2) 0px 1px 0px 0px inset;
  font-weight: var(--fw-semibold);
  line-height: 20px;
  font-size: var(--text-sm);
  height: calc(var(--spacing) * 10);
  padding-inline: calc(var(--spacing) * 4);
  border: 1px solid #0000001a;
  background: var(--bg-secondary);
  color: var(--text-on-secondary);
  white-space: nowrap;
}

.banner.banner-impersonate .btn:hover {
  cursor: pointer;
  background: var(--bg-secondary-hover);
  color: var(--text-on-secondary-hover);
}

.banner.banner-impersonate .btn:focus-visible {
  outline: 2px solid var(--base-border-focus);
  outline-offset: 2px;
}

.banner.banner-impersonate .btn:disabled {
  opacity: 60%;
  cursor: not-allowed;
}

.banner.banner-impersonate .btn:disabled:hover {
  background: var(--bg-secondary);
  color: var(--text-on-secondary);
}

.banner.banner-impersonate .btn.btn-small,
.banner.banner-impersonate .btn.btn-sm {
  height: calc(var(--spacing) * 8);
  padding-inline: calc(var(--spacing) * 3);
}

.cta-block .btns { display: flex; gap: 12px; flex-wrap: wrap; }

/* ── FORM LABEL ─────────────────────────────────────────────────────────────
   The v2 sheet shipped .field, .input and .textarea but never a rule for the
   <label> inside a .field, so every label on /contact rendered at the browser
   default (16px/400). Shared primitive, so it lives here rather than in
   pages/contact.css. */
.field label {
  font-size: var(--e-meta);
  font-weight: var(--fw-semibold);
  color: var(--text-secondary);
  letter-spacing: var(--tk-snug);
}
.field label .req { color: var(--coral-500); }

/* The label span inside .select__btn never had a rule, in v2 or before it. As a
   plain flex child a long option ("Actively planning, 6 to 12 months") grows past
   the button and shoves the chevron out, because .select__btn is a fixed 46px
   space-between row. min-width: 0 is what lets it shrink enough to ellipsize. */
.select__btn-label {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
