/* =========================================================================
   KALOCKSCO — Handyman · Electrical · Remodeling
   styles.css  ·  Single source of truth for design tokens
   Rebrand the whole site by editing the :root variables below.
   ========================================================================= */

/* -------------------------------------------------------------------------
   1. DESIGN TOKENS
   ------------------------------------------------------------------------- */
:root {
  /* Brand palette ------------------------------------------------------- */
  /* --- Santa Monica palette, re-skinned: TEAL primary ----------------- */
  --sm-teal-1:        #0E7A80;   /* primary surface / headings            */
  --sm-teal-2:        #0B6065;   /* deeper teal — hero / CTA bands         */
  --sm-teal-3:        #084A4E;   /* deepest teal — footer                  */
  --sm-teal-br:       #2BC2C9;   /* bright teal — light tints              */
  --sm-orange:        #FB4D1A;   /* sun — accent + borders                 */
  --sm-orange-dark:   #DD3D0E;   /* orange hover / dark accent             */
  --sm-gold:          #F9B23A;   /* beach — YELLOW: buttons & highlights   */
  --sm-gold-dark:     #DD971C;   /* yellow hover                           */
  --sm-charcoal:      #333333;   /* logo wordmark — body text              */
  --klein:            #002FA7;   /* International Klein Blue — accent       */
  --klein-deep:       #001F7A;   /* darker IKB for gradients               */

  /* --- Semantic roles (every component references THESE) --------------- */
  --color-navy:        var(--sm-teal-1);      /* primary surface / heading */
  --color-navy-deep:   var(--sm-teal-2);      /* darker surface            */
  --color-navy-darker: var(--sm-teal-3);      /* deepest surface (footer)  */
  --color-amber:       var(--sm-orange);      /* accent + borders          */
  --color-amber-dark:  var(--sm-orange-dark); /* accent hover              */
  --color-teal:        var(--sm-teal-br);
  --color-teal-dark:   var(--sm-teal-1);
  --color-gold:        var(--sm-gold);        /* yellow: buttons/highlights*/
  --color-gold-dark:   var(--sm-gold-dark);
  --color-ink:         var(--sm-charcoal);    /* primary body text         */
  --color-muted:       #5B6573;   /* secondary text                        */
  --color-line:        #E3E7ED;   /* hairline borders                      */
  --color-surface:     #FFFFFF;   /* cards / panels                        */
  --color-bg:          #F1FAFB;   /* page background sections (teal tint)   */
  --color-bg-alt:      #E1F4F5;   /* alternating section background         */
  --color-success:     var(--sm-teal-1);      /* checkmarks / verified     */
  --color-star:        var(--sm-gold);        /* review stars (yellow)     */
  /* neutral + semantic UI colors (NOT part of the 4-colour brand palette) */
  --color-white:       #FFFFFF;   /* solid white — text on dark, field bg  */
  --ok-bg:             #E7F6EE;   --ok-fg:     #1C7C45;   /* success msg   */
  --err-bg:            #FCEBEA;   --err-fg:    #B3261E;   /* error msg     */
  --danger:            #B53A2C;   --danger-bg: #FCEAE8;   /* remove button */
  --tint-line:         #D4DAE3;   /* card hover border                     */
  --tint-cool:         #DDE6F2;   /* admin toggle hover                    */

  /* Typography ---------------------------------------------------------- */
  --font-head: "Poppins", "Segoe UI", Arial, sans-serif;
  --font-body: "Inter", "Segoe UI", Arial, sans-serif;

  /* --fs-hero cut 30%; every other text token cut 15% (2026-07-02 density pass) */
  --fs-hero:    clamp(1.47rem, 1.8vw + 0.7rem, 2.28rem);
  --fs-h2:      clamp(1.45rem, 2.1vw + 0.85rem, 2.21rem);
  --fs-h3:      clamp(0.98rem, 0.85vw + 0.77rem, 1.19rem);
  --fs-lead:    clamp(0.89rem, 0.5vw + 0.81rem, 1.06rem);
  --fs-body:    0.85rem;
  --fs-small:   0.74rem;

  /* Hero background image — the ONE place it's defined. index.php overrides
     this variable inline when the owner uploads a custom hero (PRO →
     Homepage Content Editor); every .hero rule below references it. */
  --hero-img: url("../img/hero.jpg");

  /* Spacing & layout ---------------------------------------------------- */
  --space-section: clamp(3.5rem, 7vw, 6.5rem);
  --container:     1180px;
  --gutter:        clamp(1.1rem, 4vw, 2rem);
  --radius:        14px;
  --radius-sm:     9px;
  --radius-pill:   999px;

  /* Effects ------------------------------------------------------------- */
  /* drop shadows fall to the BOTTOM-RIGHT (owner rule: darker bottom-right) */
  --shadow-sm: 1px 1px 3px rgba(20, 32, 50, 0.08);
  --shadow-md: 4px 8px 26px rgba(20, 32, 50, 0.10);
  --shadow-lg: 8px 18px 50px rgba(20, 32, 50, 0.16);
  --ring:      0 0 0 3px color-mix(in srgb, var(--sm-orange) 35%, transparent);
  /* Heavy resting shadow for row-header panels + tiles site-wide (panels,
     panel-heads, portal tiles/bands, service/project cards) — deeper than
     --shadow-sm so these read as solid, raised surfaces even before hover. */
  --tile-shadow: 3px 6px 18px rgba(20, 32, 50, 0.16), 1px 2px 6px rgba(20, 32, 50, 0.10);
  /* Strong DEBOSSED (pressed-into-the-page) look for every button's hover/
     press — inset shadows only, no outer drop shadow, no lift. One recipe
     shared by every button-like element site-wide (.btn, .btn-mini,
     .panel-toggle) — see §"Deboss" below. */
  /* pressed look (owner rule 2026-07-13): the dark shading sits at BOTH the
     top-left AND the bottom-right, so the press reads as sunk-in all around */
  --btn-deboss:        inset 4px 4px 10px rgba(0,0,0,0.42), inset -4px -4px 10px rgba(0,0,0,0.42);
  --btn-deboss-active: inset 5px 5px 12px rgba(0,0,0,0.55), inset -5px -5px 12px rgba(0,0,0,0.55);

  /* Skin highlight trio for effects/glow — Beach Vibe = orange (flips per skin, §21) */
  --fx:        #FB4D1A;   /* main highlight                       */
  --fx-soft:   #FF8A5B;   /* lighter — glow text on dark surfaces */
  --fx-bright: #FFB48F;   /* brightest — hover                    */
  --fx-ink:    #3A1505;   /* dark text that sits on the highlight */

  --nav-h: 72px;
  --transition: 0.22s ease;

  /* CONTROL SCALE — the ONE place button/pill sizing lives (owner rule
     2026-07-13 after repeated same-size complaints). Every control (.btn,
     .nav-phone, .phone-pill, .gal-btn, …) references THESE tokens — never
     its own font-size/padding/height — so two controls can not drift apart.
     Owner decision 2026-07-13: ONE size across the ENTIRE site (public +
     admin + portal), no exceptions; titles always outrank buttons. */
  --control-h: 34px;         /* fixed height of every pill / round control */
  --control-pad-x: 1.1rem;   /* horizontal padding inside pills            */
  --control-fs: var(--fs-small);
}

/* -------------------------------------------------------------------------
   2. RESET & BASE
   ------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
/* The HTML hidden attribute must ALWAYS win — without this, any element whose
   class sets its own display (e.g. .form-actions { display:flex }, .btn
   { display:inline-flex }) silently overrides the browser's [hidden] rule and
   stays visible even though scripts set .hidden = true (the Projects bulk-bar
   "still says selected after unchecking" bug). */
[hidden] { display: none !important; }

/* scrollbar-gutter: stable reserves the scrollbar's width on every page, so
   navigating between a short page (no scrollbar) and a long one (scrollbar)
   doesn't shift the layout width — kills the sticky-header "shake". */
/* scroll-padding-top keeps in-page anchor targets (#quoteSimple, #services,
   #quick-quote…) from landing UNDER the sticky header — they stop ~1 header
   height down instead. One place, so every anchor on the site is offset. */
html { scroll-behavior: smooth; scroll-padding-top: 6rem; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scrollbar-gutter: stable; overflow-x: clip; }

/* Backstop: the PAGE itself must never scroll sideways, no matter what a
   child (e.g. a wide table) does. Anything that genuinely needs its own
   horizontal scroll (like .table-scroll) still gets one — scoped to that
   element — this only stops it from also widening the whole page. */
body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.65;
  color: var(--color-ink);
  background: var(--color-surface);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
  max-width: 100vw;
  /* footer pin (2026-07-19): EVERY page is a full-height flex column, so on
     short pages the footer sits at the bottom of the window instead of
     floating mid-page — the ONE place this behavior lives (was previously
     only on .billing-page + the homepage, so lock-finder / FAQ / knowledge
     et al. floated). Fixed/absolute children (callbar, chat) are unaffected. */
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
body > main { flex: 1 0 auto; }
body > .site-footer { margin-top: auto; flex-shrink: 0; }

h1, h2, h3, h4 { font-family: var(--font-head); line-height: 1.15; font-weight: 700; color: var(--color-navy); }
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
ul { list-style: none; padding: 0; }
button { font-family: inherit; cursor: pointer; }

:focus-visible { outline: none; box-shadow: var(--ring); border-radius: 6px; }

/* -------------------------------------------------------------------------
   3. LAYOUT HELPERS
   ------------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: var(--space-section); }
.section--alt { background: var(--color-bg); }
.section--navy { background: var(--color-navy); color: var(--color-white); }
.section--navy h2, .section--navy h3 { color: var(--color-white); }

.section-head { max-width: 680px; margin-inline: auto; text-align: center; margin-bottom: clamp(2rem, 4vw, 3rem); }
/* Homepage section titles — dark orange (--color-heading), 5px larger than the
   h2 ladder step. Shared by .section-head and .why-copy so all read the same. */
.section-head h2, .why-copy h2 { font-size: calc(var(--fs-h2) + 5px); color: var(--color-heading); margin-top: 0.4rem; }
.section-head p { color: var(--color-ink); font-size: var(--fs-lead); margin-top: 0.8rem; }

/* THE eyebrow style. Every section eyebrow on every page uses THIS rule — no
   per-section variants, no inline colors, no !important overrides. Dark orange
   (readable on the sand background) with a warm-orange glow. The ONE exception
   is the dark-surface rule below (hero photo / navy bands), where dark orange
   would vanish, so it flips to the light antique-gold. */
.eyebrow {
  font-family: var(--font-head);
  font-weight: 800;                          /* heaviest loaded weight */
  font-size: var(--fs-small);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-heading);               /* dark orange — readable on sand */
  text-shadow: 0 1px 6px var(--fx-orange);   /* warm orange glow */
}
.hero .eyebrow, .cta-band .eyebrow, .section--navy .eyebrow {
  color: var(--fx); text-shadow: 0 1px 3px rgba(0,0,0,0.6);   /* light gold on dark surfaces */
}

/* -------------------------------------------------------------------------
   4. BUTTONS
   ------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  box-sizing: border-box;
  font-family: var(--font-head);
  font-weight: 600;
  /* size comes ONLY from the control-scale tokens (see :root) — a fixed
     height makes <a> and <button> pills pixel-identical by construction */
  font-size: var(--control-fs);
  height: var(--control-h);
  padding: 0 var(--control-pad-x);
  border-radius: var(--radius-pill);
  border: 2px solid transparent;
  transition: transform var(--transition), background var(--transition),
              box-shadow var(--transition), color var(--transition);
  white-space: nowrap;
}
.btn:hover { transform: translateY(1px); box-shadow: var(--btn-deboss); }
.btn:active { transform: translateY(2px); box-shadow: var(--btn-deboss-active); }

.btn--primary { background: var(--color-gold); color: var(--color-bg); border-color: var(--sm-orange); box-shadow: var(--shadow-sm); }
.btn--primary:hover { background: var(--color-gold-dark); border-color: var(--sm-orange-dark); }

.btn--ghost { background: transparent; color: var(--color-white); border-color: rgba(255,255,255,0.55); }
.btn--ghost:hover { background: rgba(255,255,255,0.12); border-color: var(--color-white); transform: translateY(-2px); }
.btn--ghost:active { transform: translateY(1px); background: rgba(255,255,255,0.18); }

.btn--dark { background: var(--color-navy); color: var(--color-white); }
.btn--dark:hover { background: var(--color-navy-deep); }

/* same height as every other control — "large" only means wider */
.btn--lg { padding: 0 2rem; }
.btn--block { width: 100%; }

.btn svg { width: 1.15em; height: 1.15em; }

/* (2026-07-13) the control scale is GLOBAL — defined once in :root above;
   no per-surface redefinition, so public and PRO buttons are identical. */
.billing-page .btn .material-symbols-outlined { font-size: 1.2em; }

/* -------------------------------------------------------------------------
   5. HEADER / NAV
   ------------------------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(255,255,255,0.92);
  -webkit-backdrop-filter: saturate(180%) blur(10px);
  backdrop-filter: saturate(180%) blur(10px);
  border-bottom: none;
  /* padding-bottom = stripe height (9px) + 5px gap below the pill button */
  padding: 14px 0 14px;
}
/* slim tricolor accent band along the header's bottom edge */
.site-header::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 9px;
  background: var(--accent-stripe);
}
.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 100%;
  /* positioning context for the open dropdown panels, so they anchor to THIS
     centered content column (i.e., under the hamburger) — not to the
     full-width header, which drifts away from the button on wide monitors */
  position: relative;
}
.brand { display: flex; align-items: center; gap: 0.32rem; font-family: var(--font-head); font-weight: 800; font-size: calc(var(--fs-h3) * 1.18); color: var(--color-navy); letter-spacing: -0.01em; transition: color var(--transition); }
.brand .brand-mark {
  display: grid; place-items: center;
  width: 38px; height: 38px;
  background: var(--color-navy); color: var(--color-gold);
  border-radius: 10px; font-size: var(--fs-h3); font-weight: 800;
  transition: transform var(--transition), box-shadow var(--transition);
}
/* "Pierre" + ".com" as one tight unit next to the CA badge → reads "Ka Locks Co" */
.brand .brand-word { white-space: nowrap; }
.brand .brand-amp { color: var(--color-gold); }
/* brand is a link home — same press + gold-ring hover language as every pill */
.brand:hover, .brand:focus-visible { color: var(--color-gold-dark); }
.brand:hover .brand-mark, .brand:focus-visible .brand-mark { transform: translateY(1px); }
.brand:focus-visible { outline: none; }

/* PUBLIC nav is ALWAYS collapsed to the hamburger (every window size) — the
   header shows only the brand + "Get a Free Quote"; all nav items + PRO live
   in the dropdown. (The admin .dash-nav still shows its row on desktop, §18.) */
.nav-links { display: none; }
.nav-links.is-open {
  display: flex;
  /* top = row bottom + the header's 14px bottom padding, so the panel sits
     flush under the header edge with NO hover gap (a gap would fire the
     header's mouseleave-close while travelling from the hamburger down) */
  position: absolute; top: calc(100% + 14px); left: 0; right: 0;
  flex-direction: column; align-items: flex-start; gap: 0;
  background: var(--color-white); border-bottom: 1px solid var(--color-line);
  box-shadow: var(--shadow-md); padding: 0.5rem var(--gutter) 1rem; z-index: 90;
}
.nav-links.is-open a { width: 100%; padding: 0.85rem 0.6rem; border-radius: var(--radius-sm); border-bottom: 1px solid var(--color-line); text-align: right; }
/* group separator (owner: nav "grouped & by priority") — each .nav-grp starts a
   new priority group: a small gap + a gold hairline above marks the break. */
.nav-links.is-open a.nav-grp { margin-top: 0.5rem; border-top: 1px solid color-mix(in srgb, var(--color-gold) 55%, transparent); }
/* Above phone size, the open menu is a compact panel whose RIGHT EDGE lines
   up with the hamburger (right: 0 of the centered .nav column), instead of a
   full-screen-wide sheet. */
@media (min-width: 640px) {
  .nav-links.is-open {
    left: auto; right: var(--gutter); width: 300px;
    border: 1px solid var(--color-line);
    border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  }
}

/* A couple of quick links kept in the bar on WIDER screens (Services, Gallery);
   hidden on narrow, where everything lives in the hamburger. */
.nav-quick { display: none; }
@media (min-width: 900px) {
  /* margin-right:auto glues the quick links to the brand on the LEFT and
     pushes the CTA cluster to the right (auto margins win over the .nav's
     space-between), instead of the links floating mid-header. */
  .nav-quick { display: flex; align-items: center; gap: 0.3rem; margin-right: auto; margin-left: 0.6rem; }
}

/* Shared nav-link style — same active/hover treatment on the public site nav
   (.nav-links), the wide-screen quick links (.nav-quick), and the admin
   dashboard nav (.dash-nav, §18) so every header looks/behaves the same. */
