/* ============================================================================
   assets/rccs.css — the shared core. Rev 202.

   WHAT THIS FILE IS, AND WHAT CHANGED
   -----------------------------------
   It used to open with "THIS FILE IS THE SOURCE OF TRUTH FOR THE LIVE SITE'S
   STYLING". That was not true and had not been for about 120 revisions. No page
   linked it, amplify.yml never copied it, and the browser had never seen it. It
   was a snapshot extracted from rim-country-mockup.html at Rev 84: of its 272
   selectors, 86 appeared in no page at all and 46 were actively contradicted by
   one. Its --colmax said 1120px while the pages ran six different widths.

   A file that claims authority nothing grants it is worse than no file, because
   edits get made here in the belief they will show up on the site.

   So this is now the real thing: every page LINKS it, amplify.yml ships it, and
   its contents were derived by measuring what the fifteen pages actually agree
   on rather than by asserting what they ought to.

   THE CONTRACT
   ------------
   Load order on every page is: this file, then the page's own <style>. So the
   page always wins. That is deliberate — it means adding this file could not
   change how anything renders, and any page that genuinely differs keeps its
   difference as a visible inline override instead of an invisible divergence.

   WHAT LIVES HERE
   ---------------
   * the design tokens — change a colour here and it changes everywhere
   * component rules that EVERY page defining them already defines identically,
     and that no page lacking them could accidentally start matching

   WHAT DELIBERATELY DOES NOT
   --------------------------
   * --colmax and --colpad. The body column is per page by design (Rev 179
     measured six real widths: 1180/1080/880/860/760/620). Hoisting them would
     re-break the alignment that work fixed.
   * rules the pages disagree on. h1 has 11 variants across 14 pages; .masthead
     5; footer 6. Those are real differences and reconciling them is a visual
     judgement that needs a browser, not a text edit. They stay inline until
     somebody looks at them.

   Held by tests/test_css_core.py, which proves every page's effective value for
   every token is unchanged from before this file existed.
   ============================================================================ */

:root{
  /* --- Colour --- */
  --cream         : #fefbec;
  --card          : #fffdf3;
  --ink           : #4a402a;
  --brown         : #4a402a;
  --brown-header  : #342b19;
  --brown-darkest : #322b1b;
  --teal          : #5f7c7a;
  --teal-dark     : #4a6462;
  --teal-d        : #4a6462;
  --juniper       : #55705b;
  --pine          : #4f6e45;
  --sage          : #8b8063;
  --sand          : #d7d0b8;
  --sand-lt       : #efe9d6;
  --sand-band     : #e6dec5;
  /* Alias, restored Rev 215. The Rev 203 extraction took the majority
     LITERAL and dropped the indirection, which is the one thing the
     alias exists to prevent: change --sand and --gold must follow. */
  --gold          : var(--sand);
  --accent        : var(--sand);
  --hairline      : #cfc5a8;
  /* Rev 205: the folio inverted — dark grey ground, cream type. It was cream
     ground with black serif type, a newspaper masthead convention. --grey-folio
     already held this exact grey and was the only dark folio value in the
     system, so the band now uses it rather than introducing a fourth grey. */
  --folio         : #3a3a38;
  --folio-text    : #fefbec;
  --grey-folio    : #3a3a38;
  /* The footer is black, not the #34302A brown it shared with the nav. Given
     its own token so darkening the footer can never darken the nav by accident,
     which is what reusing --nav here would have set up. */
  --footer        : #000000;
  --footer-text   : #fefbec;
  --nav           : #34302a;
  --navedge       : #5f7c7a;
  --masthead      : var(--teal);
  --amber-bg      : #f5ebd6;
  --good          : #4e7c4e;
  --warn          : #b07a22;
  --bad           : #9a4a3a;
  --crimson       : #6e1f1f;
  --terra         : #bc5a28;
  /* Rev 348: TURQUOISE, ADDED RATHER THAN BORROWED — and the borrow was tried
     first. The system already holds #6F9C99, "lightened Heritage Teal", as the
     News department accent, and it is the nearest thing to turquoise here. It
     cannot carry cream text: #FEFBEC on #6F9C99 is 2.93:1, below the 3.0 floor
     tests/test_contrast.py enforces and nowhere near AA's 4.5. It works on the
     dark #161511 sidebar it was drawn for and fails as a button.
     #2E7D77 is that hue taken down until cream reads at 4.69:1. It is the
     affiliate rail's colour and nothing else's — the role accents below carry
     the role of whoever ACTS, and Amazon is not a role of ours. */
  --turquoise     : #2e7d77;
  --turquoise-d   : #26706b;
  --btn           : var(--teal);
  --btn-hover     : var(--teal-dark);

  /* --- Type --- */
  --display   : "alfa slab one",georgia,serif;
  --body      : "atkinson hyperlegible",system-ui,sans-serif;
  --label     : "oswald",system-ui,sans-serif;
  --navfont   : 'oswald',sans-serif;
  --foliofont : 'times new roman', times, georgia, serif;
  --t-micro   : 11px;
  --t-caption : 13px;
  --t-small   : 15px;
  --t-ui      : 17px;
  --t-body    : 19px;
  --t-card    : 24px;
  --t-section : 34px;
  --t-display : 48px;

  /* --- Spacing --- */
  --s1 : 4px;
  --s2 : 8px;
  --s3 : 12px;
  --s4 : 16px;
  --s5 : 24px;
  --s6 : 32px;
  --s7 : 48px;

  /* --- Radii --- */
  --r-sm   : 6px;
  --r-md   : 12px;
  --r-pill : 999px;

}

