/* Ace Pro Home Services — base styles & brand tokens */
:root {
  --navy: #1F3A56;
  /* Was #7C7F8C, which is only 3.5:1 on cream — under the 4.5:1 AA floor for
     body text, and the hero's lead paragraph uses it. #666973 measures 4.8:1
     and still reads as muted. */
  --gray: #666973;
  --brass: #D6A848;
  /* Brass is a fill colour. As TEXT on the cream page it lands at 1.9:1, which
     is close to unreadable — the hero's "SUPER AWESOME EXPERT REPAIR" line was
     exactly that. This is the same hue taken down to 4.6:1 for text use only;
     --brass stays as-is for buttons, borders, the brand dot and anything filled. */
  --brass-text: #8A6620;
  --walnut: #5C3A1A;
  /* Text sitting on a BRASS TINT (a wash of brass over the page, not solid
     brass). The tint follows the page, so it is pale in light mode and dark in
     dark mode — which means walnut text on it vanishes after dark. This token
     flips; --walnut stays put for text on solid brass. */
  --on-tint: #5C3A1A;
  --cream: #F4EFE6;
  --ink: #2B2118;
  --paper: #FFFFFF;
  --line: #E4DACA;
  --shadow: rgba(43, 33, 24, 0.14);
  /* Status colours. These were being written as raw hex in half a dozen places
     (the staff pills, the call page's mute/hang-up buttons, each page's own
     .error-msg rule), which meant three slightly different reds. One set here,
     all measured against --cream: alert 4.9:1, good 7.4:1, warn 6.8:1.
     The -soft pair is the fill the matching text colour is legible on. */
  --alert: #B3402B;
  --alert-soft: #F7E3DE;
  --good: #1F5C35;
  --good-soft: #D8ECDD;
  --warn: #7A5510;
  --warn-soft: #FDEACD;
  /* The inside of a video frame: a warm near-black, so letterbox bars read as
     the same walnut family as the rest of the site rather than a cold void. */
  --stage: #241E18;
  --serif: "Georgia", "Times New Roman", serif;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --wrap: 1120px;
}
/* The site is LIGHT for everyone. It used to follow the visitor's OS setting via
   prefers-color-scheme, which meant anyone whose machine is in dark mode — a lot
   of people — got a near-black page and a workshop photo so dimmed it read as
   mud. A handyman's shopfront should look like daylight regardless of how the
   visitor has their laptop configured, so the auto-switch is gone.

   The dark palette below is kept, but now only fires when something explicitly
   sets data-theme="dark" on <html>. Nothing does today; it is there so a toggle
   can be added later without rebuilding the palette. */
:root[data-theme="dark"] {
  --cream: #1B1713; --paper: #241E18; --ink: #EFE6D6; --line: #3A3128; --gray: #A7A9B2;
  --shadow: rgba(0,0,0,0.5);
  --on-tint: #EFC98E;
  /* Brass-as-text needs to go LIGHTER on a dark page, not darker. */
  --brass-text: #EFC98E;
  /* Same idea for the status set: the text colours lighten, the soft fills
     darken, so each pair keeps its contrast after dark. */
  --alert: #F0A493; --alert-soft: #4A2018;
  --good: #9BD8AF;  --good-soft: #1B3826;
  --warn: #EFC98E;  --warn-soft: #3C2E12;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--sans);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3 { font-family: var(--serif); line-height: 1.15; font-weight: 700; }
a { color: var(--navy); }
/* This was written as `:root[data-theme="dark"] a, @media (...) { ... }` — a
   selector list cannot contain an @media, so the whole rule was invalid and the
   browser threw it away, plus it left a stray closing brace. Valid now. */
:root[data-theme="dark"] a { color: var(--brass); }
img { max-width: 100%; display: block; }
.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 16px; }
.muted { color: var(--gray); }
.center { text-align: center; }

/* ---- buttons ---- */
/* ---- waiting on someone ----
   Every "Loading…" in the staff and owner areas is a moment where somebody is
   standing there looking at the screen, so it may as well be Steve looking
   back. Same mark as the video call's empty frame, so the whole site waits in
   one voice rather than with a different grey sentence on every screen. */