.nav-links a, .nav-quick a, .dash-nav a {
  font-family: var(--font-head); font-weight: 600; font-size: var(--fs-body);
  color: var(--color-navy); padding: 0.45rem 0.85rem; border-radius: var(--radius-pill);
  white-space: nowrap; transition: background var(--transition), color var(--transition),
  transform var(--transition), box-shadow var(--transition);
}
@media (hover: hover) {
  .nav-links a:hover, .nav-quick a:hover, .dash-nav a:hover { background: color-mix(in srgb, var(--color-gold) 12%, transparent); color: var(--color-gold-dark); transform: translateY(-1px); box-shadow: 0 6px 14px rgba(20,32,50,.10); }
}
.nav-links a:active, .nav-quick a:active, .dash-nav a:active { transform: translateY(1px); box-shadow: var(--btn-deboss-active); }
.nav-links a.is-active, .nav-quick a.is-active, .dash-nav a.is-active { background: var(--color-navy); color: var(--color-white); }
.nav-links a.is-active:hover, .nav-quick a.is-active:hover, .dash-nav a.is-active:hover { background: var(--color-navy-deep); }
/* unread-count bubble on the PRO "Inbox" nav item */
.nav-badge { display: inline-block; min-width: 1.15rem; height: 1.15rem; line-height: 1.15rem; padding: 0 0.3rem;
  border-radius: 999px; background: var(--danger); color: #fff; font-size: var(--fs-small); font-weight: 700; text-align: center; vertical-align: middle; }

/* today's date — EVERY page (owner order 2026-07-19): lives in the header's
   .nav-cta slot, left of the hamburger, same position site-wide (the spans
   sit in inc/header_public.php + inc/header_pro.php; js/main.js →
   initTodayDate fills them). Quiet, corporate; plain text, not a button. */
.nav-date {
  font-family: var(--font-head); font-weight: 700;
  font-size: var(--fs-small); color: var(--color-muted); letter-spacing: 0.01em;
  white-space: nowrap;
}

.nav-cta { display: flex; align-items: center; gap: 1rem; }
/* header phone — a tap-to-call PILL (icon + number). SAME size AND the SAME
   colour scheme as the primary "Get a Free Quote" button: filled gold pill,
   on-gold ink text, matching border. The two pills are visually identical
   (only the content differs). Hidden on phones (sticky call bar carries "Call"). */
.nav-phone {
  display: none; align-items: center; justify-content: center; gap: 0.5rem;
  box-sizing: border-box;
  /* size from the control-scale tokens ONLY — identical to .btn beside it */
  height: var(--control-h); padding: 0 var(--control-pad-x); border-radius: var(--radius-pill);
  background: var(--color-gold); border: 2px solid var(--sm-orange);
  font-family: var(--font-head); font-weight: 600; font-size: var(--control-fs);
  color: var(--color-navy); white-space: nowrap; box-shadow: var(--shadow-sm);
  transition: transform var(--transition), background var(--transition),
              box-shadow var(--transition), color var(--transition);
}
.nav-phone svg { width: 1.15em; height: 1.15em; flex: none; }
.nav-phone:hover { transform: translateY(-2px); background: var(--color-gold-dark); border-color: var(--sm-orange-dark); box-shadow: var(--shadow-md); }
.nav-phone:active { transform: translateY(0); }
@media (min-width: 640px) { .nav-phone { display: inline-flex; } }
/* Below 640px there's only room for one header pill — swap "Get a Free
   Quote" out for the phone pill so the number stays reachable/visible at
   the narrowest widths, instead of just disappearing. */
@media (max-width: 639px) {
  .nav-cta .btn--primary { display: none; }
  .nav-phone { display: inline-flex; }
}
@media (max-width: 600px) {
  .nav-cta { gap: 0.6rem; }
  .nav-cta .btn { padding: 0.55rem 0.9rem; font-size: var(--fs-body); }
}

/* social proof always in sight: "★ 4.6 (47)" chip → scrolls to reviews.
   Hidden on the smallest screens to keep the minimal bar. */
.nav-rating { display: none; align-items: center; gap: 0.3rem; font-family: var(--font-head); font-weight: 700; font-size: var(--fs-body); color: var(--color-navy); white-space: nowrap; }
.nav-rating .nr-star { color: var(--color-star); }
.nav-rating .nr-count { color: var(--color-muted); font-weight: 600; }
@media (min-width: 640px) { .nav-rating { display: inline-flex; } }

/* Owner entrance — discreet "PRO" bubble that lives INSIDE .nav-links (so it
   collapses into the hamburger with the other menu items on narrow screens) →
   dashboard (login-gated). Scoped to beat the shared .nav-links a pill style;
   uses brand tokens so it matches the active skin. */
.nav-links a.btn-pro {
  color: var(--color-gold); background: color-mix(in srgb, var(--color-gold) 12%, transparent);
  border: 1.5px solid color-mix(in srgb, var(--color-gold) 55%, transparent);
  font-weight: 800; font-size: var(--fs-small); letter-spacing: 0.06em; text-transform: uppercase;
  padding: 0.4rem 0.7rem;   /* border-radius (pill) inherited from .nav-links a */
}
.nav-links a.btn-pro:hover { background: var(--color-gold); color: var(--color-bg); box-shadow: var(--shadow-sm); }
/* In the open dropdown it drops the bubble and becomes a normal full-width row —
   same size as the other items so it's clearly legible, kept a distinct gold. */
.nav-links.is-open a.btn-pro {
  background: transparent; border: 0; border-bottom: 1px solid var(--color-line);
  font-size: var(--fs-body); letter-spacing: normal; color: var(--color-gold-dark);
}

.nav-toggle {
  display: none; background: none; border: none; padding: 0.4rem; color: var(--color-navy);
  border-radius: var(--radius-sm);
  transition: background var(--transition), color var(--transition), transform var(--transition);
}
.nav-toggle svg { width: 28px; height: 28px; }
/* hamburger → X morph, driven purely by the aria-expanded state main.js
   already toggles on click — no extra JS needed. */
.nav-toggle svg line { transition: transform .25s cubic-bezier(.22,1,.36,1), opacity .2s ease; transform-origin: 12px 12px; }
@media (hover: hover) {
  .nav-toggle:hover { background: color-mix(in srgb, var(--color-gold) 12%, transparent); color: var(--color-gold-dark); }
}
.nav-toggle:active { transform: scale(0.92); }
.nav-toggle[aria-expanded="true"] { background: color-mix(in srgb, var(--color-gold) 16%, transparent); color: var(--color-gold-dark); }
.nav-toggle[aria-expanded="true"] svg line:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] svg line:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] svg line:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
/* PUBLIC hamburger (#navToggle) is shown at ALL sizes; the admin one (#dashToggle)
   only appears ≤1000px (see §16) so the dashboard keeps its desktop row. */
#navToggle { display: inline-flex; }

/* -------------------------------------------------------------------------
   6. HERO
   ------------------------------------------------------------------------- */
.hero {
  position: relative;
  background:
    linear-gradient(135deg, color-mix(in srgb, var(--sm-teal-3) 94%, transparent), color-mix(in srgb, var(--sm-teal-2) 86%, transparent)),
    var(--hero-img) center/cover no-repeat;
  background-color: var(--color-navy-deep);
  color: var(--color-white);
  /* top padding kept tight so the hero content sits close to the header's
     accent stripe; bottom padding stays generous for the section below */
  padding-top: clamp(1.2rem, 3vw, 2rem);
  padding-bottom: clamp(3.5rem, 8vw, 7rem);
}
.hero-grid { display: grid; gap: 2.5rem; align-items: start; }
/* left column: capped at 410px (matches the grid track max) */
.hero-copy { max-width: 410px; }
/* Readability scrim (2026-07-04): ONLY the two loose-text zones over the
   photo get a translucent dark panel with rounded corners matching the
   boxes — the left copy block (eyebrow→stats, wrapped in .hero-scrim) and
   the Get in Touch block (.hero-box--clear, styled further below). The date
   pill, the View-Our-Work button, and the opaque boxes are deliberately NOT
   covered, so the photo stays sharp and clear all around them. */
.hero-scrim { border-radius: clamp(18px, 3vw, 28px); padding: 1rem 1.2rem 1.3rem; margin: 0.2rem 0 1.2rem; }
[data-theme] .hero-scrim {
  background:
    linear-gradient(135deg, rgba(255,255,255,0.06), transparent 45%),
    color-mix(in srgb, var(--color-navy-darker) 58%, transparent);
  -webkit-backdrop-filter: blur(6px) saturate(130%);
  backdrop-filter: blur(6px) saturate(130%);
  /* same gold border + glow as every other box */
  border: 2px solid color-mix(in srgb, var(--fx) 70%, transparent);
  box-shadow: var(--shadow-lg), 0 0 52px color-mix(in srgb, var(--fx) 20%, transparent);
}
/* headline (the alternate-highlight text) reduced 15% from the type-ladder token */
.hero h1 { color: var(--color-white); font-size: calc(var(--fs-hero) * 0.85); letter-spacing: -0.02em; line-height: 1.2; }
.hero h1 .accent { color: var(--color-amber); }
.hero .lead { font-size: var(--fs-lead); color: rgba(255,255,255,0.86); margin-top: 1.1rem; max-width: 36ch; }
/* Box 4 — editable highlight "pill": brown fill, big rounded ends, with a
   dateline, a gold divider, then the owner's text. Content: PRO → Homepage
   Content Editor. Tokens only — brown = --color-navy in the active skin. */
.hero-pill { color: var(--color-white);
  /* glassy, not solid: translucent brown over a blur of the hero photo,
     with a faint top-left sheen */
  background:
    linear-gradient(135deg, rgba(255,255,255,0.08), transparent 45%),
    color-mix(in srgb, var(--color-navy) 62%, transparent);
  -webkit-backdrop-filter: blur(7px) saturate(140%);
  backdrop-filter: blur(7px) saturate(140%);
  border-radius: clamp(18px, 3vw, 28px); padding: clamp(1rem, 2.2vw, 1.4rem) clamp(1.3rem, 3vw, 1.9rem);
  margin: 0 0 1.5rem;
  /* gold border + glow — the model every other hero box now matches */
  box-shadow: var(--shadow-lg), 0 0 52px color-mix(in srgb, var(--fx) 20%, transparent);
  border: 2px solid color-mix(in srgb, var(--fx, var(--color-gold)) 70%, transparent); }
/* email/other icon set before a box title (e.g. Simple Contact Request) */
.h3-ico { font-size: 1.05em; vertical-align: -0.16em; margin-left: 0.4rem; color: var(--color-bg); }
/* font-size comes from the shared ".hero-card h3, .hero-box h3, .hero-pill-date"
   rule below — one place, so the date always matches every box title */
.hero-pill-date { display: block; font-family: var(--font-head); font-weight: 700;
  letter-spacing: 0.02em; color: var(--color-white); opacity: 0.92; }
.hero-pill-rule { display: block; height: 2px; width: 100%; margin: 0.55rem 0 0.6rem;
  background: var(--color-gold); border-radius: 2px; }
.hero-pill-text { margin: 0; color: rgba(255,255,255,0.9); font-size: var(--fs-lead); line-height: 1.5; }
/* Quick-action row at the top of the hero (Quote · Call · Chat) — MOBILE ONLY
   (same ≤640px breakpoint as the bottom .callbar; desktop already has the
   header's phone + Get-a-Free-Quote pills, so it would be redundant there).
   Three equal buttons, sized by the shared control-scale tokens like every
   other control. Added 2026-07-16 — purely additive, nothing was removed. */
.hero-quick { display: none; gap: 0.5rem; margin-bottom: 0.9rem; }
.hero-quick .btn { flex: 1; min-width: 0; padding-inline: 0.5rem; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 1rem; margin-top: 1.8rem; justify-content: center; }
.hero-trust { display: flex; flex-wrap: wrap; gap: 1.4rem 2rem; margin-top: 2.2rem; padding-top: 1.6rem; border-top: 1px solid rgba(255,255,255,0.16); justify-content: center; text-align: center; }
.hero-trust .ht-item { display: flex; flex-direction: column; align-items: center; }
.hero-trust .ht-num { font-family: var(--font-head); font-weight: 800; font-size: var(--fs-h2); color: var(--color-gold); line-height: 1; }
.hero-trust .ht-label { font-size: var(--fs-small); color: rgba(255,255,255,0.78); margin-top: 0.3rem; }
/* referrers & partner logos strip (editable HTML embed; hidden when blank) */
.hero-partners { display: flex; flex-wrap: wrap; align-items: center; gap: 0.9rem 1.4rem;
  margin-top: 1.6rem; padding-top: 1.2rem; border-top: 1px solid rgba(255,255,255,0.16); }
.hero-partners img { max-height: 36px; width: auto; display: block; }
.hero-partners a { display: inline-flex; align-items: center; }

/* Hero quote card */
.hero-card {
  background: var(--color-surface);
  color: var(--color-ink);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: clamp(1.5rem, 3vw, 2.1rem);
}
/* one size rule: box titles AND the date pill's dateline stay identical */
.hero-card h3, .hero-box h3, .hero-pill-date { font-size: calc(var(--fs-h3) * 1.14); }
.hero-card p.sub, .hero-box p.sub { color: var(--color-muted); font-size: var(--fs-small); margin-top: 0.25rem; margin-bottom: 1.2rem; }

/* Six-box quote stack: each region of the old single card is its own box
   (1 start options · 2 live chat · 3 call now · 4 form · 5 bigger job ·
   6 testimonials), all always visible — no chooser show/hide. */
.hero-card-stack { display: flex; flex-direction: column; gap: 0.9rem; }
.hero-box { background: var(--color-surface); color: var(--color-ink);
  border-radius: var(--radius); box-shadow: var(--shadow-md); padding: 1.1rem 1.3rem; }
.hero-box .qc-option { display: block; width: 100%; margin-top: 0.7rem; }
.hero-box .qc-option:first-child { margin-top: 0; }
.hero-box .expert-cta { margin: 0; }
.hero-box .hero-reviews { margin-top: 0; border-top: 0; }
/* Get in Touch rows: wide text left, narrow icon pill right. */
.gt-row { display: flex; align-items: center; gap: 0.9rem; padding: 0.8rem 0;
  border-top: 1px solid var(--color-line); }
.gt-row:first-of-type { border-top: 0; padding-top: 0.2rem; }
.gt-row:last-of-type { padding-bottom: 0; }
.gt-text { flex: 1; min-width: 0; }
.gt-text strong { display: block; font-family: var(--font-head); font-weight: 700; color: var(--color-navy); }
.gt-text span { display: block; font-size: var(--fs-small); color: var(--color-muted); margin-top: 0.15rem; }
.gt-pill { flex: none; padding: 0.55rem 1.1rem; font-size: var(--fs-body); gap: 0.4rem; }
.gt-pill .material-symbols-outlined { font-size: 1.25em; line-height: 1; }

/* -------------------------------------------------------------------------
   7. FORMS
   ------------------------------------------------------------------------- */
.field { margin-bottom: 0.9rem; }
.field label { display: block; font-size: var(--fs-small); font-weight: 600; margin-bottom: 0.35rem; color: var(--color-navy); }
.field input, .field select, .field textarea {
  width: 100%;
  font-family: var(--font-body);
  font-size: var(--fs-lead);
  padding: 0.75rem 0.9rem;
  border: 1.5px solid var(--color-line);
  border-radius: var(--radius-sm);
  background: var(--color-white);
  color: var(--color-ink);
  transition: border-color var(--transition), box-shadow var(--transition);
}
.field input:focus, .field select:focus, .field textarea:focus {
  border-color: var(--color-amber);
  box-shadow: var(--ring);
  outline: none;
}
.field textarea { resize: vertical; min-height: 96px; }
.form-note { font-size: var(--fs-small); color: var(--color-muted); margin-top: 0.6rem; text-align: center; }
.form-status { display: none; margin-top: 0.8rem; padding: 0.7rem 1rem; border-radius: var(--radius-sm); font-size: var(--fs-small); }
.form-status.is-ok { display: block; background: var(--ok-bg); color: var(--ok-fg); }
.form-status.is-err { display: block; background: var(--err-bg); color: var(--err-fg); }

/* -------------------------------------------------------------------------
   8. TRUST BAR / BADGES
   ------------------------------------------------------------------------- */
.trustbar { background: var(--color-surface); border-bottom: 1px solid var(--color-line); }
.trustbar-inner { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 1rem 2.4rem; padding-block: 1.3rem; text-align: center; }
.trust-item { display: inline-flex; align-items: center; gap: 0.55rem; font-weight: 600; color: var(--color-navy); font-size: var(--fs-lead); }
.trust-item svg { width: 1.4em; height: 1.4em; color: var(--klein); flex: none; }
/* Google Material Symbols icon (editable business references) — same size/
   color slot the old inline SVGs used */
.trust-item .trust-ico { font-size: 1.4em; line-height: 1; color: var(--klein); flex: none; }

/* -------------------------------------------------------------------------
   9. SERVICES
   ------------------------------------------------------------------------- */
.cards { display: grid; gap: 1.4rem; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.card {
  background: var(--color-surface);
  border: 1.5px solid var(--color-line);
  border-radius: var(--radius);
  padding: 1.7rem;
  box-shadow: var(--tile-shadow);
  transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition);
}
.card:hover { transform: translateY(1px); box-shadow: var(--btn-deboss); border-color: var(--tint-line); }
.card:active { transform: translateY(2px); box-shadow: var(--btn-deboss-active); }
/* service cards double as links to their own dedicated page (index.php) —
   .card stays a plain container elsewhere (e.g. the admin preview), so this
   is a separate modifier rather than baking link resets into .card itself. */
.card--link { display: block; text-decoration: none; color: inherit; }
.card .icon {
  display: grid; place-items: center;
  width: 54px; height: 54px;
  border-radius: 12px;
  /* lighter gold top-left → darker orange bottom-right (owner shading rule) */
  background: linear-gradient(135deg, var(--sm-gold), var(--sm-orange));
  color: var(--color-white);
  margin-bottom: 1rem;
}
.card .icon svg { width: 28px; height: 28px; }
.card .icon .material-symbols-outlined { font-size: 28px; line-height: 1; }
.card h3 { font-size: var(--fs-h3); margin-bottom: 0.5rem; }
.card p { color: var(--color-muted); font-size: var(--fs-lead); }
.card ul { margin-top: 0.9rem; display: grid; gap: 0.4rem; }
.card ul li { position: relative; padding-left: 1.4rem; font-size: var(--fs-body); color: var(--color-ink); }
.card ul li::before {
  content: ""; position: absolute; left: 0; top: 0.55em;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--color-amber);
}

/* -------------------------------------------------------------------------
   10. WHY US
   ------------------------------------------------------------------------- */