/* --- Shared components -------------------------------------------------
   Every page that defines these defines them identically. Listed once so
   they cannot drift apart again. A page needing something different
   overrides it in its own <style>, where the difference is visible. */
.ic{width:1em;height:1em;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;vertical-align:middle;}
.ic-fill{fill:currentColor;stroke:none;}
img{max-width:100%;display:block;}
.mastslot{display:flex;align-items:center;gap:8px;}

/* Cart chip — masthead, right slot (Rev 211).
   Was a fixed bar pinned to the bottom of the viewport on three pages. Moved up
   because that is where a shopper looks for a cart, and because a fixed bottom
   bar covers page content on a phone exactly when the list is longest.
   Defined here once: identical on index, product and vendor, and the core
   exists so those three cannot drift apart again.
   Sized to sit beside .navauth without changing the masthead's height. */
/* Rev 337: the chip is a WRAPPER holding a link and a clear button, not an
   anchor. Interactive content cannot nest inside an anchor, so emptying the
   basket from the chip needed the outer element to stop being one. The total
   is gone: it could only be computed on pages that already carry the 48KB
   catalogue, which is what made this control a different size on nine pages. */
.cartchip{display:inline-flex;align-items:stretch;text-decoration:none;
  background:var(--btn);color:var(--cream);border:1px solid rgba(254,251,236,.4);
  border-radius:12px;font-family:'Oswald',sans-serif;font-weight:600;
  letter-spacing:.08em;font-size:13px;height:44px;overflow:hidden;
  white-space:nowrap;}
.cartchip .cartlink{display:inline-flex;align-items:center;gap:8px;
  color:inherit;text-decoration:none;padding:4px 12px;}
.cartchip .cartlink:hover{background:var(--btn-hover);}
.cartchip .ic{width:19px;height:19px;flex:none;}
/* The count is the thing a shopper checks at a glance, so it is the one part
   that reads as a number rather than as label text. */
.cartchip .cartqty{font-size:17px;line-height:1;}
/* The clear button. Divided from the link by a hairline so the destructive
   half is visibly a separate control rather than more of the same button, and
   36px wide so it clears WCAG 2.5.8's 24px target without crowding the count. */
.cartchip .cartclear{display:inline-flex;align-items:center;justify-content:center;
  min-width:36px;padding:0 8px;background:none;color:inherit;cursor:pointer;
  border:0;border-left:1px solid rgba(254,251,236,.4);
  font-family:'Oswald',sans-serif;font-weight:600;font-size:18px;line-height:1;}
.cartchip .cartclear:hover{background:var(--btn-hover);}
/* Armed: the chip is asking before it throws somebody's shopping away, so it
   takes the system's destructive colour rather than staying the same button
   it was a moment ago. */
/* Rev 387: the chip is a FIXTURE — always present, the badge carries the
   state. The qty span and the clear button are display:flex, which beats
   the [hidden] attribute unless said explicitly (the same lesson as
   .cartchip[hidden] below it). .bare is the empty posture: basket alone. */