.waiting { display: grid; place-items: center; gap: .8rem; padding: 2rem 1rem;
           text-align: center; color: var(--gray);
           border: 1px dashed var(--line); border-radius: 12px; }
.waiting img { width: 84px; height: 84px; border-radius: 50%; display: block;
               box-shadow: 0 0 0 3px var(--brass), 0 6px 18px var(--shadow);
               animation: waitpulse 2.2s ease-in-out infinite; }
.waiting.small img { width: 52px; height: 52px; }
.waiting p { margin: 0; }
@keyframes waitpulse {
  0%, 100% { transform: scale(1);    opacity: .88; }
  50%      { transform: scale(1.04); opacity: 1; }
}

/* ---- reduced-motion support ---- */
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
}

.btn {
  display: inline-block; padding: 0.8rem 1.4rem; border-radius: 10px;
  font-weight: 600; text-decoration: none; cursor: pointer; border: 0;
  background: var(--navy); color: #fff; transition: transform .08s ease, filter .15s ease;
}
.btn:hover { filter: brightness(1.08); transform: translateY(-1px); }
@media (prefers-reduced-motion: reduce) {
  .btn { transition: none; }
  .btn:hover { transform: none; }
}
.btn.ghost { background: transparent; color: var(--ink); border: 2px solid var(--brass); }
.btn.brass { background: var(--brass); color: var(--walnut); }