.why-grid { display: grid; gap: 2.4rem; align-items: center; grid-template-columns: 1fr; }
.why-copy h2 { margin-top: 0.4rem; }   /* size + color: shared .section-head h2, .why-copy h2 rule */
.why-copy .why-intro { color: var(--color-ink); margin-top: 0.8rem; }
.why-list { display: grid; gap: 1.3rem; margin-top: 1.6rem; }
.why-item { display: flex; gap: 1rem; }
.why-item .why-ico {
  flex: none; display: grid; place-items: center;
  width: 46px; height: 46px; border-radius: 12px;
  background: color-mix(in srgb, var(--sm-teal-br) 16%, transparent); color: var(--color-teal-dark);
}
.why-item .why-ico svg { width: 24px; height: 24px; }
.why-item .why-ico .material-symbols-outlined { font-size: 24px; line-height: 1; }
.why-item h3 { font-size: var(--fs-h3); margin-bottom: 0.2rem; }
.why-item p { color: var(--color-muted); font-size: var(--fs-lead); }
/* SQUARE photo (spec: uploads must be exactly square, ≥525×525 px). The grid
   columns are equal, so the photo renders at the SAME width as the text
   column beside it — within the owner's "no more than 25px narrower" rule
   by construction. The editable legend overlays the bottom edge. */
.why-media { position: relative; aspect-ratio: 1 / 1; border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-md); min-height: 320px; background: var(--color-bg-alt) center/cover no-repeat; }
.why-legend {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 2.2rem 1.1rem 0.9rem;
  font-family: var(--font-head); font-weight: 600; font-size: var(--fs-lead);
  color: var(--color-white);
  background: linear-gradient(transparent, rgba(0,0,0,0.62));
}

/* -------------------------------------------------------------------------
   11. REVIEWS
   ------------------------------------------------------------------------- */
.reviews-grid { display: grid; gap: 1.4rem; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.review {
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius);
  padding: 1.6rem;
  box-shadow: var(--shadow-sm);
  display: flex; flex-direction: column;
}
.stars { display: inline-flex; gap: 2px; color: var(--color-star); margin-bottom: 0.7rem; }
.stars svg { width: 18px; height: 18px; }
.review p.quote { font-size: var(--fs-lead); color: var(--color-ink); flex: 1; }
.review .reviewer { display: flex; align-items: center; gap: 0.7rem; margin-top: 1.1rem; padding-top: 1.1rem; border-top: 1px solid var(--color-line); }
.review .avatar { width: 40px; height: 40px; border-radius: 50%; background: var(--color-navy); color: var(--color-amber); display: grid; place-items: center; font-family: var(--font-head); font-weight: 700; }
.review .who strong { display: block; font-size: var(--fs-lead); color: var(--color-navy); }
.review .who span { font-size: var(--fs-small); color: var(--color-muted); }

.rating-summary { display: flex; align-items: center; justify-content: center; gap: 0.8rem; margin-top: 1.2rem; flex-wrap: wrap; }
.rating-summary .big { font-family: var(--font-head); font-weight: 800; font-size: var(--fs-h2); color: var(--color-navy); }
.rating-summary .stars svg { width: 22px; height: 22px; }

/* -------------------------------------------------------------------------
   12. SERVICE AREA / CTA BAND
   ------------------------------------------------------------------------- */
.cta-band { background: linear-gradient(135deg, var(--klein), var(--klein-deep)); color: var(--color-white); text-align: center; }
.cta-band h2 { color: var(--color-white); font-size: var(--fs-h2); }
.cta-band p { color: rgba(255,255,255,0.85); font-size: var(--fs-lead); max-width: 56ch; margin: 0.9rem auto 1.8rem; }
.cta-actions { display: flex; flex-wrap: wrap; gap: 1rem; justify-content: center; }

.area-tags { display: flex; flex-wrap: wrap; gap: 0.6rem; justify-content: center; margin-top: 1.4rem; }
.area-tags span, .area-tags a { background: rgba(255,255,255,0.10); border: 1px solid rgba(255,255,255,0.18); padding: 0.4rem 0.95rem; border-radius: var(--radius-pill); font-size: var(--fs-small); }
.area-tags a { color: inherit; text-decoration: none; cursor: pointer; transition: background 0.15s; }
.area-tags a:hover, .area-tags a:focus-visible { background: rgba(255,255,255,0.2); }

/* -------------------------------------------------------------------------
   13. CONTACT
   ------------------------------------------------------------------------- */
/* "Contact Tiles" — text on the left, icon on the right, each on its own
   ivory card (reused as-is in chatwindow.html — keep both in sync). */
.contact-tiles { display: grid; grid-template-columns: 1fr; gap: 1rem; max-width: 640px; margin-inline: auto; }
.contact-tile {
  display: flex; align-items: center; justify-content: space-between; gap: 0.9rem;
  background: var(--color-surface);
  border: 1px solid color-mix(in srgb, var(--color-gold) 35%, var(--tint-line));
  border-radius: var(--radius);
  padding: 0.9rem 1.1rem;
  box-shadow: var(--shadow-sm);
  text-decoration: none; color: inherit;
  transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition);
}
/* the 4 actionable tiles are <a> elements — the whole card is clickable,
   including the icon; the 2 info-only tiles (.contact-tile--static) stay
   plain <div>s and skip the hover lift so they don't look clickable. */
a.contact-tile:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
  border-color: var(--color-gold);
}
a.contact-tile:hover h3 { color: var(--color-amber-dark); }
.contact-tile .ci-ico { flex: none; display: grid; place-items: center; width: 46px; height: 46px; border-radius: 12px; background: var(--color-navy); color: var(--color-amber); overflow: hidden; }
.contact-tile .ci-ico svg { width: 22px; height: 22px; }
.contact-tile .ci-ico .material-symbols-outlined { font-size: 22px; line-height: 1; }
.contact-tile h3 { font-size: var(--fs-h3); margin-bottom: 0.2rem; color: var(--color-ink); transition: color var(--transition); }
.contact-tile p { color: var(--color-muted); font-size: var(--fs-lead); }
.contact-form-wrap { background: var(--color-surface); border: 1px solid var(--color-line); border-radius: var(--radius); padding: clamp(1.5rem, 3vw, 2.2rem); box-shadow: var(--shadow-md); }

/* -------------------------------------------------------------------------
   14. FOOTER
   ------------------------------------------------------------------------- */
/* Footer: slim two-line accent — thin orange + thin Klein blue — above the teal body.
   Band orange is its own token so it can be tuned without touching site accents. */
:root {
  --band-orange: var(--sm-orange);
  /* slim tricolor accent — orange · yellow · Klein blue (reused by header + footer) */
  --accent-stripe: linear-gradient(to bottom,
    var(--band-orange) 0 3px,
    var(--sm-gold)     3px 6px,
    var(--klein)       6px 9px);
}
.site-footer {
  position: relative;
  background: var(--color-navy-darker);
  color: rgba(255,255,255,0.78);
  padding-block: 3rem 1.6rem;
}
.site-footer::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 9px;
  background: var(--accent-stripe);
}
.footer-grid { display: grid; gap: 2rem; grid-template-columns: 1fr; }
.site-footer .brand { color: var(--color-white); margin-bottom: 0.8rem; }
.site-footer h4 { color: var(--color-white); font-size: var(--fs-lead); margin-bottom: 0.9rem; }
.site-footer a { color: rgba(255,255,255,0.78); transition: color var(--transition); }
.site-footer a:hover { color: var(--color-amber); }
.footer-links { display: grid; gap: 0.5rem; }
.footer-contact li { display: flex; gap: 0.55rem; align-items: flex-start; margin-bottom: 0.5rem; font-size: var(--fs-lead); }
.footer-contact svg { width: 1.05em; height: 1.05em; color: var(--color-amber); flex: none; margin-top: 0.25rem; }
.footer-bottom { margin-top: 2.2rem; padding-top: 1.4rem; border-top: 1px solid rgba(255,255,255,0.12); display: flex; flex-wrap: wrap; gap: 0.6rem 1.4rem; justify-content: space-between; font-size: var(--fs-small); }
.footer-bottom .license { color: rgba(255,255,255,0.6); }

/* THE standard public footer (inc/footer_public.php) — mission line +
   locality disclosure + centered bottom row. One include on every public
   page; the copy lives in the Homepage Content Editor (footer_* fields).
   Promoted from the homepage's page-scoped styles 2026-07-19. */
.sf-full .sf-desc { max-width: 640px; margin: 0 auto; padding-top: 1.4rem; text-align: center;
  font-size: 0.76rem; line-height: 1.55; color: rgba(255,255,255,0.55);
  border-top: 1px solid rgba(255,255,255,0.08); }
.sf-full .sf-disclosure { max-width: 640px; margin: 0.5rem auto 1rem; text-align: center;
  font-size: 0.68rem; line-height: 1.5; color: rgba(255,255,255,0.35); }
/* the shared space-between row wraps into stray left-aligned lines under the
   centered paragraphs above — center it instead so it's tidy at any width */
.sf-full .footer-bottom { justify-content: center; text-align: center; gap: 0.35rem 1rem; }
.sf-full .sf-links { color: var(--color-muted); }
.sf-full .sf-links a { color: #8A6B34; font-weight: 600; text-decoration: none; }

/* -------------------------------------------------------------------------
   15. FLOATING MOBILE CALL BAR
   ------------------------------------------------------------------------- */
.callbar {
  display: none;
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 90;
  background: var(--color-navy); border-top: 1px solid rgba(255,255,255,0.12);
  padding: 0.6rem var(--gutter);
  gap: 0.7rem;
}
.callbar .btn { flex: 1; }

/* -------------------------------------------------------------------------
   16. RESPONSIVE
   ------------------------------------------------------------------------- */
@media (min-width: 768px) {
  .why-grid { grid-template-columns: 1fr 1fr; }
  .contact-tiles { grid-template-columns: 1fr 1fr; }
  .footer-grid { grid-template-columns: 1.6fr 1fr 1.4fr; }
}
/* Hero columns (owner rule 2026-07-04): LEFT is never under 250px, RIGHT is
   never under 270px. Two columns from the first width where both floors fit
   (~600px); phones below that stack. Tracks grow toward 400/520 and the pair
   stays centered. */
@media (min-width: 600px) {
  /* left +10px (400→410), right -10px (520→510) to even the two columns */
  .hero-grid { grid-template-columns: minmax(250px, 410px) minmax(270px, 510px);
    justify-content: center; gap: clamp(1.2rem, 3vw, 5rem); }
}
@media (max-width: 599px) {
  /* Single-column hero (phones): the left copy must FILL the column like every
     other stacked section. The 410px desktop cap (see .hero-copy above) is a
     line-length limit for the two-column layout only — left here it pins the
     column to the start of a wider container, leaving lopsided space on the
     right (off-centre). max-width:none lets it sit full-width & symmetric.
     (kalocksco's home hero is .hh-hero; kept here so the shared block stays
     parallel across the three sites.) */
  .hero-copy { max-width: none; }
}

/* Admin dashboard nav (.dash-nav) is ALWAYS behind its hamburger (#dashToggle) —
   owner preference 2026-07-19: never show the horizontal pill row, at any width.
   The PUBLIC nav (.nav-links / #navToggle) is likewise always collapsed (§5). */
#dashToggle { display: inline-flex; }

@media (max-width: 640px) {
  .callbar { display: flex; }
  .hero-quick { display: flex; }   /* top-of-hero Quote · Call · Chat row */
  /* room for the floating call bar — ONLY on pages that actually have one
     (otherwise it's a 70px empty band under the footer) */
  body:has(.callbar) { padding-bottom: 70px; }
  .hero-trust { gap: 1rem 1.5rem; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition: none !important; }
}

/* =========================================================================
   17. BILLING TOOL (billing.html, invoice.php)
   Reuses the tokens/components above; no new color values.
   ========================================================================= */
.billing-page { background: var(--color-bg); }
/* (footer pin moved to the base body rule, §2 — every page has it now) */
.bill-wrap { padding-block: 1.6rem 3rem; }
.bill-head h1 { font-size: var(--fs-hero); }
.bill-head .muted { color: var(--color-muted); margin-top: 0.25rem; }

/* nav-back bakes in the "display:inline-block;margin-bottom:…" every admin
   page used to hand-carry as an inline style (29 files' worth) — matches
   capierre.com's rule so the two sites' back-links sit identically. */
.nav-back { font-family: var(--font-head); font-weight: 600; color: var(--color-navy); margin-right: 0.4rem; display: inline-block; margin-bottom: 0.4rem; }
.nav-back:hover { color: var(--color-amber-dark); }

/* Extra button variant: outlined on light */
.btn--ghost-dark { background: transparent; color: var(--color-navy); border-color: var(--sm-orange); }
.btn--ghost-dark:hover { background: color-mix(in srgb, var(--color-gold) 10%, transparent); border-color: var(--color-navy); }
.btn--ghost-dark:active { transform: translateY(1px); box-shadow: none; }
.btn[disabled] { opacity: 0.6; cursor: default; transform: none; }

/* Panels */
.panel {
  background: var(--color-surface);
  border: 1.5px solid var(--color-line);
  border-radius: var(--radius);
  box-shadow: var(--tile-shadow);
  margin-bottom: 1.1rem;
  overflow: hidden;
}
.panel-head {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 1rem 1.3rem;
  border-bottom: 2px solid var(--color-line);
}
.panel-head h2 { font-size: var(--fs-h3); }
.panel-body { padding: 1.3rem; }
.panel.is-collapsed .panel-body { display: none; }
.catalog-box.is-collapsed { display: none; }
.panel-toggle {
  background: var(--color-bg-alt); border: 1px solid var(--color-line);
  color: var(--color-navy); font-family: var(--font-head); font-weight: 600;
  font-size: var(--fs-small); padding: 0.4rem 0.9rem; border-radius: var(--radius-pill);
  transition: transform var(--transition), box-shadow var(--transition), background var(--transition);
}
.panel-toggle:hover { background: var(--tint-cool); transform: translateY(1px); box-shadow: var(--btn-deboss); }
.panel-toggle:active { transform: translateY(2px); box-shadow: var(--btn-deboss-active); }

.panel .sub { font-size: var(--fs-lead); margin: 1.2rem 0 0.6rem; color: var(--color-navy); }
.panel .sub:first-child { margin-top: 0; }
.hint { font-size: var(--fs-small); color: var(--color-muted); margin-bottom: 0.8rem; }
.hint-inline { font-weight: 400; color: var(--color-muted); font-size: var(--fs-small); }
.inline-status { font-size: var(--fs-small); margin-left: 0.7rem; color: var(--color-teal-dark); }

/* Read-only key/value detail grid — ONE shared definition used by the lead
   detail page, the leads-list expandable row, and the client contact view, so
   all three read the same. Label small/uppercase/muted, value at body weight. */
.lead-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 0.5rem 1.4rem; }
.lead-grid .lg-k { color: var(--color-muted); font-size: var(--fs-small); text-transform: uppercase; letter-spacing: 0.03em; }
.lead-grid .lg-v { color: var(--color-ink); font-weight: 600; margin-top: 0.1rem; }
.lead-msg { margin: 0.4rem 0; padding: 0.8rem 1rem; background: var(--color-bg-alt); border-radius: 8px; font-size: var(--fs-lead); white-space: pre-wrap; }

/* Homepage Content Editor tab strip (inc/homepage_editor_tabs.php) — ONE shared
   definition so every editor page (Hero / Services / Why Us / Areas / Contact)
   renders the same pills. Was duplicated in each page's <style> and missing on
   the Why Us page entirely, so its nav rendered as plain text. */
.hce-tabs { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 1rem; }
.hce-tab { font-size: var(--fs-body); font-weight: 600; color: var(--color-navy); background: var(--color-bg-alt);
  padding: 0.4rem 0.9rem; border-radius: var(--radius-pill); }
/* text-on-gold: same pairing as .btn--primary/.nav-phone — var(--color-bg), never
   var(--color-navy), since the oil-rubbed-bronze gold and navy tokens are both
   dark browns and go near-invisible together */
.hce-tab.is-active { background: var(--color-gold); color: var(--color-bg); }

/* Field grids */
.grid-2 { display: grid; gap: 0.4rem 1rem; grid-template-columns: 1fr; }
.grid-4 { display: grid; gap: 0.4rem 1rem; grid-template-columns: 1fr 1fr; }
@media (min-width: 620px) {
  .grid-2 { grid-template-columns: 1fr 1fr; }
  .grid-4 { grid-template-columns: 1fr 1fr 1fr 1fr; }
}

/* Line-item rows (labour + materials) */
.li-row {
  display: grid; gap: 0.5rem; align-items: center; margin-bottom: 0.55rem;
}
.li-row--labour { grid-template-columns: 1.6fr 0.9fr 0.6fr 0.7fr 0.8fr auto; }
.li-row--mat    { grid-template-columns: 1fr 1.4fr 0.6fr 0.8fr 0.8fr auto; }
.li-row > * { min-width: 0; }   /* let grid columns shrink instead of overflowing the panel */
.li-row input, .li-row select { padding: 0.6rem 0.6rem; width: 100%; box-sizing: border-box; }
.li-head {
  font-family: var(--font-head); font-weight: 600; font-size: var(--fs-small);
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--color-muted);
  margin-bottom: 0.5rem;
}
.li-amt { font-family: var(--font-mono, monospace); font-weight: 600; text-align: right; color: var(--color-navy); }
.row-rm {
  background: transparent; border: none; color: var(--danger); font-size: var(--fs-lead);
  width: 32px; height: 32px; border-radius: 8px;
}
.row-rm:hover { background: var(--danger-bg); }
.btn-add { margin-top: 0.3rem; font-size: var(--fs-body); padding: 0.6rem 1.1rem; }
.task-row { display: grid; grid-template-columns: 1fr auto; gap: 0.5rem; margin-bottom: 0.5rem; }

/* Catalog */
.catalog-box { background: var(--color-bg); border: 1px dashed var(--color-line); border-radius: var(--radius-sm); padding: 1.1rem; margin-bottom: 1.3rem; }
.catalog-list { margin-top: 1rem; display: grid; gap: 0.8rem; }
.cat-group { }
.cat-name { font-family: var(--font-head); font-weight: 700; color: var(--color-navy); font-size: var(--fs-body); margin-bottom: 0.35rem; }
.cat-item {
  display: flex; justify-content: space-between; gap: 1rem; width: 100%; text-align: left;
  background: var(--color-surface); border: 1px solid var(--color-line); border-radius: 8px;
  padding: 0.5rem 0.8rem; font-size: var(--fs-body); color: var(--color-ink); margin-bottom: 0.3rem;
}
.cat-item:hover { border-color: var(--color-amber); background: color-mix(in srgb, var(--sm-orange) 6%, var(--color-white)); }
.cat-item em { color: var(--color-muted); font-style: normal; font-size: var(--fs-small); }

