/*
  SeekingSitters — warm, modern design system.
  Display: Fraunces (soft serif). UI/body: Plus Jakarta Sans.
  Brand red primary on warm creams, soft depth, gentle motion.
*/
:root {
  /* Canonical brand tokens — also the source of truth for the iOS app and any
     email/embed (palette changes get a cross-repo inbox note). The *-dark values
     are the canonical dark-surface colors (iOS dark mode, dark emails); they are
     deliberately NOT wired to prefers-color-scheme — the cream site isn't a dark theme. */
  --brand-primary: #c40223;        /* UI primary — buttons, links, focus rings (6.2:1 on white, AA) */
  --brand-primary-hover: #a40119;
  --brand-primary-dark: #e63b57;   /* canonical value on dark surfaces (iOS dark mode uses this) */
  --brand-logo: #e8116b;           /* logo artwork ONLY — never a UI accent (legacy site's old primary) */
  /* retired: legacy teal #00bad0 — do not reintroduce */
  --brand-blue: #2f6fb0;
  --brand-gold: #f6b53b;           /* decorative / on-dark ONLY — fails text contrast on light (~1.8:1) */
  --brand-ink: #211a1c;
  --brand-slate: #6b6068;
  --cream: #fff8f3;
  --cream-2: #fdeee6;
  --surface: #ffffff;
  --border: #efe4dc;

  /* Compatibility aliases. These four names are used in ~58 inline styles across the portals and the
     public pages but were never defined, so every one of those declarations was invalid at
     computed-value time -- which does NOT fall back to the class underneath, it computes to `unset`
     and still wins the cascade. The visible result was ghost buttons losing their border (the
     "Cancel" escape on every request form read as plain text), .check-pill losing the outline that is
     its whole affordance, the owner sales chart rendering as an empty box, and the Cancel-job button
     not being red. Defining them is the one-line fix; the inline styles can be swept onto classes
     later without urgency. */
  --brand-border: var(--border);
  --brand-line: var(--border);
  --brand: var(--brand-primary);
  --brand-red: var(--brand-primary);

  --radius: 1.25rem;
  --radius-lg: 2rem;
  --radius-pill: 999px;
  --shadow-sm: 0 2px 8px rgba(60, 30, 20, .06);
  --shadow-md: 0 12px 30px rgba(60, 30, 20, .10);
  --shadow-lg: 0 30px 60px rgba(60, 30, 20, .14);
  --maxw: 1180px;
  --font-display: "Fraunces", Georgia, serif;
  --font-sans: "Plus Jakarta Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
}

* { box-sizing: border-box; }
html { font-size: 16px; -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0; min-height: 100vh; display: flex; flex-direction: column;
  color: var(--brand-ink); background: var(--surface);
  font-family: var(--font-sans); line-height: 1.6; -webkit-font-smoothing: antialiased;
  font-size: 1.02rem;
}
main { flex: 1 0 auto; }

h1, h2, h3 { line-height: 1.12; letter-spacing: -.02em; color: var(--brand-ink); }
a { color: var(--brand-primary); text-decoration: none; }
a:hover { color: var(--brand-primary-hover); }

:where(a, button, input, select, textarea):focus-visible {
  outline: 2px solid var(--brand-primary); outline-offset: 2px;
}

.container { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 1.5rem; }
.text-center { text-align: center; }
.mt-2 { margin-top: 2rem; } .mt-3 { margin-top: 3rem; }
.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; }

/* 🔴 Make the `hidden` attribute actually hide things.
   The UA stylesheet's `[hidden] { display: none }` is an ATTRIBUTE selector, so ANY class rule that
   sets display beats it. `.job-row { display: flex }` did exactly that: the candidate filter set
   `row.hidden = true` on 88 of 89 sitters, the property read back as true, and every row stayed on
   screen. Reported from the live dev box 2026-08-27.
   `!important` is warranted here and is the standard use of it — the whole point is that this must
   outrank a class rule, which is the one thing normal specificity cannot do. */
[hidden] { display: none !important; }
.skip-link { position: absolute; left: .75rem; top: -3rem; z-index: 1000; background: var(--brand-primary); color: #fff; padding: .6rem 1rem; border-radius: .5rem; font-weight: 600; transition: top .15s; }
.skip-link:focus { top: .75rem; outline: 2px solid #fff; outline-offset: 2px; }

/* ---------- Motion ---------- */
.reveal { opacity: 0; transform: translateY(18px); transition: opacity .7s ease, transform .7s cubic-bezier(.2,.7,.2,1); }
.reveal.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .reveal { opacity: 1; transform: none; transition: none; } html { scroll-behavior: auto; } }

/* .hero-search was used on /contact but never defined, so that ZIP form rendered unstyled while the
   identical one on the homepage looked like a pill. Mirror the homepage treatment. */
.hero-search { display: flex; gap: .6rem; flex-wrap: wrap; }
.hero-search input { flex: 1 1 12rem; min-width: 0; padding: .85rem 1.1rem; border: 1px solid var(--border); border-radius: var(--radius-pill); font: inherit; background: #fff; }

/* Dashboard counts that lead somewhere. A count the user cannot act on is just trivia -- 20 of the
   franchisee dashboard's stats now open their filtered list. The six without a genuinely matching
   filter (Rush, the two 48h buckets, Secured-no-sitter, Completed, On leave) are deliberately left
   as plain text rather than pointed at an approximate list that would not match the number. */
a.stat-link { text-decoration: none; color: inherit; display: block; border-radius: var(--radius); transition: background-color .12s, transform .12s; }
a.stat-link:hover, a.stat-link:focus-visible { background: var(--cream); transform: translateY(-1px); }
a.stat-link:hover .num, a.stat-link:focus-visible .num { color: var(--brand-primary); }

/* Thirteen forms put inputs outside .field, so they inherited the UA default (~13.3px). Under 16px
   iOS Safari zooms the viewport on focus and does not zoom back -- on Sitter/Contact that is thirteen
   zooms in one form, and it is the long form a sitter fills on a phone. Inheriting the body font
   fixes the zoom and the visual mismatch at once. Proper .field wrappers are still the tidier fix. */
input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]), select, textarea { font: inherit; }

/* .field-error was used on validation spans in three forms but never defined, so failures rendered as
   plain black body text. Match .text-danger. */
.field-error { color: var(--brand-primary); font-size: .88rem; font-weight: 600; }