/* ---- header / nav ---- */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--cream) 88%, transparent);
  backdrop-filter: blur(8px); border-bottom: 1px solid var(--line);
}
.nav { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 0.7rem 16px; max-width: var(--wrap); margin: 0 auto; }
.brand { display: flex; align-items: center; gap: .6rem; font-family: var(--serif); font-weight: 700; font-size: 1.15rem; color: var(--ink); text-decoration: none; }
.brand .dot { width: 12px; height: 12px; border-radius: 50%; background: var(--brass); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brass) 30%, transparent); }
.nav-links { display: flex; gap: 1.1rem; align-items: center; }
.nav-links a { text-decoration: none; color: var(--ink); font-weight: 500; font-size: .96rem; }
.nav-links a:hover { color: var(--navy); }
.nav-links a.cta { color: #fff; background: var(--navy); padding: .5rem .9rem; border-radius: 8px; }
.nav-toggle { display: none; background: none; border: 0; font-size: 1.6rem; color: var(--ink); cursor: pointer; }
@media (max-width: 860px) {
  .nav-toggle { display: block; }
  .nav-links { display: none; position: absolute; top: 100%; right: 0; left: 0; flex-direction: column; align-items: stretch; gap: 0; background: var(--paper); border-bottom: 1px solid var(--line); padding: .5rem 16px 1rem; }
  .nav-links.open { display: flex; }
  .nav-links a { padding: .7rem 0; border-bottom: 1px solid var(--line); }
  .nav-links a.cta { text-align: center; margin-top: .6rem; }
}

/* ---- hero ---- */
.hero {
  padding: 1.1rem 0 1.4rem;
  border-bottom: 1px solid var(--line);
  /* Artisanal wood watermark across the top: strong cream veil on the text side,
     wood showing through behind the portrait; fades to cream at the bottom. */
  background-image:
    linear-gradient(to bottom, transparent 80%, var(--cream) 100%),
    linear-gradient(105deg,
      color-mix(in srgb, var(--cream) 92%, transparent) 0%,
      color-mix(in srgb, var(--cream) 89%, transparent) 100%),
    url("/assets/workshop-bg-v2.webp");
  background-size: cover, cover, cover;
  background-position: center, center, right 42%;
  background-repeat: no-repeat;
}
.hero-art { margin-top: -0.5rem; }
@media (max-width: 860px){ .hero-art { margin-top: 0; } }
.hero-grid { display: grid; grid-template-columns: 1.05fr 1fr; gap: 2rem; align-items: center; }
@media (max-width: 860px) { .hero-grid { grid-template-columns: 1fr; text-align: center; } }
.hero h1 { font-size: clamp(2rem, 5vw, 3.1rem); margin: 0 0 .4rem; }
.hero .tag { color: var(--brass-text); font-weight: 700; letter-spacing: .04em; text-transform: uppercase; font-size: .85rem; }
.hero p.lead { font-size: 1.15rem; color: var(--gray); margin: .6rem 0 1.3rem; }
.hero .cta-row { display: flex; gap: .8rem; flex-wrap: wrap; }
@media (max-width: 860px){ .hero .cta-row { justify-content: center; } }

.values { display: flex; gap: 1.4rem; margin: 1.6rem 0 0; flex-wrap: wrap; }
@media (max-width: 860px){ .values { justify-content: center; } }
.values .v { display: flex; align-items: center; gap: .5rem; font-weight: 600; }
.values .v .ic { color: var(--brass-text); font-size: 1.2rem; }

/* ---- pop-out portrait ---- */
/* Two layers cut from Steve's own artwork: the hung frame (with the painting
   and the plaque) sits at z=0; Steve, the wrench and The Boss stand out of it.

   A layer at depth z is magnified by perspective/(perspective-z), and its
   parallax travel under rotation grows with z. Those are linked, so a big pop
   normally means a badly oversized Steve. Raising the perspective breaks the
   tie: at 1600px, z=140 gives 1600/1460 = 1.096, trimmed by scale(.97) to about
   6% — enough that he reads as nearer than the frame, while z=140 carries real
   parallax travel when the card turns.

   He must never end up SMALLER than the silhouette inpainted out of the back
   layer, or the smeared patch behind him shows at the edges. Sitting proud is
   the safe direction as well as the right-looking one. */
.stage { width: min(90vw, 470px); aspect-ratio: 1792 / 2400; position: relative; perspective: 1600px; margin: 0 auto; }
.card3d { position: absolute; inset: 0; transform-style: preserve-3d; will-change: transform; }
/* No CSS transition here on purpose: app.js eases the angle itself in a frame
   loop. Smoothing an already-smoothed value reads as lag, not weight. */
.layer { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; pointer-events: none; user-select: none; }
.layer.back  { transform: translateZ(0); }
.layer.steve {
  transform: translateZ(140px) scale(0.97);
  filter: drop-shadow(0 18px 22px rgba(28, 20, 12, .42))
          drop-shadow(0 3px 5px rgba(28, 20, 12, .30));
}
.portrait-flat { display: none; }
@media (prefers-reduced-motion: reduce) {
  .stage .card3d { display: none; }
  .portrait-flat { display: block; width: min(90vw, 470px); margin: 0 auto; }
}

/* ---- seasonal banner ---- */
.season-banner { background: var(--navy); color: #fff; text-align: center; padding: .7rem 1rem; font-weight: 600; }
.season-banner a { color: var(--brass); }

/* ---- generic section ---- */
section.block { padding: 2.4rem 0; }
section.block h2 { font-size: clamp(1.5rem, 3.5vw, 2.1rem); margin: 0 0 1rem; }
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1rem; }
.cardish { background: var(--paper); border: 1px solid var(--line); border-radius: 14px; padding: 1.2rem; box-shadow: 0 6px 18px var(--shadow); }

/* ---- philanthropy teaser ---- */
.giving { background: color-mix(in srgb, var(--brass) 14%, var(--cream)); border-radius: 16px; padding: 1.8rem; display: flex; gap: 1.2rem; align-items: center; justify-content: space-between; flex-wrap: wrap; }

/* ---- footer ---- */
.site-footer { border-top: 1px solid var(--line); margin-top: 2rem; padding: 2rem 0; color: var(--gray); }
.foot-grid { display: flex; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap; align-items: center; }
.foot-boss { display: flex; align-items: center; gap: .6rem; font-family: var(--serif); }

/* ---- owner gate page ---- */
body.gate { display: grid; place-items: center; min-height: 100vh; padding: 1rem; }
.gate-card { max-width: 460px; background: var(--paper); border: 1px solid var(--line); border-radius: 16px; padding: 2rem; box-shadow: 0 10px 30px var(--shadow); text-align: center; }
.gate-card h1 { margin-top: 0; }
.gate-card .btn { margin-top: 1rem; }

/* ---- simple page header for interior stub pages ---- */
.page-hero { padding: 2.4rem 0 1rem; }
.page-hero h1 { font-size: clamp(1.8rem, 4vw, 2.6rem); margin: 0 0 .3rem; }
.soon { display: inline-block; margin-top: .4rem; padding: .3rem .7rem; border-radius: 999px; background: color-mix(in srgb, var(--brass) 22%, transparent); color: var(--on-tint); font-weight: 600; font-size: .85rem; }

/* ---- services page ---- */
.svc-tools { display:flex; align-items:center; gap:1rem; flex-wrap:wrap; margin:.8rem 0 .4rem; }
#svc-search { flex:1; min-width:240px; padding:.7rem .9rem; border:1px solid var(--line); border-radius:10px; background:var(--paper); color:var(--ink); font-size:1rem; }
.svc-catnav { display:flex; flex-wrap:wrap; gap:.4rem; margin:.6rem 0 0; }
.svc-catnav a { font-size:.82rem; padding:.28rem .6rem; border-radius:999px; background:color-mix(in srgb, var(--brass) 16%, transparent); color:var(--on-tint); text-decoration:none; }
.svc-catnav a:hover { background:color-mix(in srgb, var(--brass) 30%, transparent); }
.svc-cat { margin:1.8rem 0 0; scroll-margin-top:80px; }
.svc-cat h2 { font-size:1.3rem; margin:0 0 .7rem; padding-bottom:.3rem; border-bottom:2px solid color-mix(in srgb, var(--brass) 40%, transparent); }
.svc-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(240px,1fr)); gap:.7rem; }
.svc-tile { text-align:left; background:var(--paper); border:1px solid var(--line); border-radius:12px; padding:.9rem 1rem; cursor:pointer; display:flex; flex-direction:column; gap:.25rem; transition:transform .08s ease, border-color .15s ease; font-family:inherit; }
.svc-tile:hover { transform:translateY(-2px); border-color:var(--brass); }
.svc-name { font-weight:600; color:var(--ink); font-size:1rem; }
.svc-price { color:var(--navy); font-weight:700; }
.svc-more { color:var(--gray); font-size:.82rem; }
.modal { position:fixed; inset:0; background:rgba(20,15,10,.55); display:grid; place-items:center; padding:1rem; z-index:100; }
.modal[hidden]{ display:none; }
.modal-card { background:var(--paper); border:1px solid var(--line); border-radius:16px; max-width:520px; width:100%; padding:1.6rem; box-shadow:0 20px 50px var(--shadow); position:relative; max-height:88vh; overflow:auto; }
.modal-x { position:absolute; top:.7rem; right:.9rem; background:none; border:0; font-size:1.7rem; line-height:1; color:var(--gray); cursor:pointer; }
.modal-cat { display:inline-block; font-size:.78rem; font-weight:700; text-transform:uppercase; letter-spacing:.04em; color:var(--brass); }
.modal-card h2 { margin:.2rem 0 .4rem; }
.modal-steps { margin:.2rem 0 1.1rem; padding-left:1.2rem; }
.modal-steps li { margin:.3rem 0; }