/* Totals — default styling suits a normal (light) panel, like every other
   block on the page (admin/project.php's Project Total). */
.tot-row { display: flex; justify-content: space-between; padding: 0.4rem 0; font-size: var(--fs-lead); }
.tot-row span:first-child { color: var(--color-muted); }
.tot-grand { border-top: 2px solid var(--color-line); margin-top: 0.4rem; padding-top: 0.8rem; font-family: var(--font-head); font-weight: 800; font-size: calc(var(--fs-h3) * 1.18); }
.tot-grand span:last-child { color: var(--color-gold); }

/* Dark (navy) totals variant — admin/quick-invoice.php still uses this look */
.panel--totals { background: var(--color-navy); border: none; }
.panel--totals .totals { color: var(--color-white); }
.panel--totals .tot-row span:first-child { color: rgba(255,255,255,0.82); }
.panel--totals .tot-grand { border-top-color: rgba(255,255,255,0.2); }
.panel--totals .panel-head { color: var(--color-white); border-bottom-color: rgba(255,255,255,0.15); }
.panel--totals.panel--fold > .panel-head:hover { background: rgba(255,255,255,0.08); }
.panel--totals.panel--fold > .panel-head::after { color: var(--color-white); }

/* Actions + result */
.action-bar { position: sticky; bottom: 0; z-index: 20; padding: 0.9rem 0; background: linear-gradient(to top, var(--color-bg) 70%, transparent); }
.action-bar .btn { width: 100%; }
.result-box { border: 2px solid var(--color-teal); }
.result-title { font-size: var(--fs-h3); color: var(--color-navy); }
.result-email { font-size: var(--fs-small); color: var(--color-muted); margin: 0.4rem 0 1rem; }
.result-actions { display: flex; flex-wrap: wrap; gap: 0.7rem; }
.result-actions .btn { flex: 1 1 auto; }

/* Compact footer variant (gallery/admin/portal pages): only the copyright row,
   so drop the homepage footer's tall top padding + the divider spacing that
   assume grid content sits above — kills the empty dark band. */
.bill-footer { margin-top: 2rem; padding-block: 1.6rem; }
.bill-footer .footer-bottom { margin-top: 0; padding-top: 0.4rem; border-top: 0; }

/* Off-screen invoice render host (used for print + PDF capture) */
.invoice-print-host { position: absolute; left: -10000px; top: 0; width: 720px; background: var(--color-white); }

@media (min-width: 880px) {
  .action-bar .btn { width: auto; min-width: 280px; }
}

/* Stack line items on small screens with field labels */
@media (max-width: 700px) {
  .li-head { display: none; }
  .li-row--labour, .li-row--mat {
    grid-template-columns: 1fr 1fr;
    border: 1px solid var(--color-line); border-radius: var(--radius-sm);
    padding: 0.8rem; gap: 0.5rem; position: relative;
  }
  .li-row--labour > *:first-child, .li-row--mat > *:first-child { grid-column: 1 / -1; }
  .li-amt { grid-column: 1 / -1; text-align: left; padding-top: 0.2rem; }
  /* scoped to these two row types on purpose — a bare ".row-rm" here would
     absolutely-position EVERY remove button on the page (location/contact/
     review cards too), which have no positioned ancestor to anchor to and
     fly off to the top of the page instead of sitting in their card. */
  .li-row--labour .row-rm, .li-row--mat .row-rm { position: absolute; top: 0.4rem; right: 0.4rem; }
}

/* PRINT: show only the rendered invoice */
@media print {
  .billing-page > .site-header,
  .billing-page > .bill-wrap,
  .billing-page > .site-footer,
  .billing-page > datalist { display: none !important; }
  .billing-page .invoice-print-host { position: static; left: 0; width: auto; }
  .billing-page { background: var(--color-white); padding: 0; }
}

/* =========================================================================
   18. OWNER DASHBOARD · PROJECT · REPORTS
   ========================================================================= */
/* Top nav (admin pages) — link style shared with the public nav, see §5.
   nowrap keeps the header a constant height on every page: with wrap, a page
   that has a vertical scrollbar is ~15px narrower and could tip the row onto a
   2nd line, making the header "jump" taller when switching tabs. */
/* Admin top nav is ALWAYS collapsed behind the hamburger (owner preference
   2026-07-19) — never a horizontal pill row, at any width. Hidden until the
   #dashToggle button flips .is-open on it. */
.dash-nav { display: none; gap: 0.4rem; flex-wrap: nowrap; align-items: center; }
.dash-nav.is-open {
  display: flex;
  /* anchored to the centered .nav column (position:relative, §5) so it sits
     flush under the hamburger; +14px = the header's bottom padding, keeping
     the hover chain contiguous for the mouseleave-close */
  position: absolute; top: calc(100% + 14px); left: 0; right: 0;
  flex-direction: column; align-items: flex-start; gap: 0;
  background: var(--color-white); border-bottom: 1px solid var(--color-line);
  box-shadow: var(--shadow-md); padding: 0.5rem var(--gutter) 1rem; z-index: 90;
}
.dash-nav.is-open a { width: 100%; padding: 0.85rem 0.6rem; border-radius: var(--radius-sm); border-bottom: 1px solid var(--color-line); text-align: right; }
/* From 640px up: a compact panel whose right edge lines up with the hamburger,
   instead of a full-width sheet. */
@media (min-width: 640px) {
  .dash-nav.is-open {
    left: auto; right: var(--gutter); width: 300px;
    border: 1px solid var(--color-line);
    border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  }
}

/* Status badge */
.badge { display: inline-block; font-family: var(--font-head); font-weight: 700; font-size: var(--fs-small);
  text-transform: uppercase; letter-spacing: 0.04em; padding: 0.2rem 0.6rem; border-radius: var(--radius-pill); }
.badge--open { background: color-mix(in srgb, var(--sm-teal-br) 18%, transparent); color: var(--color-teal-dark); }
.badge--done { background: color-mix(in srgb, var(--sm-orange) 14%, transparent); color: var(--color-amber-dark); }
/* A badge that IS an action (e.g. a message's Reply badge on the client hub):
   same look as the passive badge, plus the site-standard deboss press. */
button.badge { border: 0; cursor: pointer; transition: transform var(--transition), box-shadow var(--transition); }
button.badge:hover { transform: translateY(1px); box-shadow: var(--btn-deboss); }
button.badge:active { transform: translateY(2px); box-shadow: var(--btn-deboss-active); }

/* Dashboard layout */
.dash-grid { display: grid; gap: 1.1rem; grid-template-columns: 1fr; }
@media (min-width: 820px) { .dash-grid { grid-template-columns: 1fr 1fr; } }

.proj-list { display: grid; gap: 0.9rem; grid-template-columns: 1fr; }
@media (min-width: 620px) { .proj-list { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1000px) { .proj-list { grid-template-columns: 1fr 1fr 1fr; } }
.proj-card {
  display: block; background: var(--color-surface); border: 1.5px solid var(--color-line);
  border-left: 4px solid var(--color-navy); border-radius: var(--radius); padding: 1rem 1.1rem;
  box-shadow: var(--tile-shadow); transition: transform var(--transition), box-shadow var(--transition);
}
.proj-card:hover { transform: translateY(1px); box-shadow: var(--btn-deboss); border-left-color: var(--color-amber); }
.proj-card:active { transform: translateY(2px); box-shadow: var(--btn-deboss-active); }
.pc-top { display: flex; justify-content: space-between; align-items: center; gap: 0.6rem; }
.pc-top strong { font-family: var(--font-head); color: var(--color-navy); }
.pc-client { color: var(--color-ink); font-size: var(--fs-body); margin-top: 0.3rem; }
.pc-loc { color: var(--color-muted); }
.pc-foot { display: flex; justify-content: space-between; margin-top: 0.7rem; padding-top: 0.6rem; border-top: 1px solid var(--color-line); }
.pc-id { font-family: var(--font-mono, monospace); font-size: var(--fs-small); color: var(--color-muted); }
.pc-total { font-family: var(--font-head); font-weight: 800; color: var(--color-navy); }

/* expandable project card (client dashboard) — click the card to open it */
.proj-card--open { padding: 0; cursor: pointer; }
.proj-card--open > summary {
  list-style: none; padding: 1rem 1.1rem 1rem 2rem; position: relative; cursor: pointer;
}
.proj-card--open > summary::-webkit-details-marker { display: none; }
/* disclosure chevron on the left, rotates when open */
.proj-card--open > summary::before {
  content: ""; position: absolute; left: 0.9rem; top: 1.35rem;
  width: 0.5rem; height: 0.5rem; border-right: 2px solid var(--color-muted);
  border-bottom: 2px solid var(--color-muted); transform: rotate(-45deg);
  transition: transform var(--transition);
}
.proj-card--open[open] > summary::before { transform: rotate(45deg); }
.proj-card--open[open] { border-left-color: var(--color-amber); }
.proj-detail { padding: 0 1.1rem 1.1rem 2rem; }
.proj-detail .pd-scope { color: var(--color-ink); font-size: var(--fs-body); margin: 0 0 0.6rem; }
.proj-detail .pd-sub {
  font-family: var(--font-head); font-weight: 700; font-size: var(--fs-small); text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--color-muted); margin: 0.9rem 0 0.4rem;
}
.proj-detail .rtable { font-size: var(--fs-body); }

/* Project header meta */
.ph-meta { display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; align-items: center; font-size: var(--fs-lead); }

/* Tabs */
.tabs { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-bottom: 1rem; border-bottom: 2px solid var(--color-line); }
.tab {
  background: transparent; border: none; border-bottom: 3px solid transparent; margin-bottom: -2px;
  font-family: var(--font-head); font-weight: 600; font-size: var(--fs-lead); color: var(--color-muted);
  padding: 0.6rem 0.9rem; cursor: pointer;
}
.tab:hover { color: var(--color-navy); }
.tab.is-active { color: var(--color-navy); border-bottom-color: var(--color-amber); }
.tab-pane { display: none; }
.tab-pane.is-active { display: block; }

/* Timeline */
.tl-row {
  display: grid; grid-template-columns: auto auto 1fr auto auto; gap: 0.7rem; align-items: center;
  padding: 0.7rem 0.4rem; border-bottom: 1px solid var(--color-line);
}
.tl-date { font-family: var(--font-mono, monospace); font-size: var(--fs-small); color: var(--color-muted); white-space: nowrap; }
.tl-icon { font-size: var(--fs-h3); }
.tl-body { display: flex; flex-direction: column; min-width: 0; }
.tl-body strong { color: var(--color-navy); font-size: var(--fs-lead); }
.tl-sub { color: var(--color-muted); font-size: var(--fs-small); }
.tl-amt { font-family: var(--font-head); font-weight: 700; color: var(--color-navy); white-space: nowrap; }
.tl-task { border-left: 3px solid var(--color-teal); }
.tl-material { border-left: 3px solid var(--color-amber); }

.photo-chip { color: var(--color-teal-dark); font-weight: 600; }
.photo-chip:hover { color: var(--color-amber-dark); }

/* Gallery */
.gallery { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.9rem; }
.gal-item { display: inline-flex; align-items: center; gap: 0.4rem; background: var(--color-bg);
  border: 1px solid var(--color-line); border-radius: var(--radius-pill); padding: 0.3rem 0.4rem 0.3rem 0.8rem; font-size: var(--fs-body); }
.gal-item a { color: var(--color-navy); }
.gal-item--thumb { padding: 0.3rem; border-radius: var(--radius-sm); }
.gal-item--thumb img { width: 64px; height: 64px; object-fit: cover; border-radius: 6px; display: block; }

/* Filters */
/* Reports filters — flat & lightweight, NO card wrapper. The quick presets are
   the primary, instant filters (a tap applies immediately); the explicit
   Client / date / location inputs sit below, de-cluttered and inline. */
.rfilters { display: flex; flex-direction: column; gap: 0.5rem; margin: 0 0 0.7rem; }
.rf-presets { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; }
.rf-lbl { font-family: var(--font-head); font-weight: 600; font-size: var(--fs-small); text-transform: uppercase; letter-spacing: 0.04em; color: var(--color-muted); margin-right: 0.1rem; }
.rf-preset { font-family: var(--font-head); font-weight: 600; font-size: var(--fs-small); color: var(--color-navy);
  background: var(--color-surface); border: 1px solid var(--color-line); border-radius: var(--radius-pill);
  padding: 0.4rem 0.95rem; cursor: pointer; transition: background .15s, border-color .15s, color .15s, box-shadow .15s; }
@media (hover: hover) { .rf-preset:hover { border-color: var(--color-gold); box-shadow: var(--shadow-sm); } }
.rf-preset.is-active { background: var(--color-navy); color: var(--color-white); border-color: var(--color-navy); }
.rf-reset { margin-left: auto; background: none; border: 0; padding: 0.2rem 0.1rem; cursor: pointer;
  font-family: var(--font-head); font-weight: 600; font-size: var(--fs-small); color: var(--color-gold-dark);
  text-decoration: underline; text-underline-offset: 3px; }
@media (hover: hover) { .rf-reset:hover { color: var(--color-amber-dark); } }
.rf-adv { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; }
.rf-adv select, .rf-adv input { height: var(--control-h); padding: 0 0.55rem; font-family: var(--font-body); font-size: var(--fs-small);
  color: var(--color-ink); background: var(--color-surface); border: 1px solid var(--color-line); border-radius: var(--radius-sm); }
.rf-adv select:focus, .rf-adv input:focus { outline: none; border-color: var(--color-gold); box-shadow: var(--ring); }
.rf-adv select { min-width: 8.5rem; }
.rf-adv input[type="date"] { width: 8.4rem; }
.rf-adv input[type="text"] { flex: 1 1 8rem; min-width: 7rem; }
.rf-dash { color: var(--color-muted); }

/* Floating "+ New Client" action button — fixed bottom-right, stays on scroll.
   Reuses .btn--primary colors; .fab only adds the fixed placement + lift. */
.fab { position: fixed; right: 1.1rem; bottom: 1.1rem; z-index: 90;
  gap: 0.5rem; border-radius: var(--radius-pill); box-shadow: 0 10px 26px rgba(0,0,0,0.30); }
.fab svg { width: 20px; height: 20px; }
@media (hover: hover) { .fab:hover { transform: translateY(-2px); box-shadow: 0 14px 32px rgba(0,0,0,0.36); } }
.fab:active { transform: translateY(0); box-shadow: 0 8px 20px rgba(0,0,0,0.30); }

/* report results header: summary + expand/collapse-all, pushed to the right.
   --wrap lets the controls drop to their own line on narrow screens instead of
   squeezing the title into two lines and stacking the buttons vertically. */
.panel-head--wrap { flex-wrap: wrap; }
.panel-head--wrap > h2 { white-space: nowrap; }
.rhead-right { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; justify-content: flex-end; }
.rcpt-links { font-size: var(--fs-small); color: var(--color-muted); margin: 0 0 0.5rem; }
.rcpt-links a { color: var(--color-navy); font-weight: 600; }

/* Report table */
.table-scroll { overflow-x: auto; }
.rtable { width: 100%; border-collapse: collapse; font-size: var(--fs-body); }
.rtable th, .rtable td { padding: 0.6rem 0.7rem; text-align: left; border-bottom: 1px solid var(--color-line); white-space: nowrap; }
.rtable thead th { font-family: var(--font-head); font-size: var(--fs-small); text-transform: uppercase; letter-spacing: 0.03em; color: var(--color-muted); background: var(--color-bg); position: sticky; top: 0; }
.rtable th.sortable { cursor: pointer; -webkit-user-select: none; user-select: none; }
.rtable th.sortable:hover { color: var(--color-navy); }
.rtable tbody tr:hover { background: var(--color-bg); }
/* rows with a destination are fully clickable (same target as their Open/View
   button) — pointer + slightly stronger hover so it reads as clickable */
.rtable tbody tr[data-href] { cursor: pointer; }
@media (hover: hover) {
  .rtable tbody tr:hover { background: color-mix(in srgb, var(--color-gold) 5%, var(--color-surface)); }
  .rtable tbody tr[data-href]:hover { background: color-mix(in srgb, var(--color-gold) 9%, var(--color-surface)); }
}
.act-card[data-href] { cursor: pointer; transition: transform var(--transition), box-shadow var(--transition), background var(--transition); }
/* same press effect as the dashboard bands — the ONE site-wide band language */
@media (hover: hover) {
  .act-card[data-href]:hover { transform: translateY(-2px); border-color: var(--color-gold); box-shadow: 0 12px 26px rgba(20,32,50,.13); }
}
.act-card[data-href]:active { transform: translateY(0); }
.act-card[data-href]:active { transform: translateY(2px); box-shadow: var(--btn-deboss-active); }
/* keyboard: clickable rows/cards show the same focus ring as fold headers */
.rtable tbody tr[data-href]:focus-visible,
.act-card[data-href]:focus-visible { outline: none; box-shadow: var(--ring); }

/* shared admin list component (js/admin-table.js) — date-group headers,
   sortable columns, expandable detail rows */
.rtable th.sortable.is-sorted { color: var(--color-navy); }
.rtable tr.rt-group td {
  background: var(--color-bg-alt); font-family: var(--font-head); font-weight: 700;
  font-size: var(--fs-small); text-transform: uppercase; letter-spacing: 0.03em; color: var(--color-navy);
  white-space: nowrap; padding-top: 0.5rem; padding-bottom: 0.5rem;
}
.rtable tr.rt-group .rt-group-count { margin-left: 0.6rem; font-weight: 600; text-transform: none; letter-spacing: 0; color: var(--color-muted); }