.cartchip .cartqty[hidden],.cartchip .cartclear[hidden]{display:none;}
.cartchip.armed{background:#9A4A3A;}
.cartchip.armed .cartqty{font-size:13px;letter-spacing:.08em;}
.cartchip.armed .cartlink:hover,.cartchip.armed .cartclear:hover{background:#833D30;}
/* Hidden until there is something in it. `hidden` alone loses to the flex
   display above, which is the oldest trap with the hidden attribute. */
.cartchip[hidden]{display:none;}
.mastslot.left{grid-column:1;justify-self:start;}
.mastslot.right{grid-column:3;justify-self:end;}
.btn.gold{color:var(--cream);border:1px solid var(--gold);}
.pill.good{background:#E4EDE0;color:var(--good);border:1px solid var(--good);}
.pill.teal{background:#E4ECEB;color:var(--teal-dark);border:1px solid var(--teal);}
.btn.danger{background:#9A4A3A;}
.btn.danger:hover{background:#833D30;}
.btn.partner{background:#4F6E45;}
.btn.partner:hover{background:#42603A;}
.btn.worker{background:#BC5A28;}
.btn.worker:hover{background:#A44D20;}
/* Rev 348: outbound affiliate. Not a role accent — see --turquoise. */
.btn.amazon{background:var(--turquoise);}
.btn.amazon:hover{background:var(--turquoise-d);}
.demonote{display:none;font-family:'Oswald',sans-serif;font-weight:600;letter-spacing:.08em;text-transform:uppercase;font-size:13px;color:var(--teal-dark);background:#E4ECEB;border:1px solid var(--teal);border-radius:6px;padding:4px 12px;margin-top:8px;}
.demonote.show{display:inline-block;}
.page{display:none;max-width:var(--colmax);margin:0 auto;padding:32px var(--colpad) 48px;}
.page.active{display:block;}
.pname{font-weight:700;font-size:19px;}
.price{font-family:'Alfa Slab One',serif;font-size:24px;color:var(--brown);}
.cartbar.show{display:flex;}
.cartbtn svg{width:22px;height:22px;margin-right:8px;color:var(--cream);}
.crumbs{font-family:'Oswald',sans-serif;font-weight:500;letter-spacing:.08em;font-size:15px;text-transform:uppercase;color:#6B5F42;margin-bottom:16px;}
.crumbs b{color:var(--brown);}
.view{display:none;}
.view.active{display:block;}

/* ---------- Join band (moved out of index.html at Rev 263) ----------
   These lived inline in index.html while index.html was the only page with a
   Join band. Rev 263 puts a Become a Verifier button on vehicles.html, which
   links this stylesheet and nothing else — so the rules had to be here or be
   copied, and a copied rule is a rule that drifts. This is what rccs.css is
   for (Rev 202: shared core, every page links it). */
.reqwrap{text-align:center;padding:12px 0 4px;}
/* Rev 348: ONE HEIGHT, 44px, EVERYWHERE — and this reverses a Rev 198 decision
   on purpose rather than by accident. Rev 198 kept .reqbtn at 52px because
   "Request service" and "Browse all vehicles" are single primary CTAs, and
   introduced .small at 44 rather than shrinking the base. Joel's call at Rev
   348 is that a page reads better when every control is the same height than
   when the important one is taller — so the base comes down and .small now
   differs only in type size.

   HEIGHT, NOT MIN-HEIGHT, AND NO VERTICAL PADDING. The old rule paired
   min-height:52px with padding:16px — so the real height was whatever the type
   and padding summed to and the min-height rarely bound. A fixed height plus
   flex centring is the only arrangement that actually produces 44, and it
   cannot clip a label the way `max-height` over padding would: a long label
   pushes the box wider, which you can see, rather than being cut off, which
   you cannot. 44px is also the WCAG 2.5.5 target floor, so this is the
   smallest it may become, not a number chosen for looks. */
.reqbtn{
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--btn);color:var(--cream);border:2px solid var(--accent);border-radius:12px;
  font-family:'Oswald',sans-serif;font-weight:600;letter-spacing:.14em;font-size:19px;
  padding:16px 32px;height:44px;line-height:1;
}
.reqbtn:hover{filter:brightness(1.12);}
.reqbtn.small{font-size:15px;letter-spacing:.1em;padding:8px 16px;}

/* Rev 348: THE ROLE ACCENTS REACH THE JOIN BAND. They existed only on .btn,
   so the two buttons that ask somebody to become a Vendor or a Driver — the
   clearest role-carrying controls on the whole site — were both the default
   teal, which is the CUSTOMER accent. The design system's own rule is that a
   button carries the role of whoever acts; these were the exception nobody
   had noticed. Same hexes as .btn.partner and .btn.worker, deliberately not
   new values. */
.reqbtn.partner{background:#4F6E45;border-color:#4F6E45;}
.reqbtn.worker{background:#BC5A28;border-color:#BC5A28;}
.reqbtn.amazon{background:var(--turquoise);border-color:var(--turquoise);}
/* Rev 384 (Joel): List My Rental is black, no border, cream text. The border
   is PAINTED black rather than removed — visually identical (no border reads),
   but the 2px stays in the geometry so this button stands exactly as tall and
   as padded as its .partner/.worker siblings on the same row (Rev 348's
   one-height rule survives by construction, not by re-derivation). Cream text
   is .reqbtn's own color, inherited. Hover gets its own rule because the base
   brightness(1.12) filter is arithmetic on channel values — on #000 it
   multiplies zeros and the button plays dead; #34302A is the system's warm
   near-black (the nav's hex, borrowed as a literal the way .partner borrowed
   .btn.partner's). */
.reqbtn.owner{background:#000;border-color:#000;}
.reqbtn.owner:hover{filter:none;background:#34302A;}

/* Rev 386: THE OPEN-JOBS BOARD CARD — one compact shape, two pages (the
   Services section on index.html and the board on jobs.html), defined here
   because a copied card is a card that drifts (the Rev 263 rule). Joel's
   spec, verbatim: compact, cards, NO CHIPS, labels where needed (town),
   chronological. So: one flex row per job, type and window in the left
   column, pay on the right in plain ink — no pills, no colour blocks, no
   status paint. The TOWN is a plain small-caps LABEL in the muted label
   voice, not a chip: who-where-when-how-much is information, not
   decoration (the Rev 381 alert-card argument, applied to work). */
.oblist{display:grid;gap:8px;}
.obrow{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;
  background:var(--card,#FFFDF3);border:1px solid var(--hairline,#CFC5A8);
  border-radius:12px;padding:10px 14px;}
.obmain{min-width:0;}
.obtype{font-family:'Oswald',sans-serif;font-weight:600;font-size:16px;
  letter-spacing:.02em;color:var(--ink,#4A402A);}
.obtown{display:inline-block;font-family:'Oswald',sans-serif;font-weight:500;
  font-size:12px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--sage,#8B8063);margin-right:8px;}
.obwhen{font-size:14px;color:var(--ink,#4A402A);}
.obpay{font-family:'Oswald',sans-serif;font-weight:600;font-size:17px;
  color:var(--ink,#4A402A);white-space:nowrap;text-align:right;}
.obside{text-align:right;flex:none;}
.obnote{font-size:14px;color:var(--sage,#8B8063);margin-top:2px;}
.reqnote{font-size:17px;color:var(--brown);margin-top:8px;}
/* Rev 357: EQUAL WIDTH BY CONSTRUCTION, NOT BY A NUMBER THAT FITS TODAY.
   Joel: the two buttons at the top of Market and Services should be the same
   size and centred. Measured before changing anything: the pair was ALREADY
   centred on both pages — row centre 640 in a 1280 viewport, exactly the
   viewport centre — so only half the request was a real defect. What was
   wrong is width. The labels size the buttons, so Market read 184 / 177 and
   Services read 159 / 190, and a 31px mismatch beside a 12px gap is what the
   eye reads as "not centred" even when the pair is.

   THE OBVIOUS FIX IS A min-width AND IT IS THE WRONG ONE. A floor of 200px
   equalises today's four labels and silently stops the day somebody writes a
   longer one — that button grows past the floor, the pair mismatches again,
   and nothing fails. `grid-auto-columns:1fr` in a shrink-to-wrap grid makes
   every column the width of the WIDEST item, whatever the labels are, so the
   guarantee holds for text nobody has written yet. .reqbtn is inline-flex and
   blockifies as a grid item, which is what fills the column.

   inline-grid, not grid, so .reqwrap's own text-align:center still centres it —
   the centring that was already correct is left doing its job rather than
   replaced. justify-content is gone because a shrink-to-fit box has nothing
   left to distribute.

   REV 198'S WRAP IS KEPT, RESTATED. auto-flow:column cannot wrap, so the
   phone case moves to the same 560px breakpoint the rest of this stylesheet
   uses: one full-width column, which is better than the old wrap anyway — two
   buttons of different widths stacked was the mismatch made vertical. 12px
   between, 16px above, both still on the 4pt rhythm. */
.joinrow{display:inline-grid;grid-auto-flow:column;grid-auto-columns:1fr;
  gap:12px;margin-top:16px;}
@media (max-width:560px){
  .joinrow{display:grid;grid-auto-flow:row;grid-auto-columns:auto;}
}

/* ============================================================
   TABLE COMPONENT — Rev 360.
   =========================================================== */
/* WHY THIS EXISTS: `class="tbl"` WAS ALREADY BEING USED AND DEFINED NOWHERE.
   Six tables in the admin console carried it and it matched no rule in this
   file or in admin.html — so they rendered with the bare `table` defaults
   while eight OTHER tables, built inside JS template strings, carried a
   hardcoded `style="width:100%;border-collapse:collapse;font-size:15px;"`
   with `padding:6px 8px` on every cell. Three implementations, one of them
   imaginary. That is the whole reason the tables "look weak": several of them
   are, exactly, unstyled.

   A class somebody reaches for by instinct and that does nothing is worse
   than no class at all — it reads as applied styling in review, and it is
   the shape of the dead controls this project has had to delete twice.

   THE WRAPPER OWNS THE FRAME, THE TABLE OWNS THE GRID, and that split is
   forced rather than stylistic. Rounded corners need `overflow:hidden`, which
   CLIPS a sticky header the moment the body scrolls; and `border-collapse:
   collapse` — which is what makes row hairlines meet cleanly — hands border
   painting to the table, so a sticky cell scrolls away from its own border.
   So: `.tblwrap` carries the border, the radius and the scroll; `.tbl` carries
   collapse and the rules; and the header's bottom edge is a BOX-SHADOW, which
   travels with the sticky cell where a border does not.

   STICKY HEADERS ARE NOT DECORATION HERE. This console's tables are read by
   somebody reconciling money or QC across dozens of rows, and a column header
   that scrolls away turns every long table into a memory test. */
.tblwrap{overflow-x:auto;overflow-y:auto;background:var(--card);
  border:1px solid var(--hairline);border-radius:12px;}
.tblwrap.tall{max-height:60vh;}

.tbl{width:100%;border-collapse:collapse;background:transparent;border:0;}
.tbl thead th{position:sticky;top:0;z-index:2;
  background:var(--sand-band);color:var(--brown);
  font-family:'Oswald',sans-serif;font-weight:600;letter-spacing:.09em;
  text-transform:uppercase;font-size:13px;text-align:left;
  padding:12px;white-space:nowrap;box-shadow:inset 0 -1px 0 var(--sand);}
.tbl td{padding:12px;border-top:1px solid var(--sand);font-size:17px;
  vertical-align:middle;}
.tbl tbody tr:first-child td{border-top:0;}
.tbl tbody tr:nth-child(even) td{background:#F9F5E6;}

/* MONEY AND COUNTS RIGHT-ALIGN ON TABULAR FIGURES. Proportional digits put
   $1,240.00 and $940.00 at different widths, so a column of them cannot be
   compared by eye — which is the only reason to put numbers in a column. */
.tbl .num{text-align:right;font-variant-numeric:tabular-nums;
  font-feature-settings:'tnum' 1;}
.tbl th.num{text-align:right;}
.tbl .nowrap{white-space:nowrap;}
.tbl .mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:15px;}

/* THE EMPTY STATE IS PART OF THE COMPONENT, NOT AN AFTERTHOUGHT. Two tables
   in Members rendered `<table></table>` with no rows — a blank rectangle that
   is indistinguishable from a table that failed to load. Rev 286's rule: say
   which of the two it is, in words. */
/* VISUALLY HIDDEN — Rev 360. For a header that must exist for a screen reader
   and must not print. An action column with `<th></th>` is not "no header",
   it is an UNLABELLED one: a screen reader announces the column by position
   and the user is told nothing about what the buttons in it do. `left:-9999px`
   (the .skiplink trick) would work too, but it puts the text in the layout at
   a huge offset and can drag horizontal scroll into a table that already
   scrolls. Clipping leaves the box where it is and paints nothing. */
.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;}

.tbl td.empty{text-align:center;color:var(--brown);font-size:15px;
  padding:24px 12px;font-style:italic;}
.tbl tbody tr.emptyrow td{background:transparent;}