/* ---- print styles ---- */
@media print {
  body { background: white; color: black; }
  .site-header, .site-footer, .btn, .nav-toggle, .modal, [data-print-hide] { display: none !important; }
  a { text-decoration: underline; }
  h1, h2, h3 { page-break-after: avoid; }
  table { border-collapse: collapse; width: 100%; }
  th, td { border: 1px solid #ccc; padding: 8px; text-align: left; }
  th { background: #f5f5f5; font-weight: 700; }
  .invoice, .day-sheet, .report { page-break-inside: avoid; margin-bottom: 2rem; }
  .no-print { display: none; }
  img { max-width: 100%; page-break-inside: avoid; }
}

/* ---- service-area ring legend ----
   The bullet colour IS the data: it matches the ring drawn on the map, so
   someone can look at the map, look at the list, and pair them without reading.
   Colour alone never carries the meaning though — every row states its mileage
   and its price in text, for colour-blind readers and for anyone printing it. */
.ring-list { list-style: none; padding: 0; margin: .8rem 0 0; }
.ring-list li {
  display: grid; grid-template-columns: 22px 1fr auto; gap: .8rem; align-items: center;
  padding: .7rem .9rem; border: 1px solid var(--line); border-radius: 10px;
  background: var(--paper); margin-bottom: .5rem;
}
.ring-list .dot-ring {
  width: 18px; height: 18px; border-radius: 50%;
  border: 3px solid currentColor; background: color-mix(in srgb, currentColor 22%, transparent);
}
.ring-list .ring-what { font-weight: 600; }
.ring-list .ring-miles { display: block; color: var(--gray); font-size: .88rem; font-weight: 400; }
.ring-list .ring-fee { font-weight: 700; font-size: 1.05rem; white-space: nowrap; }
.ring-list .ring-fee small { display: block; font-weight: 400; font-size: .75rem; color: var(--gray); text-align: right; }
.ring-list li.is-yours { outline: 2px solid var(--navy); outline-offset: 1px; }
@media (max-width: 520px) {
  .ring-list li { grid-template-columns: 22px 1fr; }
  .ring-list .ring-fee { grid-column: 2; text-align: left; }
  .ring-list .ring-fee small { text-align: left; }
}

/* Staff entrance. Deliberately quiet — it is for Steve and his crew, not a
   call to action for customers — but not hidden, because hiding it would only
   mean Steve has to remember a URL. */
.nav-links a.admin-link {
  font-size: .86rem; color: var(--gray); border: 1px solid var(--line);
  padding: .35rem .7rem; border-radius: 8px;
}
.nav-links a.admin-link:hover { color: var(--navy); border-color: var(--navy); }


/* ---- Owner's Area sidebar ----
   Injected by /owner/nav.js on every page under /owner/, so the menu is present
   whether you are on the shell or on the dashboard. It is FIXED rather than part
   of each page's own layout: these pages were each written with their own
   container, and a fixed rail plus body padding is the one approach that sits on
   top of all of them without rewriting any. */
.owner-nav {
  position: fixed; inset: 0 auto 0 0; width: 230px; z-index: 60;
  background: var(--paper); border-right: 1px solid var(--line);
  padding: 1rem .6rem; overflow-y: auto;
}
body.has-owner-nav { padding-left: 230px; }
.owner-nav .brand {
  display: flex; align-items: center; gap: .5rem; padding: .4rem .6rem 1rem;
  font-family: var(--serif); font-weight: 700; font-size: 1rem;
  color: var(--ink); text-decoration: none;
}
.owner-nav a, .owner-nav button.navlink {
  display: block; width: 100%; text-align: left; padding: .6rem .7rem;
  border-radius: 9px; text-decoration: none; color: var(--ink); font-weight: 500;
  border: 0; background: none; font: inherit; cursor: pointer;
}
.owner-nav a:hover, .owner-nav button.navlink:hover,
.owner-nav a.active, .owner-nav button.navlink.active {
  background: color-mix(in srgb, var(--brass) 18%, transparent);
}
.owner-nav .sect {
  font-size: .72rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--gray); padding: 1rem .7rem .3rem; font-weight: 700;
}
.owner-nav .owner-nav-foot { margin-top: 1.2rem; color: var(--gray); }

/* On a phone the rail becomes a strip across the top — still always present,
   just not eating half the screen. */
@media (max-width: 760px) {
  .owner-nav {
    position: static; width: auto; inset: auto; border-right: 0;
    border-bottom: 1px solid var(--line);
    display: flex; flex-wrap: wrap; gap: .3rem; align-items: center;
  }
  body.has-owner-nav { padding-left: 0; }
  .owner-nav .brand, .owner-nav .sect { width: 100%; padding-bottom: .3rem; }
  .owner-nav a, .owner-nav button.navlink { width: auto; }
  .owner-nav .owner-nav-foot { margin-top: 0; }
}

/* ---- My Work / Forum ----
   These two pages used to carry their own hardcoded palette (a navy gradient
   banner, #F4EFE6 literals, a nav that had gone stale) so they read as a
   different website. They now use the same tokens as everything else, which
   also means they follow the theme instead of fighting it. */
.work-filters { display: flex; flex-wrap: wrap; gap: .5rem; margin: 0 0 1.4rem; }
.filter-btn {
  border: 1px solid var(--line); background: var(--paper); color: var(--ink);
  padding: .45rem .9rem; border-radius: 999px; cursor: pointer;
  font: inherit; font-size: .92rem; font-weight: 600;
}
.filter-btn:hover { border-color: var(--brass); }
.filter-btn.active { background: var(--navy); color: #fff; border-color: var(--navy); }

.work-grid {
  display: grid; gap: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
.work-card {
  background: var(--paper); border: 1px solid var(--line); border-radius: 12px;
  overflow: hidden; box-shadow: 0 1px 2px var(--shadow);
  display: flex; flex-direction: column;
}
.work-card img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; background: var(--cream); }
.work-card .body { padding: .8rem .9rem 1rem; }
.work-card h3 { margin: 0 0 .25rem; font-size: 1.05rem; }
.work-card .meta { color: var(--gray); font-size: .88rem; }
.work-card .tag {
  display: inline-block; margin-top: .5rem; padding: .15rem .6rem; border-radius: 999px;
  font-size: .75rem; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
  background: color-mix(in srgb, var(--brass) 25%, transparent); color: var(--on-tint);
}
.work-card .tag.giving { background: color-mix(in srgb, #2e9e57 22%, transparent); color: #1f5c35; }

.forum-cats { display: grid; gap: .8rem; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.forum-cats a, .forum-recent a { text-decoration: none; color: inherit; }
.forum-cat, .forum-post {
  display: block; background: var(--paper); border: 1px solid var(--line);
  border-radius: 12px; padding: .9rem 1rem; box-shadow: 0 1px 2px var(--shadow);
}
.forum-cat:hover, .forum-post:hover { border-color: var(--brass); }
.forum-cat h3, .forum-post h3 { margin: 0 0 .2rem; font-size: 1.05rem; }
.forum-cat .meta, .forum-post .meta { color: var(--gray); font-size: .88rem; }
.forum-recent { display: grid; gap: .6rem; }

/* Owner's Area form fields — used by the project editor. */
.fld { display: block; font-weight: 600; font-size: .9rem; margin: .8rem 0 0; }
.fld input[type=text], .fld textarea, .fld select {
  display: block; width: 100%; margin-top: .25rem; padding: .55rem .7rem;
  border: 1px solid var(--line); border-radius: 8px; font: inherit;
  background: var(--cream); color: var(--ink);
}
.chk { display: flex; align-items: center; gap: .5rem; margin: .8rem 0 0; font-weight: 500; }
.chk input { width: 18px; height: 18px; }
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1rem; }
@media (max-width: 640px) { .grid2 { grid-template-columns: 1fr; } }

/* ---- the "What's been built" inventory ----
   Jesse's figures only, plus whether a line is still an estimate and the date
   it was closed. A table across the full width — an earlier version stacked
   tall cards down the middle and wasted the whole right of the screen. */
.bt-table { width: 100%; border-collapse: collapse; }
.bt-table th, .bt-table td { padding: .55rem .6rem; vertical-align: top;
                             border-top: 1px solid var(--line); text-align: left; }
.bt-table thead th { border-top: 0; padding-bottom: .2rem; font-size: .68rem;
                     font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
                     color: var(--gray); }
.bt-table thead th.bt-h { text-align: center; }
.bt-table tbody tr:first-child th, .bt-table tbody tr:first-child td { border-top: 1px solid var(--line); }
.bt-table th[scope="row"] { width: 17rem; font-weight: 700; font-size: .98rem; line-height: 1.35; }
.bt-table th[scope="row"] .pill { display: table; margin-top: .3rem; }
.bt-what { color: var(--gray); font-size: .92rem; line-height: 1.45; }
.bt-num { width: 7rem; }
.bt-cell, .bt-est-cell, .bt-closed-cell { text-align: center; }
.bt-est-cell { width: 8rem; }
.bt-closed-cell { width: 10rem; }
.bt-busy { opacity: .5; }
/* A closed line is settled work — dimmed so the open ones stand out. */
.bt-done th[scope="row"], .bt-done .bt-what { opacity: .62; }

.bt-edit { width: 100%; text-align: center; padding: .3rem .5rem;
           border: 1px dashed var(--brass); border-radius: 8px; background: transparent;
           color: var(--brass-text); font: inherit; font-weight: 700; cursor: pointer; }
.bt-edit.set { border-style: solid; color: var(--on-tint);
               background: color-mix(in srgb, var(--brass) 18%, transparent); }
.bt-edit:hover { border-color: var(--navy); }
.bt-input { width: 100%; padding: .3rem .4rem; border: 1px solid var(--brass);
            border-radius: 8px; font: inherit; text-align: right;
            background: var(--paper); color: var(--ink); }
.bt-check { display: inline-flex; align-items: center; gap: .35rem; cursor: pointer;
            font-size: .82rem; font-weight: 600; color: var(--gray); }
.bt-check input { width: 1rem; height: 1rem; accent-color: var(--brass); cursor: pointer; }
.bt-check input:disabled { cursor: not-allowed; }
.bt-check input:disabled + span { opacity: .4; }
.bt-date { width: 100%; padding: .28rem .4rem; border: 1px solid var(--line);
           border-radius: 8px; font: inherit; font-size: .88rem;
           background: var(--cream); color: var(--ink); }
.bt-date:hover { border-color: var(--brass); }

.bt-totals { display: flex; gap: 2.5rem; flex-wrap: wrap; margin: 0 0 .9rem; }
.bt-big { font-family: var(--serif); font-weight: 700; font-size: 2rem; line-height: 1.1; }
.bt-jesse { color: var(--brass-text); }
.bt-saved { color: var(--good); }

/* Jesse's note against a line. Sits under the description because it is his
   commentary on the same thing, not a separate column to scan. */
.bt-note-cell { margin-top: .4rem; }
.bt-note { font-size: .88rem; color: var(--ink);
           background: color-mix(in srgb, var(--navy) 7%, transparent);
           border-left: 3px solid var(--navy); border-radius: 0 6px 6px 0;
           padding: .35rem .6rem; white-space: pre-wrap; }
.bt-note-edit { border: 0; background: none; padding: 0 .2rem; cursor: pointer;
                font: inherit; font-size: .78rem; font-weight: 600; color: var(--navy);
                text-decoration: underline; }
.bt-note-add { font-size: .8rem; color: var(--gray); text-decoration: none;
               border: 1px dashed var(--line); border-radius: 6px; padding: .15rem .5rem; }
.bt-note-add:hover { border-color: var(--brass); color: var(--brass-text); }
.bt-note-box { width: 100%; padding: .4rem .5rem; border: 1px solid var(--brass);
               border-radius: 8px; font: inherit; font-size: .9rem; resize: vertical;
               background: var(--paper); color: var(--ink); }

/* What is actually missing, said plainly rather than hidden. */
.bt-block { margin-top: .4rem; font-size: .86rem; color: var(--on-tint);
            background: color-mix(in srgb, var(--brass) 14%, transparent);
            border-left: 3px solid var(--brass); border-radius: 0 6px 6px 0; padding: .4rem .6rem; }

@media (max-width: 900px) {
  .bt-table thead { display: none; }
  .bt-table, .bt-table tbody, .bt-table tr, .bt-table th, .bt-table td { display: block; width: auto; }
  .bt-table tr { border-top: 1px solid var(--line); padding: .5rem 0; }
  .bt-table th, .bt-table td { border-top: 0; padding: .15rem 0; }
  .bt-cell, .bt-est-cell, .bt-closed-cell { display: inline-block; text-align: left;
                                            margin: .35rem 1rem .1rem 0; width: auto; min-width: 7rem; }
  .bt-totals { gap: 1.4rem; }
}

/* ---------- "who am I signed in as" chip ---------- */

/* Fixed top-right on every page. Steve and Jesse should never have to wonder
   whether the private area is actually private — the answer is on screen. */
.whoami { position: fixed; top: .6rem; right: .7rem; z-index: 90; }
.who-chip {
  display: flex; align-items: center; gap: .5rem;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: 999px; padding: .3rem .7rem .3rem .35rem;
  box-shadow: 0 1px 6px var(--shadow); font-size: .82rem; max-width: 62vw;
}
.who-chip.out { padding-left: .7rem; color: var(--gray); }
.who-dot { width: .5rem; height: .5rem; border-radius: 50%; background: var(--gray); flex: none; }
.who-av {
  width: 1.7rem; height: 1.7rem; border-radius: 50%; flex: none;
  background: var(--navy); color: #fff; font-weight: 700; font-size: .7rem;
  display: flex; align-items: center; justify-content: center;
}
.who-chip.owner .who-av { background: var(--brass); color: var(--walnut); }
.who-txt { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; }
.who-txt b { font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.who-role { font-size: .72rem; color: var(--gray); }
.who-warn { color: var(--alert); font-weight: 700; }
@media (max-width: 700px) {
  /* On a phone the name would eat the header; the avatar still says who. */
  .whoami { top: .4rem; right: .4rem; }
  .who-txt { display: none; }
  .who-chip { padding: .25rem; }
  .who-chip.out .who-txt { display: block; font-size: .72rem; }
}
@media print { .whoami { display: none !important; } }

/* ---------- sidebar: lock + drag ---------- */

/* The padlock is the whole control. Locked it is a quiet icon; unlocked it
   turns brass and the hint appears beside it. No Save, no Cancel — drops save
   themselves and Ctrl+Z is the undo everyone already knows. */
.navlock { display: flex; align-items: center; gap: .45rem; padding: .3rem .55rem .25rem; }
.navlock button#lockbtn {
  background: none; border: 0; cursor: pointer; font-size: .95rem;
  line-height: 1; padding: .2rem .25rem; border-radius: 6px; opacity: .55;
}
.navlock button#lockbtn:hover { opacity: 1; background: rgba(214,168,72,.15); }
.navlock.open button#lockbtn { opacity: 1; background: rgba(214,168,72,.22); }
.lockhint { font-size: .7rem; color: var(--gray); line-height: 1.3; }
.lockhint b { color: var(--brass-text); }
#menumsg { color: var(--brass-text); }

#navrows { position: relative; }

/* A row is one line. Nothing is added to it unless it earns the space: only a
   parent gets a triangle. An earlier build put a drag grip on every row and
   the menu grew past the height of the screen. */
.navrow { position: relative; display: flex; align-items: center; gap: .1rem; }
.navrow.d1 { padding-left: .85rem; }
.navrow.tucked { display: none; }

.navrow .tri {
  background: none; border: 0; cursor: pointer; color: var(--gray);
  font-size: .6rem; line-height: 1; padding: .2rem .15rem;
  transition: transform .12s ease; flex: none;
}
.navrow .tri.open { transform: rotate(90deg); }
.navrow .tri:hover { color: var(--brass-text); }
/* Headings sit flush whether or not they have a triangle, so the left edge
   stays straight down the menu. */
.navrow.ishead:not(.haskids) { padding-left: .95rem; }
.navrow:not(.ishead):not(.haskids).d0 { padding-left: .95rem; }

/* Unlocked, the whole row is the handle — no extra grip, no extra height. */
.owner-nav .navlock.open ~ #navrows .navrow { cursor: grab; touch-action: none; }
.owner-nav .navlock.open ~ #navrows .navrow:hover { background: rgba(214,168,72,.10); }
.owner-nav .navlock.open ~ #navrows .navrow .tri { cursor: pointer; }
.navrow.dragging { opacity: .7; z-index: 5; cursor: grabbing; }

.dropmark {
  position: absolute; left: 0; right: .4rem; height: 2px;
  background: var(--brass); border-radius: 2px; pointer-events: none;
}
.dropmark::before {
  content: ""; position: absolute; left: -3px; top: -3px;
  width: 8px; height: 8px; border-radius: 50%; background: var(--brass);
}