/* ---- OWNER DESIGN STANDARD for record lists, SITE-WIDE (2026-07-13):
   2 nested COLLAPSIBLE category bands, then rows of exactly 3 columns
   (5 values total). Each band level wears its own color and rows their own,
   so the nesting reads by color alone; a value never appears twice on the
   page (a column is never also a band); no column headers above the bands.
   Rendered by js/cat-bands.js (Leads, Projects, Reports) and server-side by
   admin/email-activity.php. Tokens only — reskins with the theme.
   Level palette:
     L1 band  = filled bronze (same pairing as .btn--primary: gold gradient,
                ivory text) — the strongest strip on the page
     L2 band  = light bronze tint, dark text, one step in
     rows     = faint tint on white, hover deepens                        */
/* Force the collapse ourselves rather than relying on the UA's ::details-content
   hiding, which some Chromium builds skip — the [open] attribute always toggles
   correctly, so key off it directly. */
.cat-band:not([open]) > .cat-band-body { display: none; }
/* Every expandable row wears the SAME dress as the PRO-dashboard bands
   (owner rule 2026-07-13): white rounded pill, hairline border, tile shadow;
   hover = the shared press (dark at top-left AND bottom-right). Hierarchy
   reads from indentation + type scale, not from color. */
.cat-band > summary.cat-band-head {
  list-style: none; cursor: pointer; -webkit-user-select: none; user-select: none;
  display: flex; align-items: center; gap: 0.5rem; padding: 0.6rem 0.9rem;
  font-family: var(--font-head); color: var(--color-navy);
  background: var(--color-surface); border: 1.5px solid var(--color-line);
  border-radius: var(--radius); box-shadow: var(--tile-shadow);
  margin-bottom: 0.55rem;
  transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition);
}
.cat-band > summary.cat-band-head::-webkit-details-marker { display: none; }
/* same press language as the dashboard bands and every control on the site */
.cat-band > summary.cat-band-head:hover { transform: translateY(1px); box-shadow: var(--btn-deboss); border-color: var(--color-amber); }
.cat-band > summary.cat-band-head:active { transform: translateY(2px); box-shadow: var(--btn-deboss-active); }
.cat-band > summary.cat-band-head:focus-visible { outline: none; box-shadow: var(--ring); }
.cat-band-head .cb-count { font-weight: 400; font-size: var(--fs-small); color: var(--color-muted); }
.cat-band-head .cb-chev { margin-left: auto; font-size: var(--fs-lead); line-height: 1; transition: transform var(--transition); color: var(--color-muted); }
.cat-band[open] > summary .cb-chev { transform: rotate(180deg); }

/* L1 — strongest strip: bold uppercase */
.cat-band--l1 > summary.cat-band-head {
  text-transform: uppercase; letter-spacing: 0.04em; font-weight: 700; font-size: var(--fs-body);
}
/* L2 — one step in and one step down the type ladder */
.cat-band--l2 > summary.cat-band-head {
  font-weight: 600; font-size: var(--fs-small);
  margin-left: 1.4rem;
}
.cat-band--l2 { margin-bottom: 0.55rem; }

/* rows — their own color: faint tint on the panel surface, hover deepens */
.cat-rows { width: 100%; table-layout: fixed; border-collapse: collapse; }
/* Each cell is ONE line: nowrap makes the overflow:hidden + ellipsis actually
   truncate instead of wrapping (a phone number must never break across lines). */
.cat-rows td { padding: 0.3rem 0.6rem; border-top: 1px solid var(--color-line); font-size: var(--fs-body); vertical-align: middle; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; background: color-mix(in srgb, var(--color-gold) 6%, var(--color-surface)); }
.cat-rows .c1 { width: 46%; padding-left: 2.1rem; }
.cat-rows .c1 a { font-weight: 600; }
.cat-rows .c2 { width: 34%; color: var(--color-ink); }
.cat-rows .c2 a { color: var(--color-navy); font-weight: 500; }
@media (hover: hover) { .cat-rows .c2 a:hover { color: var(--color-amber-dark); text-decoration: underline; text-underline-offset: 3px; } }
.cat-rows .c3 { width: 20%; text-align: right; color: var(--color-ink); font-size: var(--fs-small); }
/* Narrow screens: give the phone the room it needs so it stays on one line,
   trim the name indent, and let the (secondary) email give up width & ellipsis. */
@media (max-width: 560px) {
  .cat-rows .c1 { width: 40%; padding-left: 1.1rem; }
  .cat-rows .c2 { width: 30%; }
  .cat-rows .c3 { width: 30%; }
  .cat-rows.has-sel .c1 { width: calc(40% - 2.2rem); padding-left: 0.2rem; }
}
/* selectable lists (Projects): a leading checkbox cell; c1 gives up its room */
.cat-rows .csel { width: 2.2rem; text-align: center; }
.cat-rows .csel input[type="checkbox"] { width: 16px; height: 16px; cursor: pointer; }
.cat-rows.has-sel .c1 { width: calc(46% - 2.2rem); padding-left: 0.2rem; }
/* only rows that actually navigate get the pointer + hover invitation */
.cat-rows tr[data-href] { cursor: pointer; }
@media (hover: hover) {
  .cat-rows tr[data-href]:hover td { background: color-mix(in srgb, var(--color-gold) 12%, var(--color-surface)); }
}
.cat-rows tr[data-href]:focus-visible { outline: none; box-shadow: var(--ring); }

/* List toolbar — a sticky search + expand/collapse-all bar that floats above a
   CatBands list (Clients). MUST sit OUTSIDE the .panel: .panel is overflow:hidden,
   which would cancel position:sticky. Sticks just below the sticky .site-header —
   the page script measures the header and sets --header-h. */
.list-toolbar {
  position: sticky; top: calc(var(--header-h, 3.6rem) + 0.4rem); z-index: 30;
  display: flex; gap: 0.6rem; align-items: center; flex-wrap: wrap;
  padding: 0.5rem 0.6rem; margin: 0 0 0.7rem;
  background: var(--color-surface); border: 1.5px solid var(--color-line);
  border-radius: var(--radius); box-shadow: var(--tile-shadow);
}
.list-toolbar .field { margin: 0; flex: 1 1 15rem; min-width: 0; }
.list-toolbar .lt-actions { display: flex; gap: 0.4rem; flex: 0 0 auto; }
.rtable .rt-toggle-cell { width: 2.2rem; text-align: center; }
.rtable .rt-select-cell { width: 2.2rem; text-align: center; }
.rtable .rt-select-cell input[type="checkbox"] { width: 16px; height: 16px; cursor: pointer; }
.rtable .rt-toggle {
  background: none; border: 1px solid var(--color-line); border-radius: 6px; width: 1.7rem; height: 1.7rem;
  color: var(--color-muted); font-size: var(--fs-body); line-height: 1; display: inline-flex; align-items: center; justify-content: center;
}
.rtable .rt-toggle:hover { background: var(--color-bg); color: var(--color-navy); }
.rtable tr.rt-detail-row td { background: var(--color-bg); white-space: normal; }
/* Columns a caller marks { hideOnMobile: true } (see js/admin-table.js) drop out
   below the panel's own scroll-container breakpoint, so the remaining columns
   fit without the table needing its own horizontal scrollbar. Full data for a
   hidden column is still reachable — every admin row opens its own detail page. */
@media (max-width: 640px) {
  .rtable .col-opt { display: none; }
  /* The first column (the row's title/name link, always present) is allowed to
     wrap here — its badge/subtext can drop to its own line instead of forcing
     the whole row wide the way every other nowrap cell does. */
  .rtable td:first-child { white-space: normal; }
}
.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; }
.btn-mini { display: inline-block; font-family: var(--font-head); font-weight: 600; font-size: var(--fs-small);
  background: var(--color-navy); color: var(--color-white); padding: 0.3rem 0.7rem; border-radius: var(--radius-pill);
  transition: transform var(--transition), box-shadow var(--transition), background var(--transition); }
.btn-mini:hover { background: var(--color-navy-deep); transform: translateY(1px); box-shadow: var(--btn-deboss); }
.btn-mini:active { transform: translateY(2px); box-shadow: var(--btn-deboss-active); }

/* Portal tiles (dashboard) */
.portal-grid { display: grid; gap: 0.55rem; grid-template-columns: 1fr; }
@media (min-width: 560px) { .portal-grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 900px) { .portal-grid { grid-template-columns: 1fr 1fr 1fr; } }
@media (min-width: 1150px) { .portal-grid { grid-template-columns: 1fr 1fr 1fr 1fr; } }

/* Collapsible dashboard bands (native <details>): a clickable header strip
   toggles its tile grid. Help sits outside a band so it's always visible. */
.portal-band { margin-bottom: 0.75rem; }
/* Title + hint stack as two dedicated lines (grid rows) instead of fighting
   for room side-by-side in one flex row — at narrow widths that used to wrap
   both the title AND the hint independently into a jumbled 3-line mess.
   Grid position is set per-child below, so no markup change is needed even
   though title/hint/chevron are plain sibling spans in the HTML. */
.portal-band-head {
  list-style: none; cursor: pointer; -webkit-user-select: none; user-select: none;
  display: grid; grid-template-columns: 1fr auto; column-gap: 0.6rem; row-gap: 0.05rem;
  align-items: center;
  padding: 0.42rem 0.9rem; margin-bottom: 0.55rem;
  background: var(--color-surface); border: 1.5px solid var(--color-line);
  border-radius: var(--radius); box-shadow: var(--tile-shadow);
  transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition);
}
.portal-band-head::-webkit-details-marker { display: none; }
/* :hover only on devices that actually support it — on touch, a stuck
   :hover after tap would otherwise leave the band looking permanently
   "pressed" until the user taps elsewhere (owner-reported 2026-07-20). */
@media (hover: hover) {
  .portal-band-head:hover { transform: translateY(1px); box-shadow: var(--btn-deboss); border-color: var(--color-amber); }
}
.portal-band-head:active { transform: translateY(2px); box-shadow: var(--btn-deboss-active); }
/* an author `display:grid` on .portal-grid beats the UA rule that hides a
   closed <details>'s content, so hide it explicitly when the band is closed. */
.portal-band:not([open]) .portal-grid { display: none; }
.portal-band-head .pb-title { grid-column: 1; grid-row: 1; font-family: var(--font-head); font-weight: 700; font-size: var(--fs-body); color: var(--color-navy); }
.portal-band-head .portal-band-hint { grid-column: 1; grid-row: 2; color: var(--color-muted); font-size: var(--fs-small); }
.portal-band-head .pb-chev { grid-column: 2; grid-row: 1 / 3; margin-left: 0; align-self: center; flex: none; width: 20px; height: 20px; color: var(--color-navy); transition: transform var(--transition); }
.portal-band[open] .portal-band-head .pb-chev { transform: rotate(180deg); }
.portal-tile {
  display: grid; grid-template-columns: 34px 1fr; grid-template-rows: auto auto; column-gap: 0.65rem; row-gap: 0.1rem; align-items: start;
  background: var(--color-surface); border: 1.5px solid var(--color-line);
  border-radius: var(--radius); padding: 0.55rem 0.85rem; box-shadow: var(--tile-shadow);
  transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition);
}
@media (hover: hover) {
  .portal-tile:hover { transform: translateY(1px); box-shadow: var(--btn-deboss); border-color: var(--color-amber); }
}
.portal-tile:active { transform: translateY(2px); box-shadow: var(--btn-deboss-active); }
.pt-ico {
  display: grid; place-items: center; width: 34px; height: 34px; border-radius: 9px;
  background: linear-gradient(135deg, var(--sm-teal-1), var(--sm-teal-2)); color: var(--color-white); margin-bottom: 0; grid-row: 1 / 3; align-self: center;
}
.pt-ico svg { width: 17px; height: 17px; }
.pt-title { font-family: var(--font-head); font-weight: 700; font-size: var(--fs-body); color: var(--color-navy); line-height: 1.3; }
.pt-desc { color: var(--color-muted); font-size: var(--fs-small); line-height: 1.35; }

/* Narrow form pages */
.form-narrow { max-width: 720px; }
/* -------------------------------------------------------------------------
   PRO ADMIN — density pass (2026-07-20, round 2 tightened further). Scoped
   to .billing-page so the public marketing site's forms/cards are never
   affected — same shared classes (.field, .card, .tab, .grid-2/4, .panel,
   .bill-wrap) are also used site-wide (incl. faq.php, which carries NO
   .billing-page class and must keep its original spacious hero look).
   ------------------------------------------------------------------------- */
.billing-page .bill-wrap { padding-block: 0.6rem 1.2rem; }
.billing-page .bill-head { margin-bottom: 0.5rem; }
.billing-page .bill-head h1 { font-size: var(--fs-h2); }
.billing-page .bill-head .muted { font-size: var(--fs-small); margin-top: 0.1rem; }

.billing-page .field { margin-bottom: 0.3rem; }
.billing-page .field label { margin-bottom: 0.1rem; }
.billing-page .field input,
.billing-page .field select,
.billing-page .field textarea {
  font-size: var(--fs-body);
  padding: 0.28rem 0.5rem;
}
.billing-page .field textarea { min-height: 52px; }
.billing-page .grid-2,
.billing-page .grid-3,
.billing-page .grid-4 { gap: 0.22rem 0.6rem; }
.billing-page .form-actions { margin-top: 0.4rem; gap: 0.4rem; }
.billing-page .tabs { margin-bottom: 0.45rem; }
.billing-page .tab { padding: 0.3rem 0.6rem; font-size: var(--fs-body); }
.billing-page .card { padding: 0.65rem; }
.billing-page .hint, .billing-page .hce-help { margin-bottom: 0.35rem; }
.billing-page .panel .sub { margin: 0.45rem 0 0.2rem; }
.billing-page .li-row { margin-bottom: 0.25rem; }
.billing-page .li-row input, .billing-page .li-row select { padding: 0.24rem 0.4rem; }
.billing-page .catalog-box { padding: 0.5rem; margin-bottom: 0.45rem; }

.bill-head--row { display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap; }
/* A PRO page opened from a dashboard tile wears that tile's dress: the SAME
   surface, 1.5px border, radius and --tile-shadow as .portal-tile, plus the
   very same .pt-ico chip and glyph (from inc/icons.php), so the card you tap
   and the page you land on are visibly the same object. No hover/press
   effects here on purpose — the header isn't clickable, only tiles are.
   A modifier, never plain .bill-head: that class is also used by public
   marketing pages, which must keep their flat hero. */
.bill-head--tile {
  display: grid; grid-template-columns: 40px 1fr; column-gap: 0.8rem; align-items: center;
  background: var(--color-surface); border: 1.5px solid var(--color-line);
  border-radius: var(--radius); box-shadow: var(--tile-shadow);
  padding: 0.7rem 1rem; margin-bottom: 0.55rem;
}
.bill-head--tile .pt-ico { width: 40px; height: 40px; grid-row: 1 / 3; align-self: center; }
.bill-head--tile .pt-ico svg { width: 20px; height: 20px; }
.bill-head--tile .bh-text { grid-column: 2; min-width: 0; }
.bill-head--tile h1 { font-size: var(--fs-h3); margin: 0; line-height: 1.15; }
.bill-head--tile .muted { margin-top: 0.12rem; font-size: var(--fs-small); }
/* keeps a trailing action (e.g. Projects' "+ New") on the header's right edge */
.bill-head--tile.bill-head--row { display: grid; grid-template-columns: 40px 1fr auto; }

/* Record-detail pages (one project / lead / client) are reached from a LIST
   rather than a tile, and their record panel already shares the tile's
   surface + border + shadow — what was missing is the mark. This puts the
   section's tile icon beside the record's own title, so a project page still
   reads as part of the Projects tool you came from. */
.panel-ident { display: flex; align-items: center; gap: 0.6rem; min-width: 0; }
.panel-ident .pt-ico { width: 32px; height: 32px; flex: none; }
.panel-ident .pt-ico svg { width: 16px; height: 16px; }
.panel-ident > div { min-width: 0; }
.grid-3 { display: grid; gap: 0.4rem 1rem; grid-template-columns: 1fr; }
@media (min-width: 560px) { .grid-3 { grid-template-columns: 2fr 1fr 1fr; } }
.link-accent { color: var(--color-amber-dark); font-weight: 600; }
.link-accent:hover { text-decoration: underline; }

/* Timeline reflow on mobile (keeps delete accessible) */
@media (max-width: 640px) {
  .tl-row {
    grid-template-columns: auto 1fr auto;
    grid-template-areas: "date amt rm" "body body body";
    gap: 0.3rem 0.6rem; padding: 0.7rem 0.2rem;
  }
  .tl-date { grid-area: date; }
  .tl-amt  { grid-area: amt; text-align: right; }
  .tl-row .row-rm { grid-area: rm; }
  .tl-icon { display: none; }
  .tl-body { grid-area: body; }
}

/* =========================================================================
   19. CHECKBOX CHIPS (quote form: skills, preferred reply)
   ========================================================================= */
.check-group { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.15rem; }
/* selector beats ".field label" (which would otherwise force display:block) */
.check-group .check-item {
  display: inline-flex; align-items: center; gap: 0.45rem;
  font-size: var(--fs-body); font-weight: 500; color: var(--color-ink);
  background: var(--color-bg); border: 1.5px solid var(--color-line);
  border-radius: var(--radius-pill); padding: 0.45rem 0.85rem; margin: 0; cursor: pointer;
  transition: border-color var(--transition), background var(--transition);
}
.check-group .check-item:hover { border-color: var(--color-navy); }
.check-group .check-item input { accent-color: var(--sm-orange); width: 16px; height: 16px; margin: 0; flex: none; }
.check-group .check-item:has(input:checked) { border-color: var(--sm-orange); background: color-mix(in srgb, var(--sm-orange) 5%, var(--color-white)); color: var(--color-navy); font-weight: 600; }

/* =========================================================================
   20. REVIEWS MANAGER (admin)
   ========================================================================= */
#rvList { display: grid; gap: 0.8rem; }
.rv-card { border: 1px solid var(--color-line); border-left: 4px solid var(--color-navy); border-radius: var(--radius-sm); padding: 0.8rem 1rem; background: var(--color-surface); }
/* flex-wrap + min-width:0 on the title: a long location address (or any
   long title) wraps onto its own line instead of pushing Edit/Remove off
   the visible edge of the card at narrow widths. */