/* ---------- Flash banners ---------- */
.flash { border-radius: var(--radius); padding: .85rem 1.1rem; margin-bottom: 1rem; font-weight: 600; border: 1px solid; }
.flash-ok { background: #e9f7ef; border-color: #bce7cd; color: #1f7a3d; }
.flash-error { background: #fdecef; border-color: #f5c2cc; color: var(--brand-primary); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  font-family: var(--font-sans); font-weight: 700; font-size: 1rem;
  border-radius: var(--radius-pill); padding: .85rem 1.6rem; border: 1.5px solid transparent;
  cursor: pointer; transition: transform .15s ease, box-shadow .2s ease, background-color .15s;
  /* Defaults live on the base rule, NOT in a later .btn block -- a later block would have equal
     specificity to .btn-primary and would have turned every primary button white. Without these a
     variant-less .btn fell through to the browser's grey system button, which affects ~15 call sites
     including nine public "Get Started" CTAs and the Cash/Check/Comp money controls. */
  background: #fff; color: var(--brand-ink); border-color: var(--border);
}
.btn-primary { background: var(--brand-primary); color: #fff; box-shadow: 0 8px 20px rgba(196,2,35,.25); }
.btn-primary:hover { background: var(--brand-primary-hover); color: #fff; transform: translateY(-2px); box-shadow: 0 14px 28px rgba(196,2,35,.32); }
.btn-primary:disabled { opacity: .45; cursor: not-allowed; transform: none; box-shadow: none; }
.btn-ghost { background: #fff; color: var(--brand-ink); border-color: var(--border); }
.btn-ghost:hover { color: var(--brand-primary); border-color: var(--brand-primary); transform: translateY(-2px); }
.btn-lg { padding: 1rem 2rem; font-size: 1.05rem; }

.eyebrow { font-family: var(--font-sans); color: var(--brand-primary); font-weight: 700; text-transform: uppercase; letter-spacing: .12em; font-size: .78rem; }

/* ---------- Header / nav ---------- */
.site-header { position: sticky; top: 0; z-index: 50; background: rgba(255,255,255,.88); backdrop-filter: blur(12px); border-bottom: 1px solid var(--border); }
.nav { display: flex; align-items: center; justify-content: space-between; height: 4.5rem; }
.nav-logo img { height: 2.6rem; width: auto; display: block; }
.nav-links { display: flex; align-items: center; gap: 1.9rem; }
.nav-link { color: var(--brand-ink); font-weight: 600; font-size: .95rem; }
.nav-link:hover { color: var(--brand-primary); }
.nav-dropdown { position: relative; }
.nav-dropdown > button { display: inline-flex; align-items: center; gap: .3rem; background: none; border: 0; font: inherit; font-weight: 600; color: var(--brand-ink); cursor: pointer; }
.nav-dropdown:hover .nav-menu, .nav-dropdown:focus-within .nav-menu { visibility: visible; opacity: 1; transform: translateY(0); }
.nav-menu { position: absolute; left: 0; top: 100%; min-width: 12rem; background: #fff; border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-md); padding: .5rem; margin-top: .5rem; visibility: hidden; opacity: 0; transform: translateY(-6px); transition: .18s; }
.nav-menu a { display: block; padding: .55rem .8rem; border-radius: .7rem; color: var(--brand-ink); font-size: .92rem; font-weight: 500; }
.nav-menu a:hover { background: var(--cream); color: var(--brand-primary); }
.nav-toggle { display: none; background: none; border: 0; padding: .5rem; cursor: pointer; color: var(--brand-ink); }
.mobile-menu { display: none; border-top: 1px solid var(--border); padding: .5rem 0 1.25rem; }
.mobile-menu a { display: block; padding: .65rem 0; color: var(--brand-ink); font-weight: 600; }
/* Six header items since "Own a Location" joined (10-12): keep each on one line, and close the gaps on narrow desktops. */
.nav-links > a, .nav-links .nav-dropdown > button { white-space: nowrap; }
@media (max-width: 1120px) { .nav-links { gap: 1.1rem; } }
@media (max-width: 900px) { .nav-links { display: none; } .nav-toggle { display: inline-flex; } .mobile-menu.open { display: block; } }

/* ---------- Generic sections ---------- */
.section { padding: 5rem 0; }
.section-surface { background: var(--cream); }
.section-cream2 { background: var(--cream-2); }
.section-head { max-width: 44rem; }
.section-head .eyebrow { display: inline-block; margin-bottom: .6rem; }
.section-head h2 { font-family: var(--font-display); font-size: clamp(1.9rem, 3.6vw, 2.8rem); font-weight: 600; margin: 0; }
.section-head p { color: var(--brand-slate); margin-top: .85rem; font-size: 1.1rem; }
.grid { display: grid; gap: 1.5rem; }
.grid-2 { grid-template-columns: 1fr; } .grid-3 { grid-template-columns: 1fr; }
@media (min-width: 640px) { .grid-2 { grid-template-columns: repeat(2,1fr); } }
@media (min-width: 768px) { .grid-3 { grid-template-columns: repeat(3,1fr); } }

.card { background: #fff; border: 1px solid var(--border); border-radius: var(--radius); padding: 1.75rem; box-shadow: var(--shadow-sm); }
.card h2, .card h3 { margin: 0; font-size: 1.2rem; font-weight: 700; }
.card p { color: var(--brand-slate); margin: .55rem 0 0; }
a.card { display: block; transition: transform .18s ease, box-shadow .25s ease; }
a.card:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }

/* ---------- Homepage hero ---------- */
.hero { position: relative; overflow: hidden; background: linear-gradient(180deg, var(--cream) 0%, #fff 100%); padding: 4rem 0 5rem; }
.hero::before { content: ""; position: absolute; top: -12%; right: -8%; width: 38rem; height: 38rem; border-radius: 50%; background: radial-gradient(circle at 30% 30%, rgba(246,181,59,.18), transparent 60%); pointer-events: none; }
.hero::after { content: ""; position: absolute; bottom: -20%; left: -10%; width: 32rem; height: 32rem; border-radius: 50%; background: radial-gradient(circle at 50% 50%, rgba(196,2,35,.07), transparent 60%); pointer-events: none; }
.hero .container { position: relative; }
.hero-grid { display: grid; gap: 3rem; align-items: center; }
@media (min-width: 940px) { .hero-grid { grid-template-columns: 1.05fr .95fr; } }
.hero-eyebrow { display: inline-flex; align-items: center; gap: .5rem; background: #fff; border: 1px solid var(--border); border-radius: var(--radius-pill); padding: .35rem .9rem; font-size: .82rem; font-weight: 600; color: var(--brand-ink); box-shadow: var(--shadow-sm); }
.hero-eyebrow .dot { width: .5rem; height: .5rem; border-radius: 50%; background: #2bb673; }
.hero h1 { font-family: var(--font-display); font-weight: 600; font-size: clamp(2.6rem, 6vw, 4.4rem); letter-spacing: -.03em; margin: 1.25rem 0 0; }
.hero h1 .accent { color: var(--brand-primary); font-style: italic; }
.hero .lead { color: var(--brand-slate); font-size: 1.2rem; max-width: 34rem; margin-top: 1.25rem; }
.hero-media { position: relative; }
.hero-photo { width: 100%; height: auto; border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); display: block; aspect-ratio: 4 / 3.4; object-fit: cover; }
.float-badge { position: absolute; background: #fff; border-radius: 1rem; box-shadow: var(--shadow-md); padding: .85rem 1.1rem; display: flex; align-items: center; gap: .7rem; }
.float-badge .ic { width: 2.4rem; height: 2.4rem; border-radius: .7rem; display: grid; place-items: center; color: #fff; flex: 0 0 auto; }
.float-badge .ic.red { background: var(--brand-primary); } .float-badge .ic.gold { background: var(--brand-gold); color: var(--brand-ink); }
.float-badge .t { font-weight: 800; font-size: .95rem; line-height: 1.1; }
.float-badge .s { font-size: .76rem; color: var(--brand-slate); }
.float-badge.tl { top: 1.25rem; left: -1rem; } .float-badge.br { bottom: 1.5rem; right: -1rem; }
@media (max-width: 520px) { .float-badge.tl { left: .5rem; } .float-badge.br { right: .5rem; } }

/* trust row under hero */
.hero-trust { display: flex; flex-wrap: wrap; gap: 1.5rem 2rem; margin-top: 2rem; align-items: center; }
.hero-trust .ht { display: flex; align-items: center; gap: .5rem; font-weight: 600; font-size: .9rem; color: var(--brand-ink); }
.hero-trust .ht svg { width: 1.15rem; height: 1.15rem; color: var(--brand-primary); }

/* ---------- ZIP search ---------- */
.zip-form { margin-top: 2rem; max-width: 32rem; }
.zip-row { display: flex; flex-direction: column; gap: .75rem; background: #fff; padding: .5rem; border-radius: var(--radius-pill); border: 1px solid var(--border); box-shadow: var(--shadow-md); }
@media (min-width: 520px) { .zip-row { flex-direction: row; } }
.zip-input { flex: 1; border: 0; border-radius: var(--radius-pill); padding: .85rem 1.4rem; font: inherit; font-size: 1.05rem; background: transparent; }
.zip-input:focus-visible { outline: none; }
.zip-result { min-height: 1.25rem; margin: .6rem 0 0 1.4rem; font-size: .9rem; }
.zip-result .place { color: var(--brand-blue); font-weight: 700; }
.zip-result .muted { color: var(--brand-slate); }

/* ---------- Service cards ---------- */
.care-grid { display: grid; gap: 1.5rem; margin-top: 2rem; }
@media (min-width: 560px) { .care-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 940px) { .care-grid.cols-3 { grid-template-columns: repeat(3, 1fr); } }
.care-card { display: flex; gap: 1.1rem; align-items: flex-start; text-align: left; }
.care-card .icon { flex: 0 0 auto; width: 3.4rem; height: 3.4rem; border-radius: 1rem; display: grid; place-items: center; background: var(--cream-2); color: var(--brand-primary); }
.care-card .icon svg { width: 1.7rem; height: 1.7rem; }
.care-card h2 { font-size: 1.15rem; }

/* ---------- How it works ---------- */
.steps { display: grid; gap: 1.5rem; margin-top: 2.5rem; }
@media (min-width: 768px) { .steps { grid-template-columns: repeat(3, 1fr); } }
.step { text-align: center; padding: 0 .5rem; }
.step .n { width: 3.4rem; height: 3.4rem; margin: 0 auto 1rem; border-radius: var(--radius-pill); display: grid; place-items: center; font-family: var(--font-display); font-weight: 600; font-size: 1.4rem; color: #fff; background: var(--brand-primary); box-shadow: 0 8px 18px rgba(196,2,35,.25); }
.step h3 { font-size: 1.2rem; } .step p { color: var(--brand-slate); margin-top: .4rem; }

/* ---------- Stats ---------- */
.stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2rem 1.5rem; }
@media (min-width: 768px) { .stats { grid-template-columns: repeat(4,1fr); } }
.stat { text-align: center; }
.stat .num { font-family: var(--font-display); font-weight: 600; font-size: 2.6rem; color: var(--brand-primary); line-height: 1; }
.stat .label { color: var(--brand-slate); font-size: .92rem; margin-top: .5rem; }

/* ---------- Highlight / safety band ---------- */
.highlight-band { background: var(--brand-ink); color: #fff; border-radius: var(--radius-lg); padding: 3rem; display: grid; gap: 1.5rem; box-shadow: var(--shadow-lg); }
@media (min-width: 820px) { .highlight-band { grid-template-columns: auto 1fr; align-items: center; } }
.highlight-band .badge-icon { width: 5rem; height: 5rem; border-radius: 1.25rem; background: rgba(255,255,255,.08); color: #fff; display: grid; place-items: center; }
.highlight-band .badge-icon svg { width: 2.7rem; height: 2.7rem; }
.highlight-band h2 { font-family: var(--font-display); font-weight: 600; margin: 0; font-size: 1.9rem; color: #fff; }
.highlight-band p { margin: .6rem 0 0; color: #d9d2cf; max-width: 48rem; font-size: 1.05rem; }
.highlight-band .accent { color: var(--brand-gold); }

/* split feature (image + text) */
.split { display: grid; gap: 3rem; align-items: center; }
@media (min-width: 880px) { .split { grid-template-columns: 1fr 1fr; } .split.flip .split-media { order: 2; } }
.split-media img { width: 100%; height: auto; border-radius: var(--radius-lg); box-shadow: var(--shadow-md); display: block; aspect-ratio: 4/3; object-fit: cover; }
.split h2 { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.8rem,3.4vw,2.6rem); margin: .6rem 0 0; }
.split p { color: var(--brand-slate); margin-top: 1rem; font-size: 1.08rem; }

/* ---------- Trust list / checks ---------- */
.trust-list { display: grid; gap: 1.25rem; margin-top: 1.5rem; }
@media (min-width: 768px) { .trust-list { grid-template-columns: repeat(2,1fr); } }
.trust-item { display: flex; gap: .85rem; align-items: flex-start; }
.trust-item .check { flex: 0 0 auto; width: 1.8rem; height: 1.8rem; border-radius: 50%; background: #e9f7ef; color: #2bb673; display: grid; place-items: center; margin-top: .1rem; }
.trust-item .check svg { width: 1.05rem; height: 1.05rem; }
.trust-item h3 { font-size: 1.08rem; } .trust-item p { color: var(--brand-slate); margin: .25rem 0 0; }

/* ---------- Testimonials ---------- */
.testimonials { display: grid; gap: 1.5rem; margin-top: 2.5rem; }
@media (min-width: 768px) { .testimonials { grid-template-columns: repeat(3,1fr); } }
.quote { background: #fff; border: 1px solid var(--border); border-radius: var(--radius); padding: 1.75rem; box-shadow: var(--shadow-sm); }
.quote .stars { color: var(--brand-gold); letter-spacing: 3px; }
.quote p { margin: .75rem 0 1rem; color: var(--brand-ink); font-size: 1.05rem; }
.quote .who { display: flex; align-items: center; gap: .7rem; font-weight: 700; font-size: .9rem; }
.quote .who .av { width: 2.2rem; height: 2.2rem; border-radius: 50%; background: var(--cream-2); color: var(--brand-primary); display: grid; place-items: center; font-weight: 800; }

/* ---------- Badges / pills / FAQ ---------- */
.badges { display: flex; flex-wrap: wrap; gap: 1rem; justify-content: center; }
.badge-pill { display: inline-flex; align-items: center; gap: .5rem; border: 1px solid var(--border); border-radius: var(--radius-pill); padding: .65rem 1.2rem; font-weight: 600; font-size: .92rem; background: #fff; box-shadow: var(--shadow-sm); }
.badge-pill svg { width: 1.1rem; height: 1.1rem; color: var(--brand-primary); }
.faq { max-width: 48rem; margin: 1.5rem auto 0; }
.faq details { border: 1px solid var(--border); border-radius: var(--radius); padding: 0 1.3rem; margin-bottom: .85rem; background: #fff; box-shadow: var(--shadow-sm); }
.faq summary { cursor: pointer; font-weight: 700; padding: 1.1rem 0; list-style: none; display: flex; justify-content: space-between; gap: 1rem; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--brand-primary); font-size: 1.4rem; line-height: 1; }
.faq details[open] summary::after { content: "\2212"; }
.faq details p { color: var(--brand-slate); margin: 0 0 1.1rem; }

/* ---------- CTA band ---------- */
.cta-band { background: linear-gradient(135deg, var(--brand-primary), #e0356a); color: #fff; border-radius: var(--radius-lg); padding: 3.5rem 2.5rem; text-align: center; box-shadow: var(--shadow-lg); }
.cta-band h2 { font-family: var(--font-display); font-weight: 600; margin: 0; font-size: clamp(1.8rem,3.6vw,2.6rem); color: #fff; }
.cta-band p { margin: .75rem auto 1.75rem; color: #ffe1ea; max-width: 40rem; font-size: 1.1rem; }
.cta-band .btn { background: #fff; color: var(--brand-primary); }
.cta-band .btn:hover { background: #fff; color: var(--brand-primary-hover); transform: translateY(-2px); box-shadow: var(--shadow-md); }

/* ---------- Interior page hero ---------- */
.page-hero { padding: 4.5rem 0 3rem; background: linear-gradient(180deg, var(--cream), #fff); }
.page-hero .eyebrow { display: inline-block; margin-bottom: .5rem; }
.page-hero h1 { font-family: var(--font-display); font-weight: 600; font-size: clamp(2.2rem, 5vw, 3.4rem); margin: .25rem 0 0; max-width: 18ch; }
.page-hero p.lead { color: var(--brand-slate); font-size: 1.15rem; max-width: 42rem; margin-top: 1rem; }
.page-hero-split { display: grid; gap: 2.5rem; align-items: center; }
@media (min-width: 880px) { .page-hero-split { grid-template-columns: 1.1fr .9fr; } }
.page-hero-media img { width: 100%; height: auto; border-radius: var(--radius-lg); box-shadow: var(--shadow-md); aspect-ratio: 4 / 3.2; object-fit: cover; display: block; }

/* ---------- Story / About ---------- */
.story-split { display: grid; gap: 2.5rem; align-items: center; }
@media (min-width: 820px) { .story-split { grid-template-columns: .9fr 1.1fr; } .story-split.flip > .story-media { order: 2; } }
.story-media { text-align: center; }
.founder-photo { width: 100%; max-width: 360px; border-radius: var(--radius-lg); height: auto; box-shadow: var(--shadow-md); }
.story-body h2 { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.7rem,3vw,2.3rem); margin: 0 0 .75rem; }
.story-body p { color: var(--brand-slate); margin: 0 0 1rem; }
.story-body p strong { color: var(--brand-ink); }
.caption { font-size: .85rem; color: var(--brand-slate); margin-top: .75rem; }
.mission-band { background: var(--cream); border-radius: var(--radius-lg); padding: 3.5rem 2.5rem; text-align: center; }
.mission-band p.statement { font-family: var(--font-display); font-weight: 500; font-size: clamp(1.4rem,2.8vw,2rem); line-height: 1.4; max-width: 46rem; margin: .75rem auto 0; color: var(--brand-ink); }
.dual-cta { display: grid; gap: 1.25rem; margin-top: 2rem; }
@media (min-width: 640px) { .dual-cta { grid-template-columns: repeat(2,1fr); } }
.dual-cta .card h3 { margin: 0; font-size: 1.2rem; } .dual-cta .card p { margin: .4rem 0 1rem; }
.press { text-align: center; } .press img { max-width: 100%; height: auto; opacity: .9; }

/* ---------- Footer ---------- */
.site-footer { background: var(--brand-ink); color: #d9d2cf; margin-top: auto; }
.footer-grid { display: grid; grid-template-columns: repeat(2,1fr); gap: 2.5rem; padding: 4rem 0; }
@media (min-width: 768px) { .footer-grid { grid-template-columns: 2fr 1fr 1fr 1fr; } }
.footer-brand .name { font-family: var(--font-display); font-weight: 600; color: #fff; font-size: 1.4rem; }
.footer-brand p { color: #b3a9a5; font-size: .92rem; max-width: 20rem; }
.site-footer h2 { font-size: .82rem; text-transform: uppercase; letter-spacing: .1em; color: #fff; }
.site-footer ul { list-style: none; padding: 0; margin: .9rem 0 0; }
.site-footer li { margin: .5rem 0; }
.site-footer li a { color: #b3a9a5; font-size: .92rem; }
.site-footer li a:hover { color: #fff; }
.footer-base { border-top: 1px solid rgba(255,255,255,.1); }
.footer-base p { color: #8c817d; font-size: .82rem; padding: 1.5rem 0; margin: 0; }

/* ---------- Funnel ---------- */
.funnel { max-width: 760px; margin: 0 auto; } .funnel-wide { max-width: 920px; }
.step-indicator { display: flex; align-items: center; justify-content: center; gap: .5rem; margin-bottom: 1.75rem; }
/* Public 375px check 2026-10-13: four steps overflowed a phone by 2px; let them wrap. Long URLs in an article (the privacy
   policy's opt-out links) overflowed by 64px; let them break. */
@media (max-width: 480px) { .step-indicator { flex-wrap: wrap; row-gap: .4rem; } }
.article-body a, .article a { overflow-wrap: anywhere; }
.step-dot { width: 2.25rem; height: .4rem; border-radius: 999px; background: var(--border); }
.step-dot.active { background: var(--brand-primary); } .step-dot.done { background: var(--brand-blue); }
.funnel h1 { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.8rem,3.5vw,2.6rem); }
.funnel .sub { color: var(--brand-slate); margin-top: .5rem; font-size: 1.1rem; }
.timing-grid { display: grid; gap: 1rem; margin-top: 2rem; }
@media (min-width: 560px) { .timing-grid { grid-template-columns: repeat(2,1fr); } }
.timing-card { text-align: center; font-weight: 700; padding: 1.5rem; }
.timing-card span.note { display: block; font-weight: 400; font-size: .88rem; color: var(--brand-slate); margin-top: .3rem; }
.funnel-back { display: inline-block; margin-bottom: 1rem; color: var(--brand-slate); font-size: .92rem; font-weight: 600; }
.context-chips { display: flex; flex-wrap: wrap; gap: .5rem; justify-content: center; margin-top: .75rem; }
.chip { background: #fff; border: 1px solid var(--border); border-radius: 999px; padding: .3rem .85rem; font-size: .82rem; color: var(--brand-slate); }
.chip strong { color: var(--brand-ink); }
.choice-grid { display: grid; gap: 1.5rem; margin-top: 2.5rem; }
@media (min-width: 640px) { .choice-grid { grid-template-columns: repeat(2,1fr); } }
.choice .title { font-size: 1.3rem; font-weight: 800; } .choice .title.primary { color: var(--brand-primary); } .choice .title.blue { color: var(--brand-blue); }

/* ---------- Forms ---------- */
.form-card { background: #fff; border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 2rem; box-shadow: var(--shadow-md); margin-top: 1.5rem; }
.form-section + .form-section { margin-top: 1.75rem; padding-top: 1.5rem; border-top: 1px solid var(--border); }
.form-section > h2 { font-size: 1.1rem; margin: 0 0 1rem; }
.field-grid { display: grid; gap: 1.1rem; }
@media (min-width: 560px) { .field-grid.cols-2 { grid-template-columns: 1fr 1fr; } }
/* min-width: 0 because a grid/flex ITEM defaults to min-width:auto and floors at its content's
   min-content width. A native date input's intrinsic width is ~330px, so .field refused to shrink
   below it inside a 254px track and the input's own max-width:100% resolved against the oversized
   .field -- 25px of page overflow at 375px (measured 2026-09-22). Third instance of this same rule
   on this estate, after .portal-grid and .cal-grid; if a form ever runs off a phone, look here. */
.field { display: flex; flex-direction: column; gap: .4rem; min-width: 0; } .field.span-2 { grid-column: 1 / -1; }
.field label { font-size: .88rem; font-weight: 700; color: var(--brand-ink); } .field .req { color: var(--brand-primary); }
/* min-width:0 + max-width:100% are load-bearing, not cosmetic. A <select> sizes itself to its widest
   option, and as a flex item it defaults to min-width:auto -- so the franchisee "Move to another
   location" picker, whose options include names like "Denton and NE Tarrant County", widened the whole
   PAGE by 108px at 375px rather than shrinking inside its row. Constraining every form control here
   fixes that wherever a control sits beside a button, instead of one row at a time. */
.field input, .field select, .field textarea { border: 1px solid var(--border); border-radius: .8rem; padding: .75rem .9rem; font: inherit; background: #fff; min-width: 0; max-width: 100%; }
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--brand-primary); outline: none; }
.field textarea { min-height: 5rem; resize: vertical; }
.field-hint { font-size: .82rem; color: var(--brand-slate); }
/* For a <legend> heading a group of related inputs (e.g. the three date-of-birth boxes). A legend is
   not a label, so it does not inherit the .field label rule above and needs its own. */
.field-label { font-size: .88rem; font-weight: 700; color: var(--brand-ink); padding: 0; }
.checkbox-row { display: flex; gap: .6rem; align-items: flex-start; } .checkbox-row input { margin-top: .25rem; flex-shrink: 0; } .checkbox-row label { font-weight: 500; font-size: .92rem; }
.text-danger { color: var(--brand-primary); font-size: .82rem; }
.validation-summary-errors { background: #fdecef; border: 1px solid #f5c2cc; border-radius: .8rem; padding: .85rem 1.1rem; margin-bottom: 1rem; }
.validation-summary-errors ul { margin: 0; padding-left: 1.1rem; }
/* MUST stay after the rule above. The validation-summary tag helper keeps the literal
   class="validation-summary-errors" from the markup and ADDS validation-summary-valid when there is
   nothing to report, so the element carries both classes and the pink box was painted on every clean
   form — an empty red bar above the login fields, on 43 pages. Both selectors are a single class, so
   they have equal specificity and only source order decides the winner: move this up and the box
   comes back. */
.validation-summary-valid { display: none; }
.form-actions { margin-top: 1.5rem; } .legal { font-size: .82rem; color: var(--brand-slate); margin-top: 1rem; }
.success { max-width: 640px; margin: 0 auto; text-align: center; }
.success .seal { width: 5rem; height: 5rem; border-radius: 999px; background: #e9f7ef; color: #2bb673; display: grid; place-items: center; margin: 0 auto 1.5rem; box-shadow: var(--shadow-sm); }
.success .seal svg { width: 2.7rem; height: 2.7rem; }

/* ---------- Legal ---------- */
.legal-notice { background: #fff8e1; border: 1px solid #ffe2a8; color: #6b5300; border-radius: .8rem; padding: .9rem 1.1rem; font-size: .88rem; margin-bottom: 1.5rem; }
.legal-updated { color: var(--brand-slate); font-size: .88rem; margin-top: .25rem; }

/* ---------- Blog ---------- */
.blog-toolbar { display: flex; flex-wrap: wrap; gap: 1rem; align-items: center; justify-content: space-between; margin-top: 1.5rem; }
.cat-filter { display: flex; flex-wrap: wrap; gap: .5rem; }
.cat-chip { display: inline-block; padding: .6rem 1rem; border-radius: 999px; border: 1px solid var(--border); background: #fff; color: var(--brand-ink); font-size: .88rem; font-weight: 600; }
.cat-chip:hover { border-color: var(--brand-primary); color: var(--brand-primary); }
.cat-chip.active { background: var(--brand-primary); border-color: var(--brand-primary); color: #fff; }
.blog-search { display: flex; gap: .5rem; }
.blog-search input { border: 1px solid var(--border); border-radius: 999px; padding: .6rem 1.1rem; font: inherit; min-width: 13rem; }
.post-grid { display: grid; gap: 1.75rem; margin-top: 2rem; }
@media (min-width: 600px) { .post-grid { grid-template-columns: repeat(2,1fr); } }
@media (min-width: 920px) { .post-grid { grid-template-columns: repeat(3,1fr); } }
.post-card { display: flex; flex-direction: column; background: #fff; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-sm); transition: transform .18s, box-shadow .25s; }
.post-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
.post-card .thumb { position: relative; aspect-ratio: 16/9; background: linear-gradient(135deg, var(--cream-2), var(--cream)); background-size: cover; background-position: center; display: grid; place-items: center; }
.post-card .thumb .cat-tag { background: var(--brand-primary); color: #fff; font-size: .72rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; padding: .3rem .7rem; border-radius: 999px; }
.post-card .thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.post-card .thumb.has-img .cat-tag { position: absolute; top: .7rem; left: .7rem; z-index: 1; }
.post-card .body { padding: 1.4rem; display: flex; flex-direction: column; flex: 1; }
.post-card h2 { font-size: 1.15rem; margin: 0; } .post-card h2 a { color: var(--brand-ink); } .post-card h2 a:hover { color: var(--brand-primary); }
.post-card .excerpt { color: var(--brand-slate); font-size: .92rem; margin: .5rem 0 1rem; }
.post-meta { margin-top: auto; font-size: .8rem; color: var(--brand-slate); }
.empty-state { text-align: center; color: var(--brand-slate); padding: 3rem 0; }
.article { max-width: 44rem; margin: 0 auto; }
.article .kicker { color: var(--brand-primary); font-weight: 700; text-transform: uppercase; letter-spacing: .08em; font-size: .8rem; }
.article h1 { font-family: var(--font-display); font-weight: 600; font-size: clamp(2rem,4vw,3rem); margin: .5rem 0 0; }
.article .byline { color: var(--brand-slate); font-size: .9rem; margin-top: .75rem; }
.article-lead { width: 100%; aspect-ratio: 16/9; object-fit: cover; border-radius: var(--radius); margin-top: 2rem; }
.article-body { margin-top: 2rem; font-size: 1.1rem; line-height: 1.8; }
.article-body h2 { font-family: var(--font-display); font-weight: 600; font-size: 1.5rem; margin: 2rem 0 .5rem; }
.article-body p { margin: 0 0 1.1rem; } .article-cta { margin-top: 2.5rem; }

/* ---------- Portal ---------- */
.portal { padding: 2.5rem 0 4rem; }
.portal-grid { display: grid; gap: 2rem; }
@media (min-width: 860px) { .portal-grid { grid-template-columns: 240px 1fr; align-items: start; } }
/* Todd 10-01: the side nav is sticky, and a franchisee's runs past the bottom of the window, so its lower half could not be
   reached -- the wheel over it scrolled the page instead. Capped to the window below the header (top 5.5rem + a margin), it
   scrolls on its own; overscroll-behavior stops the page moving once the nav reaches either end. Groups open inline
   (details), so nothing pops out to be clipped. Desktop only: below 860px the nav is the horizontal strip. */
@media (min-width: 860px) { .portal-nav { max-height: calc(100vh - 6.5rem); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; } }
.portal-nav { background: #fff; border: 1px solid var(--border); border-radius: var(--radius); padding: .75rem; position: sticky; top: 5.5rem; box-shadow: var(--shadow-sm); }
.portal-nav a { display: block; padding: .65rem .85rem; border-radius: .7rem; color: var(--brand-ink); font-weight: 600; font-size: .92rem; }
.portal-nav a:hover { background: var(--cream); color: var(--brand-primary); }
.portal-nav a.active { background: var(--brand-primary); color: #fff; }

/* Below the two-column breakpoint the nav previously stacked its full link list ABOVE the page
   content on every portal page -- roughly 860px of scrolling before a member saw "Requests", and 53
   items for a franchisee on a tablet in portrait. Turn it into a single horizontally-scrolling strip
   so the content starts immediately. Applies to all five portals, which share .portal-nav. */
@media (max-width: 859px) {
  /* The single column must be allowed to shrink. A bare `1fr` track floors at the item's min-content
     width, and .portal-nav below is a flex row whose intrinsic width is the whole link list. */
  .portal-grid { grid-template-columns: minmax(0, 1fr); }

  .portal-nav {
    position: static;
    display: flex; flex-wrap: nowrap; gap: .4rem;
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    padding: .5rem; margin-bottom: .25rem;
    scrollbar-width: thin;
    /* Load-bearing. As a grid item this defaults to min-width:auto, so the nav refused to shrink
       below its own content and widened the whole PAGE instead of scrolling inside itself --
       measured on prod as 141px of horizontal document scroll on the franchisee sitter-detail page.
       It only showed up where an expanded nav group made the content wide enough, which is why the
       pages I checked first looked fine. overflow-x cannot take effect without this. */
    min-width: 0;
  }
  .portal-nav a { flex: 0 0 auto; white-space: nowrap; padding: .6rem .9rem; }
  /* Collapsible groups (the franchisee nav) stay as single chips that expand in place. */
  .portal-nav .nav-group { flex: 0 0 auto; }
  .portal-nav .nav-group > summary { white-space: nowrap; padding: .6rem .9rem; }
  .portal-nav .nav-group[open] { flex: 1 0 100%; }

  /* The location block is a BLOCK heading with a border and its own sub-link, so as a flex item in
     the strip above it took a whole column's width and forced the strip ~220px tall -- which is what
     pushed the links off-screen. Full-width row of its own, compact. */
  .portal-nav .nav-loc,
  .portal-nav .nav-loc-switch { flex: 1 0 100%; margin-bottom: 0; padding-bottom: .5rem; }

  /* ---- With JS: a disclosure instead of a sideways strip (see site.js). -------------------
     Julia, 2026-09-22: 99% of sitters are on phones and half are not tech-savvy. An item hidden
     off-screen sideways, with no cue that it exists, is the pattern that audience cannot use. The
     button names the page you are on and opens the whole list vertically. */
  .portal-nav-toggle {
    display: flex; align-items: center; justify-content: space-between; gap: .5rem;
    width: 100%; margin-bottom: .75rem;
    padding: .8rem 1rem;
    background: #fff; border: 1px solid var(--border); border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    font: inherit; font-weight: 600; color: var(--brand-ink);
    text-align: left; cursor: pointer;
  }
  .portal-nav-toggle svg { width: 1.15rem; height: 1.15rem; flex: 0 0 auto; transition: transform .15s ease; }
  .portal-nav-toggle[aria-expanded="true"] svg { transform: rotate(180deg); }
  .portal-nav-toggle-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* Open: a plain vertical list, which is the desktop shape and the one every link is readable in. */
  .portal-nav.is-mobile {
    display: block; overflow-x: visible;
    padding: .5rem; margin-bottom: 1rem;
  }
  .portal-nav.is-mobile a,
  .portal-nav.is-mobile .nav-group > summary { white-space: normal; padding: .7rem .85rem; }
  .portal-nav.is-mobile.is-collapsed { display: none; }
}

/* The toggle is a phone-only control; it must never appear beside the sticky sidebar. */
@media (min-width: 860px) { .portal-nav-toggle { display: none; } }
.portal-nav form { margin: .5rem 0 0; padding-top: .5rem; border-top: 1px solid var(--border); }
.portal-nav button.linklike { width: 100%; text-align: left; background: none; border: 0; padding: .65rem .85rem; border-radius: .7rem; color: var(--brand-slate); font: inherit; font-weight: 600; cursor: pointer; }
.portal-nav button.linklike:hover { background: var(--cream); color: var(--brand-primary); }
/* Franchisee back-office nav: location header, collapsible groups, sub-items, counts, coming-soon */
.portal-nav .nav-loc { font-family: var(--font-display); font-weight: 600; font-size: 1.05rem; padding: .35rem .85rem .7rem; color: var(--brand-ink); border-bottom: 1px solid var(--border); margin-bottom: .4rem; }
.portal-nav .nav-back { color: var(--brand-slate) !important; font-size: .85rem; }
/* The location switcher IS the sidebar heading -- same type as .nav-loc, so it reads as the page's
   own title rather than a form control dropped above it. The native select is stripped back and given
   our own chevron; the whole row is the hit target, which matters on a phone. */
.portal-nav .nav-loc-switch { position: relative; padding: .35rem .85rem .7rem; border-bottom: 1px solid var(--border); margin-bottom: .4rem; }
.portal-nav .nav-loc-switch select {
  appearance: none; -webkit-appearance: none;
  width: 100%; padding: .1rem 1.6rem .1rem 0;
  background: none; border: 0; border-radius: 0;
  font-family: var(--font-display); font-weight: 600; font-size: 1.05rem;
  color: var(--brand-ink); cursor: pointer; line-height: 1.3;
}
.portal-nav .nav-loc-switch select:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; border-radius: .2rem; }
.portal-nav .nav-loc-switch:hover select { color: var(--brand); }
.portal-nav .nav-loc-chev { position: absolute; right: .85rem; top: .45rem; width: 1.1rem; height: 1.1rem; color: var(--brand-slate); pointer-events: none; }
.portal-nav .nav-loc-switch:hover .nav-loc-chev { color: var(--brand); }
.portal-nav .nav-loc-chev svg { width: 100%; height: 100%; display: block; }
.portal-nav details.nav-group { margin: 0; }
.portal-nav .nav-divider { display: block; margin: .45rem .85rem .2rem; padding-top: .45rem; border-top: 1px solid var(--border);
  font-size: .7rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--brand-slate); }
.portal-nav details.nav-group > summary { list-style: none; cursor: pointer; padding: .65rem .85rem; border-radius: .7rem; color: var(--brand-ink); font-weight: 600; font-size: .92rem; display: flex; justify-content: space-between; align-items: center; }
.portal-nav details.nav-group > summary::-webkit-details-marker { display: none; }
.portal-nav details.nav-group > summary:hover { background: var(--cream); color: var(--brand-primary); }
.portal-nav details.nav-group > summary::after { content: "\25B8"; color: var(--brand-slate); font-size: .7rem; }
.portal-nav details.nav-group[open] > summary::after { content: "\25BE"; }
.portal-nav .nav-sub { display: flex; justify-content: space-between; align-items: center; gap: .5rem; padding: .5rem .85rem .5rem 1.6rem; border-radius: .7rem; font-size: .88rem; font-weight: 500; color: var(--brand-ink); }
.portal-nav a.nav-sub:hover { background: var(--cream); color: var(--brand-primary); }
.portal-nav a.nav-sub.active { background: var(--brand-primary); color: #fff; }
.portal-nav span.nav-soon { color: var(--brand-slate); opacity: .75; cursor: default; }
.portal-nav .nav-count { font-size: .72rem; font-weight: 700; color: var(--brand-blue); background: var(--cream); border-radius: 999px; padding: .05rem .5rem; }
.portal-nav a.nav-sub.active .nav-count { color: #fff; background: rgba(255,255,255,.25); }
/* Franchisee calendar top status bar (legacy incHeader.asp count breadcrumb) */
.topstats { display: flex; flex-wrap: wrap; gap: .35rem .9rem; padding: .75rem 1rem; background: #fff; border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-sm); margin-bottom: 1.25rem; font-size: .85rem; }
.topstats .topstat { color: var(--brand-blue); font-weight: 600; }
.topstats a.topstat:hover { color: var(--brand-primary); text-decoration: underline; }
.topstats .topstat.soon { color: #b7b2aa; font-weight: 500; cursor: default; }
.portal-head { margin-bottom: 1.5rem; }
.portal-head h1 { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.7rem,3vw,2.3rem); margin: 0; }
.portal-head p { color: var(--brand-slate); margin: .25rem 0 0; }
/* Neutral default: without one, an unmodified .verify-badge had padding and a pill radius but no
   background or colour, so statuses like "Unapproved" or "Pending" rendered as bare text rather than
   a badge. .ok / .no override it below. */
.verify-badge { display: inline-flex; align-items: center; gap: .35rem; font-size: .78rem; font-weight: 700; padding: .2rem .65rem; border-radius: 999px; background: var(--cream-2); color: var(--brand-slate); }
.verify-badge.ok { background: #e9f7ef; color: #1f7a3d; } .verify-badge.no { background: #fdecef; color: var(--brand-primary); }
.dash-grid { display: grid; gap: 1.25rem; } @media (min-width: 560px) { .dash-grid { grid-template-columns: repeat(2,1fr); } }
a.dash-tile { display: block; } .dash-tile h2 { font-size: 1.1rem; margin: 0; } .dash-tile p { color: var(--brand-slate); font-size: .92rem; margin: .35rem 0 0; }
.info-rows { display: grid; gap: .9rem; }
/* minmax(0, 1fr) rather than 1fr: a bare fr track floors at the cell's min-content width, so a value
   with no spaces in it holds the column open and widens the page. Real data does this -- a member's
   Email field legitimately holds comma-joined addresses ("a@x.com,b@x.com", 42 unbreakable characters),
   which pushed this row 76px past a 375px viewport. Used by 34 views, so it is worth fixing here. */
.info-row { display: grid; grid-template-columns: 11rem minmax(0, 1fr); gap: 1rem; padding-bottom: .9rem; border-bottom: 1px solid var(--border); }
/* On a phone the 11rem label column leaves 183px for the value, which is not enough for a money row
   or a name plus a control. Label above value instead -- the same information, readable. */
@media (max-width: 560px) { .info-row { grid-template-columns: minmax(0, 1fr); gap: .2rem; } }
.info-row:last-child { border-bottom: 0; padding-bottom: 0; }
.info-row .k { color: var(--brand-slate); font-size: .92rem; } .info-row .v { font-weight: 600; overflow-wrap: anywhere; }
@media (max-width: 520px) { .info-row { grid-template-columns: minmax(0, 1fr); gap: .15rem; } }
.entity { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; }
.entity h2, .entity h3 { margin: 0; font-size: 1.1rem; } .entity .sub { color: var(--brand-slate); font-size: .88rem; }
.pill { font-size: .75rem; font-weight: 700; color: var(--brand-blue); background: var(--cream); border-radius: 999px; padding: .25rem .7rem; white-space: nowrap; }
/* State pills: a thing that is public (ok) or waiting on someone else (warn). */
.pill-ok { color: #1d6b3a; background: #e3f4e8; }
.pill-warn { color: #8a5a00; background: #fff3d6; }
.stub-note { font-size: .82rem; color: var(--brand-slate); margin-top: 1.25rem; font-style: italic; }
.entity-actions { display: flex; align-items: center; gap: 1rem; margin-top: 1rem; padding-top: .85rem; border-top: 1px solid var(--border); }
.entity-actions form { margin: 0; }
/* Hit area, not looks: padding:0 gave a ~14px target on controls that delete a child,
   cancel a job or block a sitter. Negative margin keeps the visual layout identical. */
.btn-link { background: none; border: 0; padding: .6rem .25rem; margin: -.6rem -.25rem; font: inherit; font-weight: 700; font-size: .9rem; color: var(--brand-blue); cursor: pointer; }
.btn-link:hover { text-decoration: underline; } .btn-link.danger { color: var(--brand-primary); }

/* Type-ahead filter over the franchisee job-detail candidate list. Defined here rather than inline
   because .field-error once shipped as markup referencing a class that did not exist, so validation
   failures rendered as unstyled text nobody noticed. */
.candidate-filter { margin: .75rem 0 1rem; }
.candidate-filter input { width: 100%; max-width: 22rem; border: 1px solid var(--border); border-radius: .8rem; padding: .6rem .8rem; font: inherit; background: #fff; }
.candidate-filter input:focus { border-color: var(--brand-primary); outline: none; }

/* ---------- Sitter calendar ---------- */
.cal-nav { display: flex; align-items: center; gap: .75rem; }
.cal-nav .btn { padding: .5rem .9rem; }
.cal-month { font-family: var(--font-display); font-weight: 600; font-size: 1.25rem; min-width: 9rem; text-align: center; }
/* wrap, not overflow: at 375px the six items ran off the right edge and the last one read "Ano... loc"
   (measured 2026-09-22). Each item keeps its dot and label together. */
.cal-legend { display: flex; flex-wrap: wrap; gap: .5rem 1.25rem; margin-bottom: 1rem; font-size: .85rem; color: var(--brand-slate); }
.cal-legend > span { white-space: nowrap; }
.cal-legend .dot { display: inline-block; width: .7rem; height: .7rem; border-radius: 50%; margin-right: .35rem; vertical-align: middle; }
.dot.avail { background: #2bb673; } .dot.out { background: var(--brand-primary); } .dot.job { background: var(--brand-blue); }
/* minmax(0, 1fr), not 1fr: a bare 1fr floors at the track's MIN-CONTENT, and .cal-pill is
   white-space:nowrap, so each of the seven columns refused to go narrower than "8:00 AM-1:00 PM" and
   the grid widened the whole PAGE instead -- 180px of horizontal document scroll at 375px (measured
   2026-09-22, the sweep of all 163 portal routes). The pill already ellipsises; it just never got the
   chance. Same lesson as .portal-grid above. */
.cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
.cal-dow { background: var(--cream); padding: .6rem; text-align: center; font-weight: 700; font-size: .78rem; color: var(--brand-slate); text-transform: uppercase; letter-spacing: .04em; border-bottom: 1px solid var(--border); }
.cal-cell { min-height: 6.5rem; border-right: 1px solid var(--border); border-bottom: 1px solid var(--border); padding: .35rem; display: flex; flex-direction: column; gap: .25rem; position: relative; }
/* The whole day is the tap target for setting availability, but it sits BEHIND the job links so those
   still open the job (Julia, 2026-09-22: set availability on the calendar, as the legacy does). */
.cal-day-hit { position: absolute; inset: 0; z-index: 0; border-radius: .2rem; }
.cal-day-hit:hover { background: var(--cream); }
.cal-day-hit:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.cal-cell > *:not(.cal-day-hit) { position: relative; z-index: 1; pointer-events: none; }
.cal-cell a:not(.cal-day-hit) { pointer-events: auto; }
.cal-cell.picked { box-shadow: inset 0 0 0 2px var(--brand); }

/* The day panel: two big choices, the sitter's own saved times as chips, and an "other hours" form.
   No JavaScript anywhere in it -- plain links and forms, so it works on any phone and Back behaves. */
.cal-daypanel { margin-bottom: 1rem; }
.cal-choices { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .75rem; }
.cal-choices form { margin: 0; }
.cal-choices .btn { width: 100%; }
@media (min-width: 480px) { .cal-choices .btn { width: auto; } }
.cal-hours { margin-top: 1rem; }
.cal-hours > summary { cursor: pointer; font-weight: 600; padding: .5rem 0; }
.cal-hours-form { display: flex; flex-wrap: wrap; gap: .75rem; align-items: flex-end; margin-top: .5rem; }
.cal-hours-form .field { flex: 1 1 8rem; }
.cal-cell:nth-child(7n) { border-right: 0; }
.cal-cell.empty { background: #fcfaf8; }
.cal-cell.today { background: var(--cream-2); }
.cal-num { font-size: .82rem; font-weight: 700; color: var(--brand-ink); }
.cal-cell.today .cal-num { color: var(--brand-primary); }
.cal-pill { font-size: .68rem; font-weight: 600; border-radius: .4rem; padding: .12rem .35rem; line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-pill.avail { background: #e9f7ef; color: #1f7a3d; } .cal-pill.out { background: #fdecef; color: var(--brand-primary); } .cal-pill.job { background: #e8f0f9; color: var(--brand-blue); }
/* Done, so it recedes rather than competing with upcoming work. */
.cal-pill.job.done { background: #f1f2f4; color: #5b6472; font-weight: 500; }
/* A job at another location: one flat colour and no status colour, as the legacy does. */
.cal-pill.visiting { background: #ede9fb; color: #4c3d9e; border: 1px solid #cfc4f2; }
a.cal-pill { display: block; text-decoration: none; }
@media (max-width: 640px) { .cal-cell { min-height: 4.5rem; } .cal-pill { font-size: .6rem; } }

/* ---------- Job timeline ---------- */
.timeline { position: relative; padding-left: 1.25rem; }
.timeline::before { content: ""; position: absolute; left: .3rem; top: .4rem; bottom: .4rem; width: 2px; background: var(--border); }
.tl-item { position: relative; padding: 0 0 1.25rem; }
.tl-item:last-child { padding-bottom: 0; }
.tl-dot { position: absolute; left: -1.1rem; top: .35rem; width: .65rem; height: .65rem; border-radius: 50%; background: var(--brand-primary); box-shadow: 0 0 0 3px #fff; }
.tl-body .tl-time { font-size: .78rem; color: var(--brand-slate); font-weight: 600; }
.tl-body p { margin: .15rem 0 .35rem; }
.tl-body form { margin: 0; }

/* Timeline markers that carry an icon. The icon marker is larger than the plain .tl-dot, so it is
   positioned to keep the SAME centre: the dot's centre sits at (-1.1rem + .325rem) = -.775rem from
   the item's left edge, so a 1.25rem marker starts .625rem left of that. Change one of these four
   numbers and the markers drift off the 2px rail -- .timeline padding-left, .timeline::before left,
   .tl-dot left and .tl-dot-icon left all move together.
   The white background does the same job as .tl-dot's box-shadow: it masks the rail behind it. */
.tl-dot-icon {
    left: -1.4rem; top: .05rem;
    width: 1.25rem; height: 1.25rem;
    border-radius: 50%;
    background: #fff;
    box-shadow: none;
    display: flex; align-items: center; justify-content: center;
    color: var(--brand-primary);
}
/* Stroke and fill must be set HERE rather than on the sprite root: presentation attributes on the
   root <svg> of a sprite do not reach the shadow tree a <use> clones, and the icons render as solid
   black boxes if you rely on them. Each <symbol> also carries its own, belt and braces. */
.tl-icon { width: 1.05rem; height: 1.05rem; display: block; fill: none; stroke: currentColor; }

/* ---------- Timeline icon picker ---------- */
/* A radio group styled as a grid of glyphs. The native radio stays in the DOM and keeps focus and
   keyboard behaviour -- it is moved off-screen rather than display:none, which would take it out of
   the tab order and out of the accessibility tree. Each option carries an .sr-only text label, so
   the group announces "Meal Time" rather than "radio button". */
.icon-picker { border: 0; padding: 0; margin: 0 0 .75rem; }
.icon-picker legend { padding: 0; margin-bottom: .4rem; }
.icon-picker-grid { display: flex; flex-wrap: wrap; gap: .35rem; }
.icon-opt { position: relative; display: inline-flex; cursor: pointer; }
.icon-opt input {
    position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0;
}
.icon-opt-face {
    display: flex; align-items: center; justify-content: center;
    width: 2.1rem; height: 2.1rem;
    border: 1px solid var(--border); border-radius: 8px;
    color: var(--brand-slate); background: #fff;
    transition: border-color .12s, color .12s, background .12s;
}
.icon-opt:hover .icon-opt-face { border-color: var(--brand-primary); color: var(--brand-primary); }
/* Adjacent sibling rather than :has(). The input sits immediately before its face, so
   `input:checked + .face` says the same thing with a selector that has been universally supported
   for far longer -- no reason to reach for :has() when the markup already gives us the sibling.
   :focus-visible draws the same ring the rest of the app uses, so keyboard users can see where they
   are as they arrow through the grid.
   Selector correctness is asserted in TimelineIconTests via Element.matches(); the painted result
   was not verified in-browser, because the preview pane was hidden for this session and a hidden tab
   suspends style recalculation -- getComputedStyle returns stale values there and rAF never fires. */
.icon-opt input:checked + .icon-opt-face {
    border-color: var(--brand-primary); color: var(--brand-primary); background: #fdf2f4;
}
.icon-opt input:focus-visible + .icon-opt-face {
    outline: 2px solid var(--brand-primary); outline-offset: 2px;
}
.icon-opt-none { font-size: .95rem; line-height: 1; }
.icon-opt .tl-icon { width: 1.15rem; height: 1.15rem; }

/* ---------- Dashboard job rows ---------- */
/* flex-wrap and min-width:0 keep this row inside the page on a phone. It is the list row for 11 views
   (members, sitters, jobs, credits, invoices, pets...), and without them a long name plus the trailing
   "View ->" simply overflowed: measured 128px of horizontal document scroll on the franchisee members
   list at 375px. The trailing action drops to the next line instead of off the screen. */
.job-row { display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap; min-width: 0; padding: .85rem 0; border-bottom: 1px solid var(--border); color: var(--brand-ink); }
/* The text block must be allowed to shrink, or it floors at its longest unbreakable word.
   overflow-wrap covers the case where that word is longer than the phone itself -- a customer-entered
   name with no spaces, or a long email address. Surfaced by a 101-character dev-data name, but real
   records contain long unbroken emails, and one of those should not push the page sideways. */
.job-row > * { min-width: 0; overflow-wrap: anywhere; }
.job-row:last-child { border-bottom: 0; }
.job-row:hover { color: var(--brand-primary); }
/* A row holding several links (the office job list) does not light up as one; each link does. */
.job-row--links:hover { color: var(--brand-ink); }
.job-row strong { font-weight: 700; }

/* ---------- Sitter chat ---------- */
.chat-thread { display: flex; align-items: center; gap: .85rem; padding: .9rem .25rem; border-bottom: 1px solid var(--border); color: var(--brand-ink); }
.chat-thread:last-child { border-bottom: 0; }
.chat-thread:hover { color: var(--brand-primary); }
.chat-thread .av { flex: 0 0 auto; width: 2.6rem; height: 2.6rem; border-radius: 50%; background: var(--cream-2); color: var(--brand-primary); display: grid; place-items: center; font-weight: 800; text-transform: uppercase; }
.chat-thread .ct-body { flex: 1; min-width: 0; }
.chat-thread .ct-top { display: flex; justify-content: space-between; align-items: center; gap: .5rem; }
.chat-thread .ct-msg { color: var(--brand-slate); font-size: .9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-unread { background: var(--brand-primary); color: #fff; font-size: .72rem; font-weight: 700; min-width: 1.3rem; height: 1.3rem; padding: 0 .4rem; border-radius: 999px; display: inline-grid; place-items: center; }
.chat-stream { display: flex; flex-direction: column; gap: .85rem; }
.chat-msg { max-width: 78%; align-self: flex-start; }
.chat-msg.me { align-self: flex-end; text-align: right; }
.chat-msg .bubble { display: inline-block; padding: .65rem .95rem; border-radius: 1.1rem; background: var(--cream); color: var(--brand-ink); border-top-left-radius: .3rem; }
.chat-msg.me .bubble { background: var(--brand-primary); color: #fff; border-top-left-radius: 1.1rem; border-top-right-radius: .3rem; }
.chat-time { font-size: .72rem; color: var(--brand-slate); margin-top: .2rem; }
/* Member-facing sitter browse */
.sitter-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 1.25rem; }
.sitter-card { display: flex; flex-direction: column; background: #fff; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-sm); transition: transform .18s, box-shadow .25s; color: inherit; }
.sitter-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
.sitter-photo { position: relative; aspect-ratio: 1/1; background: linear-gradient(135deg, var(--cream-2), var(--cream)); }
.sitter-photo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.sitter-flag { position: absolute; top: .6rem; left: .6rem; font-size: .68rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; padding: .25rem .6rem; border-radius: 999px; color: #fff; }
.sitter-flag.preferred { background: var(--brand-primary); }
.sitter-flag.blocked { background: var(--brand-slate); }
.sitter-body { padding: 1rem 1.1rem 1.2rem; }
.sitter-body h2 { font-size: 1.1rem; margin: 0; color: var(--brand-ink); }
.sitter-age { color: var(--brand-slate); font-size: .9rem; margin: .15rem 0 .6rem; }
.sitter-detail { display: grid; grid-template-columns: 160px minmax(0, 1fr); gap: 1.5rem; align-items: start; }
.sitter-detail-photo { aspect-ratio: 1/1; border-radius: var(--radius); overflow: hidden; background: linear-gradient(135deg, var(--cream-2), var(--cream)); }
.sitter-detail-photo img { width: 100%; height: 100%; object-fit: cover; }
.sitter-actions { display: flex; flex-wrap: wrap; gap: .75rem; align-items: center; margin-top: 1.1rem; }
.review-list { display: flex; flex-direction: column; gap: 1rem; }
.review { margin: 0; padding: 1rem 1.25rem; background: var(--cream); border-radius: var(--radius); border: 1px solid var(--border); }
.review p { margin: 0 0 .4rem; color: var(--brand-ink); }
.review cite { color: var(--brand-slate); font-size: .88rem; font-style: normal; }
@media (max-width: 560px) { .sitter-detail { grid-template-columns: minmax(0, 1fr); } .sitter-detail-photo { max-width: 200px; } }

/* Checkbox pills (e.g. pet selection on a request form) */
.check-grid { display: flex; flex-wrap: wrap; gap: .6rem; }
.check-pill { display: inline-flex; align-items: center; gap: .5rem; padding: .5rem .9rem; border: 1px solid var(--brand-border); border-radius: 999px; cursor: pointer; background: #fff; }
.check-pill input { accent-color: var(--brand-primary); }
/* Simple data table (billing payment history) */
.data-table { width: 100%; border-collapse: collapse; font-size: .95rem; }
.data-table th, .data-table td { text-align: left; padding: .6rem .5rem; border-bottom: 1px solid var(--border); }
.data-table th { font-size: .8rem; text-transform: uppercase; letter-spacing: .04em; color: var(--brand-slate); }
.data-table .num { text-align: right; white-space: nowrap; }
/* Let wide tables scroll instead of blowing out the card and giving the whole document a horizontal
   scrollbar. 34 views use .data-table and none had any mobile treatment -- the worst are the ones
   whose users are on phones (sitter Payments is 14 columns, member Billing 12). Scoped to narrow
   viewports so desktop table layout is untouched; a per-table card restack is the better long-term
   answer for the member- and sitter-facing ones. */
@media (max-width: 860px) {
  .data-table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }

  /* Opt-in card stacking, for the tables whose readers are on a phone. Sideways scrolling is a
     tolerable fallback for a franchisee at a desk, but a parent checking a bill or a sitter checking
     a payout should not have to drag a 5-to-7 column grid around. Each row becomes a card and each
     cell carries its own label, so the columns survive the loss of the header. Needs data-label on
     the cells -- without one a cell just renders unlabelled rather than breaking. */
  .data-table.stack-mobile { display: block; overflow-x: visible; }
  .data-table.stack-mobile thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; }
  .data-table.stack-mobile tbody, .data-table.stack-mobile tr, .data-table.stack-mobile td { display: block; width: auto; }
  .data-table.stack-mobile tr {
    border: 1px solid var(--border); border-radius: var(--radius);
    padding: .75rem .9rem; margin-bottom: .75rem; background: #fff;
  }
  .data-table.stack-mobile td { border: 0; padding: .3rem 0; display: flex; justify-content: space-between; gap: 1rem; text-align: left; }
  .data-table.stack-mobile td::before {
    content: attr(data-label); font-size: .78rem; font-weight: 700; letter-spacing: .03em;
    text-transform: uppercase; color: var(--brand-slate); flex: 0 0 auto;
  }
  .data-table.stack-mobile td.num { text-align: right; }
}

/* Mini bar chart (billing summary by month) */
.bar-chart { display: flex; align-items: flex-end; gap: .4rem; height: 120px; }
.bar-col { flex: 1; display: flex; flex-direction: column; align-items: center; gap: .35rem; height: 100%; }
.bar-track { flex: 1; width: 100%; display: flex; align-items: flex-end; background: var(--cream); border-radius: .35rem; overflow: hidden; }
.bar-fill { width: 100%; background: var(--brand-primary); min-height: 2px; border-radius: .35rem .35rem 0 0; transition: height .3s; }
.bar-label { font-size: .7rem; color: var(--brand-slate); }

/* Weekly schedule grid (recurring request edit) */
.day-grid { display: flex; flex-direction: column; gap: .4rem; }
.day-row { display: grid; grid-template-columns: 7rem 1fr 1fr; gap: .75rem; align-items: center; }
.day-row.head { color: var(--brand-slate); font-size: .8rem; text-transform: uppercase; letter-spacing: .04em; }
.day-row span:first-child { font-weight: 600; }

.check-rows { display: flex; flex-direction: column; gap: .25rem; }
.check-row { display: flex; align-items: flex-start; gap: .75rem; padding: .85rem; border-radius: var(--radius); cursor: pointer; }
.check-row:hover { background: var(--cream); }
.check-row input { margin-top: .25rem; accent-color: var(--brand-primary); width: 1.1rem; height: 1.1rem; }
.check-row span { display: flex; flex-direction: column; }
.check-row small { color: var(--brand-slate); }

.chat-reply { display: flex; gap: .75rem; align-items: flex-end; margin-top: 1rem; }
.chat-reply textarea { flex: 1; resize: vertical; min-height: 2.75rem; padding: .65rem .85rem; border: 1px solid var(--brand-line); border-radius: .75rem; font: inherit; }
.chat-reply .btn { white-space: nowrap; }

/* Owner dashboard monthly-sales chart.
   .chart-track is what makes this work: a bar sized in % needs an ancestor with a DEFINITE height,
   and the column cannot supply one because the row is align-items:flex-end (columns size to content,
   not to the row). Giving the bar its own fixed-height track resolves the percentage against 120px.
   Without it every month drew at the same 3px minimum while declaring 41%, 64%, 92%... */
.chart-months { display: flex; align-items: flex-end; gap: .4rem; margin-top: 1.25rem;
  border-bottom: 1px solid var(--border); padding-bottom: .25rem; }
.chart-col { flex: 1; display: flex; flex-direction: column; align-items: center; gap: .25rem; min-width: 0; }
.chart-track { width: 100%; height: 120px; display: flex; align-items: flex-end; }
.chart-fill { width: 100%; background: var(--brand-primary); border-radius: 3px 3px 0 0; }
.chart-label { font-size: .65rem; }

/* Create-job sitter name lookup. Positioned over the form so the list does not push fields around
   as it grows and shrinks with each keystroke. */
[data-sitter-picker] { position: relative; }
.sitter-results { position: absolute; top: 100%; left: 0; right: 0; z-index: 40; margin-top: .25rem;
  background: #fff; border: 1px solid var(--border); border-radius: .8rem; box-shadow: var(--shadow-md);
  max-height: 15rem; overflow-y: auto; }
.sitter-option { display: flex; justify-content: space-between; align-items: center; gap: .75rem;
  width: 100%; text-align: left; background: none; border: 0; padding: .6rem .85rem; font: inherit;
  color: var(--brand-ink); cursor: pointer; }
.sitter-option:hover, .sitter-option.active { background: var(--cream); color: var(--brand-primary); }
/* The status is shown rather than the row hidden: only 34 of 1,749 contractors are Active, so an
   Active-only list returns nothing for most searches and reads as broken. NoHire is excluded server-side. */
.sitter-status { font-size: .72rem; font-weight: 700; color: var(--brand-slate); background: var(--cream);
  border-radius: 999px; padding: .05rem .5rem; flex: 0 0 auto; }
.sitter-empty { padding: .6rem .85rem; color: var(--brand-slate); font-size: .9rem; }

/* Sitter calendar: a job awaiting acceptance is not the same as a confirmed one, and the legacy
   colours them differently for that reason. Amber rather than the brand red so it reads as
   'needs you' rather than 'error', and it is a link because accepting should be one click away. */
.cal-pill.pending { background: #fff4e0; border: 1px solid #f0c069; color: #8a5a00; font-weight: 700;
  text-decoration: none; display: block; }
.cal-pill.pending:hover { background: #ffe9c4; color: #6d4700; }
.dot.pending { background: #f0c069; }
.dot.visiting { background: #7c68d6; }
.dot.closeout { background: #d9822b; }
/* Finished but not closed out — the legacy legend's "Need To Complete". Warmer than the scheduled
   colour so an actionable job does not read as one still to come. */
.cal-pill.closeout { background: #fdf0e2; border: 1px solid #e8b478; color: #8a4b00; font-weight: 700; }
.cal-pill.closeout:hover { background: #fbe4cd; }

/* Sitter location tab strip — the legacy's sitters/index.asp tab row. Scrolls sideways rather than
   wrapping, so five locations stay one predictable row on a phone. */
.loc-tabs { display: flex; gap: .35rem; overflow-x: auto; padding-bottom: .3rem; margin-bottom: .35rem;
    -webkit-overflow-scrolling: touch; scrollbar-width: thin; }
.loc-tab-form { margin: 0; flex: 0 0 auto; }
.loc-tab { flex: 0 0 auto; display: inline-flex; align-items: center; gap: .35rem; white-space: nowrap;
    font: inherit; font-size: .82rem; font-weight: 600; line-height: 1; cursor: pointer;
    padding: .45rem .7rem; border-radius: 999px; border: 1px solid var(--border);
    background: #fff; color: var(--text); }
.loc-tab:hover { border-color: var(--brand-primary); color: var(--brand-primary); }
.loc-tab.current { background: var(--brand-primary); border-color: var(--brand-primary); color: #fff;
    cursor: default; }
.loc-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 1.15rem;
    height: 1.15rem; padding: 0 .3rem; border-radius: 999px; font-size: .68rem; font-weight: 700;
    background: var(--brand-primary); color: #fff; }
/* Muted on the location already being worked as, matching the legacy's greyed bell there. */
.loc-badge.muted { background: rgba(255,255,255,.28); color: #fff; }

/* Sitter FAQ — collapsed by default so a long list stays scannable. */
.faq-item { border-bottom: 1px solid var(--border); }
.faq-item:last-child { border-bottom: 0; }
.faq-item > summary { cursor: pointer; list-style: none; padding: .85rem 0; font-weight: 600;
    display: flex; justify-content: space-between; align-items: center; gap: 1rem; }
.faq-item > summary::-webkit-details-marker { display: none; }
.faq-item > summary::after { content: "+"; color: var(--muted); font-weight: 400; font-size: 1.15rem; }
.faq-item[open] > summary::after { content: "\2212"; }
.faq-answer { padding: 0 0 1rem; }

/* ---------------------------------------------------------------------------
   Print
   ---------------------------------------------------------------------------
   Replaces the legacy's separate printable routes (Members/jobdetailsprintable.asp,
   which is the same job-detail include rendered without the surrounding chrome and
   with PRINTABLE=TRUE). A print stylesheet does the same job for every page at once
   instead of maintaining a second copy of each one that can drift from the original.

   Anything the reader cannot act on when it is on paper comes off: navigation,
   buttons, forms, and the details/summary collapse behaviour, which would otherwise
   print an FAQ or timeline as a list of headings with the answers hidden.
   -------------------------------------------------------------------------- */
@media print {
    .site-header,
    .site-footer,
    .preview-bar,   /* the pre-launch banner would head every printed page, the FSA statement included */
    .cat-chip,      /* filter and year chips are screen controls */
    .portal-nav,
    .funnel-back,
    .btn,
    .btn-link,
    .linklike,
    .entity-actions,
    .form-actions { display: none !important; }

    /* Deliberately NOT hiding <form> wholesale. The request pages ARE a form, so a blanket rule
       printed them as a blank sheet. Hiding the action controls above is enough — the logout form
       is inside .portal-nav and already goes with it. */

    /* The portal is a sidebar grid; without the sidebar it should be a plain column. */
    .portal-grid { display: block !important; }
    .portal { padding: 0 !important; }
    .container { max-width: none !important; padding: 0 !important; }

    /* Cards are screen affordances. On paper they become sections with a rule. */
    .card {
        border: 0 !important;
        border-top: 1px solid #999 !important;
        border-radius: 0 !important;
        box-shadow: none !important;
        padding: .6rem 0 !important;
        margin: 0 !important;
        break-inside: avoid;
    }

    /* A collapsed <details> prints as a heading with nothing under it. Force them open. */
    details { display: block !important; }
    details > summary { list-style: none; font-weight: 700; }
    details > summary::after { content: "" !important; }
    details > *:not(summary) { display: block !important; }

    /* Keep a row and its label together rather than splitting across a page break. */
    .info-row, .job-row, .faq-item { break-inside: avoid; }

    body { background: #fff !important; color: #000 !important; font-size: 11pt; }
    a { text-decoration: none !important; color: #000 !important; }

    /* Spell out link targets, which are invisible on paper -- but only for real
       destinations, not in-page anchors or javascript: handlers. */
    .article-body a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; }

    /* Print-only header so a loose page still identifies itself. */
    .print-only { display: block !important; }
}

.print-only { display: none; }

/* Owner preview bar (Todd's GO 2026-09-22): above the header on every page of a previewing
   persona's session. Deliberately not sticky -- it is an explanation and a way back, not a
   control anyone needs mid-scroll, and a second sticky strip would eat a phone's viewport. */
.preview-bar {
    background: var(--brand-ink, #21303c);
    color: #fff;
    font-size: .9rem;
}
.preview-bar-inner {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem 1.25rem;
    align-items: baseline;
    justify-content: space-between;
    padding-top: .6rem;
    padding-bottom: .6rem;
}
.preview-bar-text { max-width: 60ch; }
.preview-bar-links { display: flex; gap: 1.25rem; flex-wrap: wrap; }
.preview-bar a { color: #fff; text-decoration: underline; white-space: nowrap; }
.preview-bar a:hover { text-decoration: none; }


/* ---- 375px sweep, 2026-09-22 ------------------------------------------------------------------
   Every portal route (163 across five personas) was loaded at 375px and measured for horizontal
   document overflow, after Julia's note that 99% of sitters and members are on their phones. These
   are the remaining causes; each is a element that cannot shrink rather than a layout choice.      */
@media (max-width: 560px) {
  /* A $360.00 at 2.6rem is ~170px, so two stat tiles plus the gap exceed the viewport. */
  .stat .num { font-size: 2rem; }
  /* And the value is not always a number: the home page's fourth stat is the word "Nationwide", which
     needs 175px of glyphs in a 144px column even at 2rem and spilled 7px onto the page. One per row
     below 420px -- a word reads better with the width anyway, and it holds for any future value. */
  @media (max-width: 420px) { .stats { grid-template-columns: minmax(0, 1fr); gap: 1.5rem; } }
  /* 27 pages set `display:flex` inline on .portal-head to push actions to the right, and none of them
     set flex-wrap -- so a heading plus two or three buttons ran off a 375px screen. Wrapping here
     covers all of them; the inline rule only sets display, so this is not fighting it. */
  .portal-head { flex-wrap: wrap; }
  .portal-head > div { min-width: 0; }
  /* Inputs carry an intrinsic size (type=file and type=date especially) that ignores the column. */
  input, select, textarea, .field input, .field select, .field textarea { max-width: 100%; min-width: 0; }
  input[type="file"] { width: 100%; }
  /* A form row of controls wraps instead of running off the screen. */
  .form-actions { flex-wrap: wrap; }
}

/* A data table is the one thing that legitimately needs its own width. Give it a scroller of its own
   rather than letting it widen the page -- the page scrolling sideways loses the nav and the heading,
   the table scrolling sideways does not. */
@media (max-width: 859px) {
  .table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }
}

/* ── Owner e-learning (ported from classic OwnerForum/elearning; Pages/Franchisee/Learning*) ── */
.elearning-courses { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr)); gap: 1.25rem; }
.elearning-note { background: #fff8e1; border: 1px solid #ffe2a8; color: #6b5300; border-radius: .8rem; padding: .9rem 1.1rem; font-size: .92rem; margin: .75rem 0; }
.elearning-note h4 { margin: 0 0 .35rem; font-size: .95rem; }
/* 16:9 and never wider than its card: classic's embeds were fixed 450-640px wide, which overflows a phone. */
.elearning-video { position: relative; width: 100%; aspect-ratio: 16 / 9; margin: .5rem 0; }
.elearning-video iframe, .elearning-content iframe { width: 100%; height: 100%; border: 0; border-radius: .5rem; }
.elearning-content iframe { aspect-ratio: 16 / 9; height: auto; }
.elearning-content img { max-width: 100%; height: auto; border-radius: .4rem; }
.elearning-content table { width: 100%; border-collapse: collapse; margin: .75rem 0; display: block; overflow-x: auto; }
.elearning-content td, .elearning-content th { border: 1px solid var(--border); padding: .4rem .5rem; vertical-align: top; }
.elearning-content h3, .elearning-content h4 { margin: 1.25rem 0 .5rem; }
.elearning-content { overflow-wrap: anywhere; line-height: 1.6; }
.elearning-lessons { margin: .25rem 0 .5rem; padding-left: 1.25rem; }
.elearning-lessons li { margin: .3rem 0; }
.elearning-video-item { border-bottom: 1px solid var(--border); padding: .5rem 0; }
.elearning-video-item summary { cursor: pointer; font-weight: 600; }

/* Show/hide password (site.js). The wrapper takes the input's place; the eye sits inside its right edge, a 44px tap target. */
.pw-wrap { position: relative; display: block; width: 100%; }
.pw-wrap > input { width: 100%; padding-right: 3rem; box-sizing: border-box; }
.pw-toggle {
  position: absolute; top: 50%; right: .25rem; transform: translateY(-50%);
  width: 2.75rem; height: 2.75rem; display: inline-flex; align-items: center; justify-content: center;
  background: none; border: 0; padding: 0; margin: 0; cursor: pointer; color: var(--brand-slate); border-radius: .6rem;
}
.pw-toggle:hover { color: var(--brand-primary); }
.pw-toggle:focus-visible { outline: 2px solid var(--brand-primary); outline-offset: -2px; }
.chart-key { display: inline-block; width: .7rem; height: .7rem; border-radius: 2px; vertical-align: -1px; margin-right: .2rem; }

/* The owner page's filtering card (Owner.cshtml): outlined while it filters the locations table, so the state is visible. */
.loc-metric-active { outline: 2px solid var(--brand-primary); outline-offset: -2px; }

/* --------------------------------------------------------------------------
   Office member record: the action bar (Jennifer 09-30; Todd ~21:2x, phase 2).
   Four large targets for what an office does from a family's record, two by two on a
   phone; every other destination in one quiet row of links underneath.
   -------------------------------------------------------------------------- */
.member-actions { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .5rem; margin-top: .9rem; align-items: start; }
@media (max-width: 640px) { .member-actions { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.member-action { position: relative; display: flex; flex-direction: column; gap: .15rem; padding: .7rem .8rem; border: 1px solid var(--brand-border);
    border-radius: 12px; background: #fff; color: var(--brand-ink); text-decoration: none; min-height: 3.6rem; }
a.member-action:hover, details.member-action > summary:hover { color: var(--brand-primary); border-color: var(--brand-primary); }
details.member-action { padding: 0; }
details.member-action > summary { list-style: none; cursor: pointer; display: flex; flex-direction: column; gap: .15rem; padding: .7rem .8rem; border-radius: 12px; }
details.member-action > summary::-webkit-details-marker { display: none; }
.member-action-label { font-weight: 700; }
.member-action .field-hint { margin: 0; font-size: .8rem; }
.member-action-menu { display: grid; gap: .1rem; padding: 0 .8rem .7rem; }
.member-action-menu a { padding: .35rem 0; border-top: 1px solid var(--border); }
.member-more { display: flex; flex-wrap: wrap; gap: .25rem 1rem; margin-top: .75rem; font-size: .92rem; }

/* Office member record sections (phase 2b): jump links under the money chips, and a heading per group of cards. */
.member-sections { display: flex; flex-wrap: wrap; gap: .4rem; margin: 0 0 1.25rem; }
.member-sections a { padding: .45rem .9rem; border: 1px solid var(--brand-border); border-radius: 999px; background: #fff; color: var(--brand-ink); font-weight: 600; font-size: .9rem; text-decoration: none; }
.member-sections a:hover { color: var(--brand-primary); border-color: var(--brand-primary); }
.member-section { scroll-margin-top: 6rem; }   /* clears the sticky site header */
.member-section-title { font-size: 1.15rem; margin: 1.5rem 0 .75rem; padding-bottom: .35rem; border-bottom: 2px solid var(--brand-border); }
@media print { .member-sections { display: none !important; } }