.rv-card-top { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.rv-card-top strong { color: var(--color-navy); font-family: var(--font-head); min-width: 0; flex: 1 1 auto; }
.rv-stars { color: var(--color-gold); letter-spacing: 1px; }
.rv-card-top .row-rm { margin-left: auto; flex: none; }
.rv-meta { font-size: var(--fs-small); color: var(--color-muted); margin-top: 0.1rem; }
.rv-quote { margin-top: 0.4rem; color: var(--color-ink); font-size: var(--fs-lead); }

/* =========================================================================
   21. SKINS
   Default (:root above) = "Beach Vibe" (the original teal / sand / yellow;
   internal slug stays santa-monica-beach).
   Two light, elegant alternates, chosen from the dashboard and applied
   site-wide via <html data-theme="…"> (see inc/theme.php):
     ivory-ink          — warm ivory + charcoal ink + muted teal
     oil-rubbed-bronze  — warm ivory + deep oil-rubbed bronze
   Components read semantic tokens, so most flip from the token blocks below;
   the grouped rules afterward fix the few spots that reuse one token as both
   a foreground and a background.
   ========================================================================= */

/* ---- Ivory & Ink ---- (warm ivory + charcoal INK, monochrome — no color) */
[data-theme="ivory-ink"] {
  --sm-gold:#2E2B25;     --sm-gold-dark:#1A1813;     /* accent = warm charcoal ink */
  --sm-orange:#2E2B25;   --sm-orange-dark:#1A1813;
  --color-gold:#2E2B25;  --color-gold-dark:#1A1813;
  --color-amber:#2E2B25; --color-amber-dark:#1A1813;
  --color-teal:#2E2B25;  --color-teal-dark:#1A1813;
  --color-navy:#26231E;  --color-navy-deep:#1A1813; --color-navy-darker:#13110C;
  --klein:#2E2B25;       --klein-deep:#1A1813;
  --color-ink:#262420;   --color-muted:#6F6A60;
  --color-line:#E6DFCC;  --tint-line:#DAD2BC; --tint-cool:#EEE7D6;
  --color-surface:#FFFFFF; --color-bg:#F5F1E7; --color-bg-alt:#EFE8D8;
  --color-star:#2E2B25;  --color-success:#4A463C;
  --ring:0 0 0 3px color-mix(in srgb, var(--color-gold) 28%, transparent);
  --fx:#002FA7; --fx-soft:#3D6BFF; --fx-bright:#6E92FF; --fx-ink:#FFFFFF; /* Klein blue effects */
}

/* ---- Oil-Rubbed Bronze & Ivory ---- */
[data-theme="oil-rubbed-bronze"] {
  /* Recommended palette 2026-07-18: taupe buttons + elegant gold + near-black ink */
  --sm-gold:#867460;     --sm-gold-dark:#6E5F4C;
  --sm-orange:#867460;   --sm-orange-dark:#6E5F4C;
  --color-gold:#867460;  --color-gold-dark:#6E5F4C;
  --color-amber:#867460; --color-amber-dark:#6E5F4C;
  --color-teal:#867460;  --color-teal-dark:#6E5F4C;
  --color-navy:#1A1A1A;  --color-navy-deep:#242424; --color-navy-darker:#2D2D2D;
  --klein:#867460;       --klein-deep:#6E5F4C;
  --color-ink:#1A1A1A;   --color-muted:#8A7D71;
  --color-line:#D9D3CA;  --tint-line:#CFC8BC; --tint-cool:#EFEAE2;
  --color-surface:#FFFFFF; --color-bg:#F6EDE9; --color-bg-alt:color-mix(in srgb, var(--color-bg) 90%, var(--color-ink));
  --color-star:#867460;  --color-success:#6E8B5E;
  --ring:0 0 0 3px color-mix(in srgb, var(--color-gold) 35%, transparent);
  --fx:#D2AB84; --fx-soft:#E4CBA6; --fx-bright:#F1E0C6; --fx-ink:#2A2118; /* elegant gold effects */
  /* Section titles + eyebrows: the site's dark brown text, with the warm-orange
     kept only as the glow/shadow effect (--fx-orange). Change --color-heading to
     retune every homepage title/eyebrow color at once. */
  --color-heading:var(--color-navy); --fx-orange:#E07B39;
}

/* ---- shared across the elegant alternates (token-driven) ---- */
[data-theme="ivory-ink"] body,
[data-theme="oil-rubbed-bronze"] body { background: var(--color-bg); }

[data-theme="ivory-ink"] .brand .brand-mark,
[data-theme="oil-rubbed-bronze"] .brand .brand-mark { background: var(--color-gold); color: var(--color-bg); }
/* Recommended palette: near-black "Ka" logo tile + elegant-gold "Co" */
[data-theme="oil-rubbed-bronze"] .brand .brand-mark { background:#1A1A1A; color:var(--color-bg); }
[data-theme="oil-rubbed-bronze"] .brand .brand-amp { color:var(--fx); }

[data-theme="ivory-ink"] .btn--primary,
[data-theme="ivory-ink"] .nav-phone,
[data-theme="oil-rubbed-bronze"] .btn--primary,
[data-theme="oil-rubbed-bronze"] .nav-phone { color: var(--color-bg); }

/* same gold-on-dark pairing as .btn--primary: ivory numbers on filled wizard dots */
[data-theme="ivory-ink"] .wiz-dot.is-active,
[data-theme="oil-rubbed-bronze"] .wiz-dot.is-active { color: var(--color-bg); }

[data-theme="ivory-ink"] .pt-ico,
[data-theme="oil-rubbed-bronze"] .pt-ico { background: linear-gradient(135deg, var(--color-gold), var(--color-gold-dark)); color: var(--color-bg); }

[data-theme="ivory-ink"] .hero,
[data-theme="oil-rubbed-bronze"] .hero {
  background: linear-gradient(135deg, color-mix(in srgb, var(--color-navy-darker) 62%, transparent), color-mix(in srgb, var(--color-navy-deep) 34%, transparent)), var(--hero-img) center/cover no-repeat;
  background-color: var(--color-navy-darker);
}

[data-theme="ivory-ink"] .check-group .check-item:has(input:checked),
[data-theme="oil-rubbed-bronze"] .check-group .check-item:has(input:checked) {
  border-color: var(--color-gold); background: color-mix(in srgb, var(--color-gold) 14%, var(--color-surface)); color: var(--color-ink);
}
[data-theme="ivory-ink"] .badge--open,
[data-theme="oil-rubbed-bronze"] .badge--open { background: color-mix(in srgb, var(--color-gold) 16%, transparent); color: var(--color-gold-dark); }
[data-theme="ivory-ink"] .badge--done,
[data-theme="oil-rubbed-bronze"] .badge--done { background: color-mix(in srgb, var(--color-success) 18%, transparent); color: var(--color-success); }

/* =========================================================================
   22. SKIN FLAIR (highlight + glow) — shared rules, per-skin highlight color
   Each skin defines the --fx / --fx-soft / --fx-bright / --fx-ink trio (§1 +
   §21); these rules apply that highlight identically to every skin:
     Beach Vibe = orange · Ivory & Ink = Klein blue · Oil-Rubbed Bronze = gold
   ========================================================================= */

/* highlight accents */
[data-theme] .hero h1 .accent {
  color: var(--fx-soft);
  text-shadow: 0 0 30px color-mix(in srgb, var(--fx) 72%, transparent);
}
/* marker-highlight headline: a gold stroke PAINTS ITSELF behind each accent
   word on load, one word after the other, and STAYS — the text flips to the
   skin's on-gold ink once its stroke lands. Unmissable and permanent, not a
   passing shimmer. Token-only (fx / fx-soft / fx-ink).
   box-decoration-break keeps the stroke intact when a phrase wraps. */
[data-theme] .hero h1 .accent {
  padding: 0 0.12em;
  margin: 0;
  border-radius: var(--radius);
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  text-shadow: none;
  /* ONE gradient, 3× the word's width, with a bright shimmer band parked in
     the middle third: at rest only gold shows; sliding background-position-x
     sweeps the band across the letters, then it hides off-edge again. */
  background-repeat: no-repeat;
  background-image: linear-gradient(105deg,
    var(--fx) 0%, var(--fx) 46%,
    color-mix(in srgb, var(--fx-bright) 55%, white) 50%,
    var(--fx) 54%, var(--fx) 100%);
  /* band sized to the LETTERFORMS in em (cap-top → below descenders), not to
     the font's ~1.4em metric box: 1.08em band inside 1.2em lines leaves a
     guaranteed 0.12em gap between wrapped lines at any font size */
  background-size: 0 1.08em;
  background-position: left 0.26em;
  /* paint once, then a shimmer sweep re-runs EVERY 3s, forever */
  animation: hero-marker-paint 0.7s ease-out both,
             hero-marker-shimmer 3s linear 1.5s infinite;
}
/* stagger both animations word by word (paint delay, shimmer delay) */
[data-theme] .hero h1 .accent:nth-of-type(2) { animation-delay: 0.35s, 1.85s; }
[data-theme] .hero h1 .accent:nth-of-type(3) { animation-delay: 0.7s, 2.2s; }
[data-theme] .hero h1 .accent:nth-of-type(4) { animation-delay: 1.05s, 2.55s; }
[data-theme] .hero h1 .accent:nth-of-type(5) { animation-delay: 1.4s, 2.9s; }
/* alternate-word headlines can have more highlighted words — keep both
   sequences sequential past the original five */
[data-theme] .hero h1 .accent:nth-of-type(6) { animation-delay: 1.75s, 3.25s; }
[data-theme] .hero h1 .accent:nth-of-type(7) { animation-delay: 2.1s, 3.6s; }
[data-theme] .hero h1 .accent:nth-of-type(8) { animation-delay: 2.45s, 3.95s; }
[data-theme] .hero h1 .accent:nth-of-type(9) { animation-delay: 2.8s, 4.3s; }
/* paint: width grows to the full 300% canvas (band still parked off-edge),
   text color flips to on-gold ink when the stroke lands */
@keyframes hero-marker-paint {
  0%        { background-size: 0 1.08em;    color: var(--fx-soft); }
  60%       { background-size: 300% 1.08em; color: var(--fx-soft); }
  85%, 100% { background-size: 300% 1.08em; color: var(--fx-ink); }
}
/* shimmer: the bright band sweeps across in the first ~0.7s of each 3s cycle,
   then rests hidden — both loop ends show plain gold, so the restart is
   invisible */
@keyframes hero-marker-shimmer {
  0%        { background-position-x: 0%; }
  23%       { background-position-x: 100%; }
  100%      { background-position-x: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  [data-theme] .hero h1 .accent { animation: none; background-size: 300% 1.08em; color: var(--fx-ink); }
}
[data-theme] .hero-trust .ht-num {
  color: var(--fx-soft);
  text-shadow: 0 0 16px color-mix(in srgb, var(--fx) 45%, transparent);
}
[data-theme] .brand .brand-amp { color: var(--fx); }


/* highlight glow in the hero (radial wash, top-right).
   Overlay kept light so the real jobsite photo reads clearly — the darker
   top-left corner plus the text-shadow below keep the headline legible. */
[data-theme] .hero {
  background:
    radial-gradient(72% 95% at 78% 14%, color-mix(in srgb, var(--fx) 18%, transparent), transparent 60%),
    linear-gradient(135deg, color-mix(in srgb, var(--color-navy-darker) 62%, transparent), color-mix(in srgb, var(--color-navy-deep) 34%, transparent)),
    var(--hero-img) center/cover no-repeat;
  background-color: var(--color-navy-darker);
}
[data-theme] .hero h1,
[data-theme] .hero .lead { text-shadow: 0 2px 14px rgba(0,0,0,0.55); }

/* glowing primary CTA — shared by EVERY pill (header nav-phone, hero
   Call-Now phone-pill, form Send Request, Bigger-job link) so all pills on
   the page carry the identical gold ring + glow + hover lift */
[data-theme] .btn--primary,
[data-theme] .nav-phone,
[data-theme] .phone-pill {
  border-color: color-mix(in srgb, var(--fx) 70%, transparent);
  /* machined edge (fine-detail pass 2026-07-19): thin light line along the
     top + thin dark line along the bottom, under the gold ring + glow */
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.38),
              inset 0 -1px 0 rgba(0,0,0,0.10),
              0 0 0 1px color-mix(in srgb, var(--fx) 70%, transparent),
              0 10px 30px color-mix(in srgb, var(--fx) 40%, transparent);
}
/* hover = the button INVITES a click: lift up, glow brighter (never darker/
   flatter than rest — a hover that looks less alive than rest reads as
   "nothing happened"). The press/deboss look is reserved for :active only
   (the actual click), so lift and press stay two distinct, honest states. */
[data-theme] .btn--primary:hover,
[data-theme] .nav-phone:hover,
[data-theme] .phone-pill:hover {
  border-color: var(--fx);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.38),
              inset 0 -1px 0 rgba(0,0,0,0.10),
              0 0 0 1.5px var(--fx),
              0 14px 34px color-mix(in srgb, var(--fx) 60%, transparent);
  transform: translateY(-2px);
}
[data-theme] .btn--primary:active,
[data-theme] .nav-phone:active,
[data-theme] .phone-pill:active {
  box-shadow: var(--btn-deboss-active), 0 0 0 1px var(--fx);
  transform: translateY(1px);
}

/* brand mark + hero card glow */
[data-theme] .brand .brand-mark {
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--fx) 40%, transparent),
              0 0 20px color-mix(in srgb, var(--fx) 55%, transparent);
}
/* on hover the mark's gold ring wakes up — same brightening as .btn--primary */
[data-theme] .brand:hover .brand-mark,
[data-theme] .brand:focus-visible .brand-mark {
  box-shadow: 0 0 0 1px var(--fx),
              0 0 26px color-mix(in srgb, var(--fx) 75%, transparent);
}
/* Every hero box wears the SAME gold border + glow as the top-left date pill
   (2px gold ring at 70%, plus the ambient gold glow). One rule = uniform. */
[data-theme] .hero-card,
[data-theme] .hero-box {
  border: 2px solid color-mix(in srgb, var(--fx) 70%, transparent);
  box-shadow: var(--shadow-lg), 0 0 52px color-mix(in srgb, var(--fx) 20%, transparent);
}

/* Right-column box variants (owner styles 2026-07-04) ---------------------
   --glass: the SAME recipe as .hero-pill (the date box in the left column) —
   translucent brown over a blur of the photo, gold border, ivory text.
   --clear: fully transparent, no card at all, bold ivory text. */
[data-theme] .hero-box--glass {
  background:
    linear-gradient(135deg, rgba(255,255,255,0.08), transparent 45%),
    color-mix(in srgb, var(--color-navy) 62%, transparent);
  -webkit-backdrop-filter: blur(7px) saturate(140%);
  backdrop-filter: blur(7px) saturate(140%);
  border: 2px solid color-mix(in srgb, var(--fx) 70%, transparent);
  border-radius: clamp(18px, 3vw, 28px);
  color: var(--color-white);
}
[data-theme] .hero-box--glass h3 { color: var(--color-white); }
[data-theme] .hero-box--glass .hero-review p { color: rgba(255,255,255,0.92); }
[data-theme] .hero-box--glass .hero-review cite { color: var(--color-white); }
[data-theme] .hero-box--glass .hero-review-stars { color: var(--fx); }
[data-theme] .hero-box--glass .field label { color: var(--color-white); }
[data-theme] .hero-box--glass .reply-promise { color: rgba(255,255,255,0.9); }

[data-theme] .hero-box--clear {
  /* darkened rounded panel — keeps the gold border + glow inherited from
     [data-theme] .hero-box above, so it matches every other box */
  background:
    linear-gradient(135deg, rgba(255,255,255,0.06), transparent 45%),
    color-mix(in srgb, var(--color-navy-darker) 58%, transparent);
  border-radius: clamp(18px, 3vw, 28px);
  -webkit-backdrop-filter: blur(6px) saturate(130%);
  backdrop-filter: blur(6px) saturate(130%);
  color: var(--color-white);
}
[data-theme] .hero-box--clear h3 { color: var(--color-white); }
[data-theme] .hero-box--clear .sub { color: rgba(255,255,255,0.88); }
[data-theme] .hero-box--clear .gt-text strong { color: var(--color-white); font-weight: 800; }
[data-theme] .hero-box--clear .gt-text span { color: rgba(255,255,255,0.92); font-weight: 600; }
/* Same gold divider as .hero-pill-rule (under the date), everywhere a row
   separator or section divider appears in the right column. */
[data-theme] .hero-box--clear .gt-row,
[data-theme] .gt-row,
[data-theme] .hero-trust { border-top-color: var(--color-gold); border-top-width: 2px; }

/* service / why cards: highlight edge + glow on hover */
[data-theme] .card { transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition); }
[data-theme] .card:hover {
  border-color: color-mix(in srgb, var(--fx) 70%, transparent);
  box-shadow: var(--btn-deboss);
  transform: translateY(1px);
}

/* ---- icon "logotypes": high-contrast highlight + glow ---- */
/* contact-info tiles: deep tile, bright highlight icon, ring + glow */
[data-theme] .contact-tile .ci-ico {
  background: linear-gradient(150deg, color-mix(in srgb, var(--fx) 24%, var(--color-navy)), var(--color-navy));
  color: var(--fx-soft);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--fx) 32%, transparent),
              0 0 18px color-mix(in srgb, var(--fx) 20%, transparent);
}
/* review avatar: highlight disc, contrast initial, glow ring */
[data-theme] .review .avatar {
  background: linear-gradient(135deg, var(--fx-soft), var(--fx));
  color: var(--fx-ink);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--fx) 38%, transparent),
              0 0 16px color-mix(in srgb, var(--fx) 28%, transparent);
}
/* gallery slide-number badge: same brand color as the "Ka" mark / primary button */
[data-theme] .gal-num {
  background: var(--color-gold);
  color: var(--color-bg);
  box-shadow: 0 0 14px color-mix(in srgb, var(--color-gold) 35%, transparent);
}
/* gallery prev/next button: same brand color as the "Ka" mark / primary button */
[data-theme] .gal-btn {
  background: var(--color-gold);
  color: var(--color-bg);
  border-color: color-mix(in srgb, var(--color-gold) 60%, transparent);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.38),
              inset 0 -1px 0 rgba(0,0,0,0.10),
              0 0 0 1px color-mix(in srgb, var(--color-gold) 45%, transparent),
              0 6px 18px color-mix(in srgb, var(--color-gold) 32%, transparent);
}
[data-theme] .gal-btn:hover {
  background: var(--color-gold-dark);
  border-color: var(--color-gold);
  transform: translateY(-1px);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.38),
              inset 0 -1px 0 rgba(0,0,0,0.10),
              0 0 0 1px var(--color-gold), 0 10px 26px color-mix(in srgb, var(--color-gold) 48%, transparent);
}

/* =========================================================================
   23. QUOTE FORM EXTRAS (lead-gen)
   ========================================================================= */
/* honeypot — hidden from people, visible to bots (no layout/scroll impact) */
.hp-field { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ZIP service-area note */
.svc-note { font-size: var(--fs-small); color: var(--color-muted); margin-top: 0.35rem; min-height: 1.15em; }
.svc-note.is-ok { color: var(--color-success); font-weight: 600; }

/* emergency call-now shortcut (revealed when "Emergency" timeframe is picked) */
.emergency-call {
  display: flex; align-items: center; gap: 0.5rem; margin-top: 0.6rem; padding: 0.6rem 0.9rem;
  border-radius: var(--radius-sm); font-family: var(--font-head); font-weight: 700; font-size: var(--fs-lead);
  background: color-mix(in srgb, var(--color-amber) 14%, var(--color-surface));
  color: var(--color-amber-dark);
  border: 1px solid color-mix(in srgb, var(--color-amber) 40%, transparent);
}
.emergency-call:hover { background: color-mix(in srgb, var(--color-amber) 24%, var(--color-surface)); }

/* photo drop zone */
.field .file-input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.file-drop {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.35rem;
  text-align: center; padding: 1.4rem 1rem; cursor: pointer;
  border: 2px dashed var(--color-line); border-radius: var(--radius-sm);
  background: var(--color-bg); color: var(--color-muted);
  transition: border-color var(--transition), background var(--transition), color var(--transition);
}
.file-drop:hover, .file-drop.is-drag { border-color: var(--color-amber); background: color-mix(in srgb, var(--color-amber) 7%, var(--color-bg)); color: var(--color-ink); }
.file-drop svg { width: 26px; height: 26px; color: var(--color-amber); }
.file-drop-text { font-weight: 500; }
.file-drop strong { color: var(--color-amber-dark); }
.file-drop-hint { font-size: var(--fs-small); color: var(--color-muted); }
.file-list { list-style: none; margin: 0.6rem 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.4rem; }
.file-list li {
  display: inline-flex; align-items: center; gap: 0.4rem; font-size: var(--fs-small);
  background: var(--color-bg-alt); border: 1px solid var(--color-line); border-radius: var(--radius-pill);
  padding: 0.3rem 0.75rem; color: var(--color-ink);
}
.file-remove { background: none; border: 0; padding: 0 0.1rem; cursor: pointer; color: var(--err-fg); font-weight: 700; font-size: 0.9em; line-height: 1; }
.file-list li.file-note { background: none; border: 0; color: var(--err-fg); }

/* trust strip above the submit button */
.trust-strip {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 0.5rem 1.2rem;
  margin: 0.4rem 0 1.1rem; font-size: var(--fs-small); color: var(--color-muted);
}
.trust-strip span { display: inline-flex; align-items: center; gap: 0.35rem; }
.trust-strip strong { color: var(--color-ink); }
/* compact variant inside the hero quote card */
.trust-strip--form { gap: 0.3rem 0.9rem; margin: 0.2rem 0 0.5rem; font-size: var(--fs-small); }

/* the reply-speed promise, shown BEFORE submitting */
.reply-promise {
  text-align: center; font-size: var(--fs-small); color: var(--color-success);
  font-weight: 600; margin: 0 0 0.8rem;
}
/* Simple Contact Request footer buttons: "Send Request" + "Add details" split
   into two equal halves (stacks on very narrow widths). */
.hero-form-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.hero-form-actions > * { flex: 1 1 45%; white-space: nowrap; }

/* secondary path to the detailed quote form — a real button, not a footnote.
   white-space:normal overrides .btn's nowrap: the long label must wrap, or its
   min-content width blows the hero column open on ~768-800px viewports. */
.expert-cta { margin-top: 0.8rem; font-size: var(--fs-body); padding: 0.7rem 1rem; white-space: normal; }

/* hero card choose-your-path (simple / detailed / live chat / call now) */
.quote-choice { display: grid; gap: 0.7rem; }
.quote-choice .sub { margin-bottom: 0.3rem; }
.qc-option {
  display: block; width: 100%; text-align: left; cursor: pointer; font: inherit;
  background: var(--color-surface); border: 1.5px solid var(--color-line);
  border-radius: var(--radius-sm); padding: 1rem 1.1rem; text-decoration: none;
  transition: border-color var(--transition), background var(--transition);
}
.qc-option:hover { border-color: var(--color-gold); background: color-mix(in srgb, var(--color-gold) 7%, var(--color-surface)); }
.qc-title { display: block; font-family: var(--font-head); font-weight: 700; color: var(--color-navy); }
.qc-hint { display: block; font-size: var(--fs-small); color: var(--color-muted); margin-top: 0.2rem; }
.qc-call-label { text-align: center; font-size: var(--fs-small); color: var(--color-muted); margin: 0.5rem 0 0.5rem; }
.qc-call { text-align: center; margin: 0; }

/* phone pill — same hover language as .btn (lift + shadow). Every accent
   token (gold/amber/klein/teal) collapses to the same bronze under this
   skin by design, so "its own color" has to come from --color-navy (the
   skin's dark ink tone) — the one token that actually reads as a distinct
   color next to the gold Free-Quote button, not another shade of it. */
.phone-pill {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; white-space: nowrap;
  box-sizing: border-box;
  /* size from the control-scale tokens ONLY — same as .btn / .nav-phone */
  height: var(--control-h); padding: 0 var(--control-pad-x); border-radius: var(--radius-pill);
  background: var(--color-navy); border: 1px solid var(--color-navy); color: var(--color-white);
  font-family: var(--font-head); font-weight: 700; font-size: var(--control-fs);
  transition: var(--transition);
}
.phone-pill svg { width: 1.05em; height: 1.05em; flex: none; }
.phone-pill:hover { transform: translateY(-2px); background: var(--color-navy-deep); border-color: var(--color-navy-deep); box-shadow: var(--shadow-md); }
.phone-pill:active { transform: translateY(0); }
.qc-back { background: none; border: 0; padding: 0; margin: 0 0 0.6rem; cursor: pointer; font: inherit; font-size: var(--fs-small); color: var(--color-muted); }
.qc-back:hover { color: var(--color-ink); }

/* homepage contact section: panel that hands off to the wizard page */
.wizard-entry h3 { font-family: var(--font-head); font-size: var(--fs-h3); color: var(--color-navy); margin-bottom: 0.5rem; }
.wizard-entry > p { color: var(--color-muted); margin-bottom: 1rem; }
.wizard-entry .next-steps { margin-bottom: 1.2rem; }
.wizard-entry .trust-strip { margin-top: 1rem; }

/* ---- Detailed Estimate wizard (detailed-quote.php) ---- */
.wiz-wrap { max-width: 640px; margin: 0 auto; }
.wiz-progress { counter-reset: wiz; display: flex; gap: 0.7rem; justify-content: center; margin: 0.4rem 0 0.3rem; }
.wiz-dot {
  counter-increment: wiz;
  width: 36px; height: 36px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--color-bg-alt); color: var(--color-muted);
  border: 1.5px solid var(--color-line);
  font-family: var(--font-head); font-weight: 700; font-size: var(--fs-lead);
  transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.wiz-dot::before { content: counter(wiz); }
.wiz-dot.is-active { background: var(--color-gold); color: var(--color-navy); border-color: var(--color-gold); }
.wiz-count { text-align: center; font-size: var(--fs-small); color: var(--color-muted); margin-bottom: 1.2rem; }
.wiz-step { display: none; border: 0; padding: 0; margin: 0; }
.wiz-step.is-active { display: block; }
.wiz-q { font-family: var(--font-head); font-weight: 700; font-size: var(--fs-h3); color: var(--color-navy); margin-bottom: 0.9rem; padding: 0; }
.wiz-options { display: grid; gap: 0.55rem; }
.wiz-option {
  display: flex; align-items: center; gap: 0.7rem;
  padding: 0.85rem 1rem; border: 1.5px solid var(--color-line); border-radius: var(--radius-sm);
  background: var(--color-surface); cursor: pointer; font-weight: 500; color: var(--color-ink);
  transition: border-color var(--transition), background var(--transition);
}
.wiz-option:hover { border-color: var(--color-gold); }
.wiz-option input { accent-color: var(--color-gold); width: 18px; height: 18px; margin: 0; flex: none; }
.wiz-option:has(input:checked) {
  border-color: var(--color-gold);
  background: color-mix(in srgb, var(--color-gold) 10%, var(--color-surface));
  font-weight: 600;
}
.wiz-err { min-height: 1.2em; font-size: var(--fs-small); color: var(--err-fg); margin-top: 0.5rem; }
.wiz-err:not(:empty) {
  font-weight: 600;
  background: color-mix(in srgb, var(--err-fg) 8%, var(--color-surface));
  border: 1px solid color-mix(in srgb, var(--err-fg) 35%, transparent);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.9rem;
}
.wiz-nav { display: flex; gap: 0.8rem; justify-content: space-between; margin-top: 1.4rem; }
.wiz-nav .btn { flex: 1; }
/* .btn's display would beat the [hidden] attribute — wizard.js drives which
   button shows per step (Next on steps 1-3, Send My Request only on the last) */
.wiz-nav .btn[hidden] { display: none; }

/* Box 5: testimonials cycle under the hero quote form (from content/reviews.csv).
   Slides stack; only .is-active shows. Height follows the tallest slide so the
   card doesn't jump as reviews rotate. */
.hero-reviews { position: relative; margin-top: 1.1rem; border-top: 1px solid var(--color-line);
  display: grid; }
.hero-review {
  grid-area: 1 / 1;                 /* stack every slide in the same cell */
  margin: 0; padding: 0.8rem 1rem 0.7rem;
  font-size: var(--fs-small); color: var(--color-muted);
  opacity: 0; visibility: hidden; transition: opacity 0.4s ease;
}
.hero-review.is-active { opacity: 1; visibility: visible; }
.hero-review-head { display: flex; align-items: center; gap: 0.55rem; }
/* thumbnail — placeholder for a future reviewer photo (shows the initial) */
.hero-review-thumb { flex: none; width: 34px; height: 34px; border-radius: 50%;
  background: var(--color-bg-alt); color: var(--color-navy);
  display: grid; place-items: center; font-family: var(--font-head); font-weight: 700; font-size: var(--fs-body); }
.hero-review-stars { color: var(--color-star); letter-spacing: 0.1em; font-size: var(--fs-body); }
.hero-review p { margin: 0.4rem 0 0.3rem; color: var(--color-ink); font-style: italic; line-height: 1.5; }
.hero-review cite { font-style: normal; font-weight: 600; color: var(--color-navy); }

/* "what happens next" steps below the button */
.next-steps { list-style: none; counter-reset: ns; margin: 1.1rem 0 0; padding: 0; display: grid; gap: 0.55rem; }
/* centered variant — the block of steps is centered in the card, each row's
   number + text still reading left-to-right within it. */
.next-steps--center { width: fit-content; margin-inline: auto; }
.next-steps li { counter-increment: ns; display: flex; align-items: flex-start; gap: 0.6rem; font-size: var(--fs-lead); color: var(--color-ink); }
.next-steps li::before {
  content: counter(ns); flex: none; width: 24px; height: 24px; margin-top: 1px; border-radius: 50%;
  display: grid; place-items: center; font-family: var(--font-head); font-weight: 700; font-size: var(--fs-small);
  background: var(--color-amber); color: var(--color-white);
}

/* =========================================================================
   24. SKIN FLAIR — highlight polish for the lead-gen form extras (§23)
   ========================================================================= */
[data-theme] .file-drop:hover,
[data-theme] .file-drop.is-drag { border-color: var(--fx); background: color-mix(in srgb, var(--fx) 8%, var(--color-bg)); }
[data-theme] .file-drop svg,
[data-theme] .file-drop strong { color: var(--fx); }
[data-theme] .next-steps li::before {
  background: var(--fx); color: var(--fx-ink);
  box-shadow: 0 0 10px color-mix(in srgb, var(--fx) 30%, transparent);
}
[data-theme] .emergency-call {
  background: color-mix(in srgb, var(--fx) 14%, var(--color-surface));
  color: var(--fx);
  border-color: color-mix(in srgb, var(--fx) 45%, transparent);
  box-shadow: 0 0 14px color-mix(in srgb, var(--fx) 18%, transparent);
}
[data-theme] .emergency-call:hover { background: color-mix(in srgb, var(--fx) 22%, var(--color-surface)); }
/* footer contact icons + link hover: brighter tint for contrast on the dark footer */
[data-theme] .footer-contact svg { color: var(--fx-soft); }
[data-theme] .site-footer a:hover { color: var(--fx-soft); }

/* =========================================================================
   25. ACTIVITY FEED (admin/inbox.php's own feed; admin/client.php's
   per-client slice of the same feed, via api/billing.php?action=client_activity)
   ========================================================================= */
.act-card { border: 1px solid var(--color-line); border-left: 4px solid var(--color-gold); border-radius: var(--radius-sm);
  padding: 0.9rem 1.1rem; margin-bottom: 0.8rem; background: var(--color-surface); }
.act-card.is-new { border-left-color: var(--color-navy); background: var(--color-bg-alt); }
.act-top { display: flex; flex-wrap: wrap; gap: 0.4rem 0.9rem; align-items: baseline; justify-content: space-between; }
.act-client { font-family: var(--font-head); font-weight: 700; color: var(--color-navy); }
.act-date { font-size: var(--fs-small); color: var(--color-muted); }
.act-summary { margin: 0.4rem 0 0.2rem; font-size: var(--fs-lead); }
.act-detail { margin-top: 0.4rem; padding: 0.6rem 0.8rem; background: var(--color-bg); border-radius: 6px; font-size: var(--fs-lead); white-space: pre-wrap; }
.act-links { margin-top: 0.5rem; }

/* =========================================================================
   26. PRO PAGE DESIGN STANDARD
   (documented for the owner in Help & Docs → "Design standard")
   Every PRO page is built from stacked .panel blocks:
   - .panel--fold: the WHOLE header row is the open/close control — click
     anywhere on it (chevron shows the state; clicks on real controls inside
     the head — buttons, links — never toggle). Behavior: js/main.js
     initPanelFolds(). Markup: role="button" tabindex="0" aria-expanded +
     title/aria-label on the .panel-head.
   - Every input/select/textarea lives inside a .field (label above,
     control below) and spans its column's full width (§7 sets width:100%)
     — NEVER inline-flexed next to a button.
   - .form-actions: submit/action buttons ALWAYS go on their own line BELOW
     the fields, left-aligned; the inline status message rides in the same
     row after the buttons.
   ========================================================================= */
.panel--fold > .panel-head {
  cursor: pointer; user-select: none;
  transition: transform var(--transition), box-shadow var(--transition), background var(--transition);
}
/* same press effect as the dashboard bands — the ONE site-wide band language */
@media (hover: hover) {
  .panel--fold > .panel-head:hover { transform: translateY(-2px); border-color: var(--color-gold); box-shadow: 0 12px 26px rgba(20,32,50,.13); }
}
.panel--fold > .panel-head:active { transform: translateY(2px); box-shadow: var(--btn-deboss-active); }
.panel--fold > .panel-head:focus-visible { outline: none; box-shadow: var(--ring); }
/* first head child stretches so buttons + chevron cluster on the right
   (overrides the head's space-between, which would strand a lone button
   in the middle of the row) */
.panel--fold > .panel-head > :first-child { flex: 1 1 auto; min-width: 0; }
.panel--fold > .panel-head::after {
  content: "▾"; flex: none; color: var(--color-muted);
  font-size: var(--fs-lead); line-height: 1;
  transition: transform var(--transition);
}
.panel--fold.is-collapsed > .panel-head::after { transform: rotate(-90deg); }
/* collapsed: the head's bottom border would double the panel's own edge */
.panel.is-collapsed > .panel-head { border-bottom: none; }

.form-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-start; gap: 0.6rem; margin-top: 0.9rem; }
.form-actions .inline-status { margin-left: 0.3rem; }

/* Email / Call / Text contact pill row — shared by admin/lead.php and
   admin/client.php (moved here from lead.php's private style block, which
   client.php borrowed the class name from without ever having the styles). */
.lead-contact { display: flex; flex-wrap: wrap; gap: 0.8rem 1.6rem; margin-top: 0.4rem; }

/* =========================================================================
   24. FINE-DETAIL PASS (2026-07-19) — homepage micro-details, site-wide
   The homepage hero's pixel-level treatments promoted to the shared sheet so
   every surface (public + portal + admin) wears the identical details.
   Token-only (--fx trio + brand tokens) so all three skins stay correct.
   Purely additive: accents, edge highlights and hover physics — no layout,
   sizing or content changes.
   ========================================================================= */

/* --- eyebrow accent: small rotated gold square before every eyebrow.
   [data-theme] prefix so this outranks the page-scoped .lf-/.kb- variants'
   own single-class rules (their <style> blocks load after this sheet). --- */
[data-theme] .eyebrow,
[data-theme] .lf-eyebrow,
[data-theme] .kb-eyebrow {
  display: inline-flex; align-items: center; gap: 0.55rem;
}
[data-theme] .eyebrow::before,
[data-theme] .lf-eyebrow::before,
[data-theme] .kb-eyebrow::before {
  content: ""; flex: none; width: 6px; height: 6px;
  background: var(--fx); transform: rotate(45deg);
  box-shadow: 0 0 6px color-mix(in srgb, var(--fx) 65%, transparent);
}

/* --- gold sweep bar: a thin gold→bright gradient sweeps across the top
   edge of every interactive tile on hover (the homepage KB-tile move). --- */
[data-theme] .card,
[data-theme] a.contact-tile,
[data-theme] .qc-option,
[data-theme] .portal-tile { position: relative; overflow: hidden; }
[data-theme] .card::before,
[data-theme] a.contact-tile::before,
[data-theme] .qc-option::before,
[data-theme] .portal-tile::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: linear-gradient(90deg, var(--color-gold), var(--fx));
  transform: scaleX(0); transform-origin: left;
  transition: transform 0.3s ease; pointer-events: none;
}
[data-theme] .card:hover::before,
[data-theme] a.contact-tile:hover::before,
[data-theme] .qc-option:hover::before,
[data-theme] .portal-tile:hover::before { transform: scaleX(1); }

/* --- permanent gold hairline across the top of dark bands (same rule the
   homepage "how it works" band wears) --- */
[data-theme] .section--navy,
[data-theme] .cta-band { position: relative; }
[data-theme] .section--navy::before,
[data-theme] .cta-band::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: linear-gradient(90deg, transparent, var(--fx), transparent);
  opacity: 0.75; pointer-events: none;
}

/* --- panels (PRO + admin): quiet version of the same hairline --- */
[data-theme] .panel { position: relative; }
[data-theme] .panel::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 2px;
  background: linear-gradient(90deg, transparent, var(--fx) 50%, transparent);
  opacity: 0.55; pointer-events: none;
}

/* --- filled gold icon chips: the ONE gradient recipe the homepage step
   numbers + KB icons wear, applied to every icon chip site-wide (service
   cards, why-us, portal tiles, active wizard dot). Shape stays each chip's
   own; only the fill, ink and edge highlights unify. --- */
[data-theme] .card .icon,
[data-theme] .why-item .why-ico,
[data-theme] .pt-ico,
[data-theme] .wiz-dot.is-active {
  background: linear-gradient(155deg, var(--fx-bright), var(--fx) 55%, var(--color-gold-dark));
  color: var(--fx-ink);
  box-shadow: inset 0 1.5px 0 rgba(255,255,255,0.55),
              inset 0 -2px 3px rgba(0,0,0,0.22),
              0 0 0 1px color-mix(in srgb, var(--fx) 70%, transparent),
              0 4px 14px color-mix(in srgb, var(--fx) 45%, transparent);
}

/* --- active editor tab: same machined edge as the primary pills --- */
[data-theme] .hce-tab.is-active {
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.30),
              inset 0 -1px 0 rgba(0,0,0,0.12);
}

/* =========================================================================
   KA LOCKS CO — PRO Dashboard sophistication pass (2026-07-20).
   Uses the theme's existing --fx-bright (skin-aware "brightest hover" highlight)
   as the single bright accent + springier, more dynamic motion: lift-and-glow
   tiles, a diagonal sheen sweep, an icon pop, and a motion-safe staggered
   entrance. Scoped to the dashboard's .portal-* chrome; appended last so it
   wins the cascade over the base rules above.
   ========================================================================= */

/* Tiles — replace the press-in hover with a premium lift + gold glow + sheen. */
.portal-tile {
  position: relative; overflow: hidden; will-change: transform;
  transition: transform .3s cubic-bezier(.22,1,.36,1), box-shadow .3s ease, border-color .3s ease;
}
.portal-tile::after {                    /* diagonal sheen, swept across on hover (::before is the theme's top accent bar) */
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0; z-index: 1;
  background: linear-gradient(115deg, transparent 30%,
              color-mix(in srgb, var(--fx-bright) 60%, transparent) 47%, transparent 60%);
  transform: translateX(-120%);
}
.portal-tile:hover {
  transform: translateY(-4px);
  border-color: var(--color-gold);
  box-shadow: 0 16px 36px rgba(20,32,50,.17),
              0 0 0 1px color-mix(in srgb, var(--color-gold) 50%, transparent),
              0 0 22px color-mix(in srgb, var(--fx-bright) 30%, transparent);
}
.portal-tile:hover::after { opacity: 1; animation: pt-sheen .75s cubic-bezier(.22,1,.36,1); }
.portal-tile:active { transform: translateY(-1px) scale(.994); }
@keyframes pt-sheen { from { transform: translateX(-120%); } to { transform: translateX(120%); } }

/* Icon — brighten, scale, and glow on hover; title warms to the accent. */
.pt-ico { transition: transform .3s cubic-bezier(.34,1.56,.64,1), box-shadow .3s ease; position: relative; z-index: 2; }
.portal-tile:hover .pt-ico {
  transform: translateY(-2px) scale(1.07) rotate(-3deg);
  box-shadow: 0 8px 20px color-mix(in srgb, var(--color-gold) 45%, transparent);
}
.pt-title, .pt-desc { position: relative; z-index: 2; }
.pt-title { transition: color .22s ease; }
.portal-tile:hover .pt-title { color: var(--color-amber-dark); }

/* Band headers — lift + gold accent + a soft top highlight; springy chevron. */
.portal-band-head {
  position: relative; overflow: hidden;
  transition: transform .28s cubic-bezier(.22,1,.36,1), box-shadow .28s ease, border-color .28s ease;
}
.portal-band-head::after {               /* thin bright top-edge highlight, fades in on hover */
  content: ""; position: absolute; top: 0; left: 12%; right: 12%; height: 2px; opacity: 0;
  background: linear-gradient(90deg, transparent, var(--fx-bright), transparent);
  transition: opacity .28s ease;
}
.portal-band-head:hover {
  transform: translateY(-2px); border-color: var(--color-gold);
  box-shadow: 0 12px 26px rgba(20,32,50,.13);
}
.portal-band-head:hover::after { opacity: .9; }
.portal-band-head:active { transform: translateY(0); }
.portal-band-head .pb-chev { transition: transform .38s cubic-bezier(.34,1.56,.64,1); }

/* Staggered entrance — motion-safe. Runs on load and when a band opens. */
@media (prefers-reduced-motion: no-preference) {
  .portal-band[open] .portal-tile { animation: pt-rise .5s cubic-bezier(.22,1,.36,1) both; }
  .portal-grid .portal-tile:nth-child(2) { animation-delay: .05s; }
  .portal-grid .portal-tile:nth-child(3) { animation-delay: .10s; }
  .portal-grid .portal-tile:nth-child(4) { animation-delay: .15s; }
  .portal-grid .portal-tile:nth-child(5) { animation-delay: .20s; }
  .portal-grid .portal-tile:nth-child(6) { animation-delay: .25s; }
  @keyframes pt-rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
}
/* =========================================================================
   PRO nav dropdown — refined (2026-07-20). The admin hamburger menu was
   reusing the pill-row's press-in hover, which reads oddly as a vertical
   list. This turns it into a proper menu: rounded panel + gold top hairline,
   a soft gold-tint hover fill, a right-edge accent that grows on hover/active
   (text is right-aligned), and a motion-safe staggered entrance. Skin-aware
   via --color-gold / --fx-bright. Appended last to win the cascade.
   ========================================================================= */
.dash-nav.is-open {
  border-radius: var(--radius); overflow: hidden; padding: 0.4rem;
  box-shadow: 0 18px 44px rgba(20,32,50,.18),
              0 0 0 1px color-mix(in srgb, var(--color-gold) 30%, transparent);
  animation: nav-drop .2s cubic-bezier(.22,1,.36,1) both;
}
.dash-nav.is-open::before {              /* gold hairline across the panel top */
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 2px; pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--color-gold), transparent);
}
@keyframes nav-drop { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: none; } }

.dash-nav.is-open a {
  position: relative; width: 100%;
  padding: 0.7rem 1rem; border-radius: var(--radius-sm);
  border-bottom: none; text-align: right; box-shadow: none;
  transition: background .16s ease, color .16s ease, transform .16s ease;
}
.dash-nav.is-open a + a { margin-top: 1px; }
.dash-nav.is-open a::after {            /* right-edge accent, grows on hover/active */
  content: ""; position: absolute; right: 0.4rem; top: 50%;
  transform: translateY(-50%) scaleY(0); transform-origin: center;
  width: 3px; height: 56%; border-radius: 3px; background: var(--fx-bright);
  transition: transform .16s ease;
}
.dash-nav.is-open a:hover {
  background: color-mix(in srgb, var(--color-gold) 15%, transparent);
  transform: none; box-shadow: none;
}
.dash-nav.is-open a:hover::after { transform: translateY(-50%) scaleY(1); }
.dash-nav.is-open a.is-active { background: var(--color-navy); color: var(--color-white); box-shadow: var(--shadow-sm); }
.dash-nav.is-open a.is-active:hover { background: var(--color-navy-deep); }
.dash-nav.is-open a.is-active::after { transform: translateY(-50%) scaleY(1); background: var(--color-gold); }

@media (prefers-reduced-motion: no-preference) {
  .dash-nav.is-open a { animation: nav-item .26s cubic-bezier(.22,1,.36,1) both; }
  .dash-nav.is-open a:nth-child(1){animation-delay:.02s}
  .dash-nav.is-open a:nth-child(2){animation-delay:.05s}
  .dash-nav.is-open a:nth-child(3){animation-delay:.08s}
  .dash-nav.is-open a:nth-child(4){animation-delay:.11s}
  .dash-nav.is-open a:nth-child(5){animation-delay:.14s}
  .dash-nav.is-open a:nth-child(6){animation-delay:.17s}
  .dash-nav.is-open a:nth-child(7){animation-delay:.20s}
  .dash-nav.is-open a:nth-child(8){animation-delay:.23s}
  .dash-nav.is-open a:nth-child(9){animation-delay:.26s}
  .dash-nav.is-open a:nth-child(10){animation-delay:.29s}
  .dash-nav.is-open a:nth-child(11){animation-delay:.32s}
  @keyframes nav-item { from { opacity: 0; transform: translateX(12px); } to { opacity: 1; transform: none; } }
}
/* Nav dropdown — icons + left-aligned labels (2026-07-20) for faster scanning.
   Overrides the right-aligned refinement above (appended later = wins). */
.dash-nav.is-open a {
  display: flex; align-items: center; justify-content: flex-start;
  text-align: left; gap: .7rem; padding: .7rem 1rem .7rem .95rem;
}
.dash-nav.is-open a .dn-ico { width: 18px; height: 18px; flex: none; opacity: .82;
  transition: opacity .16s ease, transform .16s ease; }
.dash-nav.is-open a .dn-label { flex: 1 1 auto; }
.dash-nav.is-open a .nav-badge { flex: none; margin-left: auto; }
.dash-nav.is-open a:hover .dn-ico { opacity: 1; transform: scale(1.08); }
.dash-nav.is-open a.is-active .dn-ico { opacity: 1; }
.dash-nav.is-open a::after { left: .3rem; right: auto; }   /* accent moves to the icon (left) side */

/* =========================================================================
   27. KNOWLEDGE-BASE BROWSER — shared search + category tiles + article list.
   One source of truth for the reusable ".kb-*" component: instant-answer
   search, category tiles, and the collapsible article list. Driven entirely
   by js/knowledge.js reading window.KB (cats + articles) — used by BOTH the
   public Security Knowledge Base (knowledge.php) and the PRO-only Technician
   KB (admin/technician-kb.php). Page-specific framing (hero copy, CTA button)
   stays inline on each page; only the browser chrome itself lives here.
   ========================================================================= */
.kb-searchwrap { max-width: 680px; margin: 1.1rem auto 0; padding: 0 1rem; position: relative; }
.kb-search { width: 100%; padding: 0.95rem 1.1rem 0.95rem 2.9rem; font-size: var(--fs-lead); font-family: var(--font-body);
  border: 2px solid var(--color-line); border-radius: var(--radius-pill); background: var(--color-surface); color: var(--color-ink); box-shadow: var(--shadow-sm); }
.kb-search:focus { outline: none; border-color: var(--color-gold); box-shadow: var(--ring); }
.kb-searchwrap svg { position: absolute; left: 1.9rem; top: 50%; transform: translateY(-50%); width: 20px; height: 20px; color: var(--color-muted); pointer-events: none; }

.kb-answer { max-width: 680px; margin: 1rem auto 0; padding: 0 1rem; }
.kb-answer-card { border: 1px solid var(--color-gold); background: color-mix(in srgb, var(--color-gold) 8%, var(--color-surface));
  border-radius: var(--radius); padding: 1rem 1.15rem; box-shadow: var(--shadow-sm); }
.kb-answer-tag { font-family: var(--font-head); font-weight: 700; font-size: .68rem; letter-spacing: .12em; text-transform: uppercase; color: var(--color-gold-dark); }
.kb-answer-q { font-family: var(--font-head); font-weight: 700; color: var(--color-navy); font-size: var(--fs-lead); margin: .2rem 0 .4rem; }
.kb-answer-a { color: var(--color-ink); line-height: 1.6; margin: 0; }
.kb-answer-more { display: inline-block; margin-top: .6rem; font-family: var(--font-head); font-weight: 600; font-size: var(--fs-small);
  color: var(--color-navy); background: none; border: 0; cursor: pointer; padding: 0; text-decoration: underline; text-underline-offset: 3px; }
.kb-answer-disc { font-size: var(--fs-small); color: var(--color-muted); margin: .55rem auto 0; text-align: center; }

.kb-tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: .8rem; max-width: 900px; margin: 1.5rem auto 0; padding: 0 1rem; }
@media (max-width: 680px) { .kb-tiles { grid-template-columns: 1fr; } }
.kb-tile { text-align: center; background: var(--color-surface); border: 1px solid var(--color-line); border-radius: var(--radius);
  padding: 1.3rem 1rem; cursor: pointer; box-shadow: var(--shadow-sm); transition: border-color .15s, transform .1s, box-shadow .15s; font: inherit; color: inherit; }
.kb-tile:hover { border-color: var(--color-gold); transform: translateY(-2px); box-shadow: var(--shadow-md); }
.kb-tile.is-active { border-color: var(--color-gold); box-shadow: 0 0 0 1px var(--color-gold), var(--shadow-sm); background: color-mix(in srgb, var(--color-gold) 7%, var(--color-surface)); }
.kb-tile .kb-tile-ico { font-size: 2.6rem; color: var(--color-gold); line-height: 1; }
.kb-tile h3 { font-family: var(--font-head); color: var(--color-navy); font-size: var(--fs-lead); margin: .45rem 0 .35rem; }
.kb-tile p { color: var(--color-muted); font-size: var(--fs-small); line-height: 1.5; margin: 0; }
.kb-allreset { text-align: center; margin: .8rem auto 0; }
.kb-allreset button { background: none; border: 0; color: var(--color-gold-dark); font-weight: 600; font-family: var(--font-head);
  cursor: pointer; font-size: var(--fs-small); text-decoration: underline; text-underline-offset: 3px; }

.kb-list { max-width: 760px; margin: 1.4rem auto 0; padding: 0 1rem 1rem; }
.kb-count { font-size: var(--fs-small); color: var(--color-muted); margin: 0 0 .7rem; }
.kb-item { border: 1px solid var(--color-line); border-radius: var(--radius); background: var(--color-surface);
  margin-bottom: .7rem; box-shadow: var(--shadow-sm); overflow: hidden; }
.kb-item > summary { list-style: none; cursor: pointer; padding: 1rem 1.1rem; position: relative; }
.kb-item > summary::-webkit-details-marker { display: none; }
.kb-item-cat { font-family: var(--font-head); font-weight: 700; font-size: .62rem; letter-spacing: .1em; text-transform: uppercase; color: var(--color-gold-dark); }
.kb-item-title { font-family: var(--font-head); font-weight: 700; color: var(--color-navy); font-size: var(--fs-lead); margin: .15rem 0 .25rem; }
.kb-item-a { color: var(--color-muted); font-size: var(--fs-small); line-height: 1.5; margin: 0; }
.kb-item[open] .kb-item-a { display: none; }
.kb-item-body { padding: 0 1.1rem 1.1rem; color: var(--color-ink); line-height: 1.65; font-size: var(--fs-body); }
.kb-item-body .kb-lead { font-weight: 600; color: var(--color-navy); }
.kb-empty { text-align: center; color: var(--color-muted); padding: 1.5rem 1rem; }
.kb-empty a { color: var(--color-gold-dark); font-weight: 600; }

.kb-note { font-size: var(--fs-small); color: var(--color-muted); text-align: center; max-width: 60ch; margin: .8rem auto 0; padding: 0 1rem 1.5rem; line-height: 1.55; }

/* =========================================================================
   SHARED PAGE UTILITIES — KEEP BYTE-IDENTICAL ACROSS SITES (2026-07-21).
   The ONE utility vocabulary for capierre.com, kalocksco.com and the KASITE
   template. These replace per-page inline style="" attributes (margins,
   alignment, narrow measures). Rules of the section:
     - never add a site-specific rule here;
     - never redefine one of these locally or inline;
     - a value change is made here on ALL THREE sites in the same edit
       (the KASITE drift-check page is the watchdog).
   ========================================================================= */
/* vertical rhythm */
.stack-xs  { margin-top: 0.8rem; }
.stack-sm  { margin-top: 1rem; }
.stack-md  { margin-top: 1.2rem; }
.gap-below { margin-bottom: 1.2rem; }
/* alignment */
.ta-center { text-align: center; }
/* narrower reading measures for prose sections */
.container--narrow { max-width: 48rem; }
.container--tight  { max-width: 40rem; }
/* back-link with no trailing gap (login pages — nothing follows it) */
.nav-back--flush { margin-right: 0; }
/* server-rendered status banner sitting above a form needs bottom spacing
   the JS-driven inline ones don't (.is-ok/.is-err already make it visible) */
.form-status.is-shown { margin-bottom: 1rem; }
