/* ==========================================================================
   Bid Budi — design tokens
   The single source of truth for colour, type and spacing.
   Every value used anywhere in the UI must come from this file.
   If you find yourself writing a raw hex or px value in a template,
   the token is missing — add it here rather than inlining it.

   REBRANDED TWICE. This file first held a warm-neutral, square-cornered,
   serif-display palette described in kit/docs/UI.md as a case file rather than
   a marketplace. That was replaced by a violet-primary direction, and the
   violet has now been replaced in turn by the two colours in the logo — see
   UI.md §1, amended in the same change rather than left contradicting the code.

   The palette is no longer invented. Both accents are sampled from
   assets/img/logo.png, and app/Core/Mail/Html.php sampled the same two values
   independently months earlier: the mail has looked like the logo for a while
   and the website did not. It does now.

   The token NAMES are unchanged, which is why one edit to this file moves all
   ~1300 lines of app.css and all 98 views with it. Three of them now carry a
   colour their name no longer describes, and that is worth knowing:

     --bb-brass*  is the orange primary. Still "live / in progress /
                  attention", still the focus ring and the link colour. It was
                  brass, then violet, and is now the orange from the logo.
     --bb-verify* is teal rather than green.
     --bb-amber*  is a true gold rather than the burnt orange it used to be.
                  It had to move, and that is the one knock-on worth reading
                  the note on the wayfinding hues for.

   Renaming --bb-brass would have touched every file in the product for no
   visual gain, so the name stayed and this note exists instead. --lp-violet in
   landing.css WAS renamed, to --lp-brand, because that one cost eighteen lines
   and the word was about to become the name of a colour that is not there.
   ========================================================================== */

:root {

  /* --- Surfaces & ink ---------------------------------------------------
     ELECTRIC, chosen by the owner on 2026-09-29 from the mockup rounds. The
     neutrals lean violet: a lavender ground, indigo ink and deep indigo bars
     (the --bb-chrome* tokens below), with the logo orange unchanged on top.
     The ground used to be a warm near-white on the argument that a tinted one
     would fight the accents; the tint is now the point, and the orange reads
     louder against violet than it ever did against warm grey.

     --bb-surface-sunk is as dark as it can go and still carry --bb-brass-text
     at AA (4.53:1). Darkening it for looks fails every orange link on it. */
  --bb-paper:        #F4F2FB;  /* page ground, lavender */
  --bb-surface:      #FFFFFF;  /* cards, panels, sheets */
  --bb-surface-sunk: #F1EEFA;  /* inset panels, quiet callouts */
  --bb-placeholder:  #FBEDE3;  /* image placeholder fill */

  --bb-ink:          #140F2B;  /* primary text, dark bars */
  --bb-ink-body:     #3D3659;  /* body copy inside cards */
  --bb-ink-muted:    #5B5478;  /* secondary text */
  --bb-ink-faint:    #5E5779;  /* mono labels, metadata — 5.9:1 on sunk; do not lighten past 4.5 */
  --bb-ink-on-fill:  #9A3412;  /* text on --bb-placeholder */
  --bb-ink-on-dark:  #FFFFFF;  /* text on --bb-ink */
  --bb-ink-on-dark-muted: #ADA3DA;
  /* These two sit on --bb-brass-DEEP, not on --bb-brass. White on the primary
     orange measures 5.18:1, which is a pass and nothing more — there is no room
     left underneath it for a second, quieter tier. A ground that has to carry
     both body copy and a muted label needs the deep orange. */
  --bb-ink-on-brand: #FBDCC9;        /* body copy on a --bb-brass-deep fill */
  --bb-ink-on-brand-muted: #EFC2A4;  /* mono labels on a --bb-brass-deep fill */
  --bb-ink-on-amber: #3A2606;        /* text on any fill too light for white:
                                        --bb-brass-bright and --bb-amber-mid */

  --bb-line:         #E0DBF0;  /* default border */
  --bb-line-strong:  #CEC6E6;  /* card border */
  --bb-line-hair:    #EDEAF7;  /* internal dividers inside a card */
  --bb-line-dark:    #5B5288;  /* dividers on --bb-ink and the chrome */

  /* --- Accents ----------------------------------------------------------
     brass  = the primary. Live / in progress / attention, links, focus ring.
              The logo orange now; the token name is historical, see the header.
     verify = something has actually been verified (never decorative)
     alert  = time running out (never decorative)

     The verify/alert rule survives the rebrand intact, and it matters MORE
     now than it did: when green was the only colour on a neutral page it
     carried itself. On a page with five hues it cannot, so the verified badge
     also gained a border and a shield — three signals, not one. Never spend
     teal or red on decoration.

     THE ORANGE COMES IN THREE WEIGHTS AND THEY ARE NOT INTERCHANGEABLE. The
     logo's own #FD7102 cannot carry white text — 2.79:1 against a floor of
     4.5, which is not a near miss — and it cannot be a focus ring either,
     because 2.79 also misses the 3:1 that non-text contrast asks of one. So
     the bright value is a FILL ONLY, with --bb-ink-on-amber on it, and
     everything that has to be text or an outline uses --bb-brass. */
  --bb-brass:        #C2410C;  /* the working primary: fills under white text, focus ring */
  --bb-brass-text:   #C2410C;  /* primary used as text on a light ground (AA) */
  --bb-brass-on-ink: #FD9A4A;  /* primary used as text on --bb-ink (AA) */
  --bb-brass-soft:   #FEF1E8;
  --bb-brass-line:   #F7CFB2;
  --bb-brass-bright: #FD7102;  /* the logo orange, exactly. FILL ONLY — see above */
  --bb-brass-deep:   #7C2D12;  /* a brand ground with room for two tiers of text on it */

  --bb-verify:       #0B6E5F;
  --bb-verify-soft:  #E0F2EF;
  --bb-verify-line:  #A8D8CF;
  --bb-verify-text:  var(--bb-verify);

  /* Red rather than the coral it used to be. Coral was #C9331A, which sat one
     shade off the primary above — and this is the colour that has to mean a
     payment clock running out. An accent nobody can tell from the chrome is
     not an alert, so it moved to somewhere unmistakably red. */
  --bb-alert:        #B91C1C;
  --bb-alert-soft:   #FDEAEA;
  --bb-alert-line:   #F3BFBF;
  --bb-alert-track:  #F6DCDC;

  /* --- Wayfinding hues ---------------------------------------------------
     Category and audience colour, and nothing more. These carry no state and
     no meaning: they exist so a reader can tell one kind of thing from
     another at a glance. None of them may stand in for verify or alert. */
  --bb-amber:        #8A6100;  /* featured, and the facility side of the product. This value has
                                  moved twice for two different reasons. It was #B45309, darkened to
                                  #AD4F08 on 2026-09-03 because it measured 4.489:1 on --bb-amber-soft
                                  and missed WCAG AA by 0.011. It moved again on 2026-09-09, and that
                                  time contrast was not the problem: the primary became orange, and
                                  #AD4F08 IS orange, so "featured" and "live" became the same colour.
                                  A wayfinding hue that cannot be told from the chrome has stopped
                                  wayfinding. This is a true gold — the hue --bb-amber-mid was all
                                  along — at 5.54:1 on white and 4.95:1 on --bb-amber-soft. */
  --bb-amber-mid:    #E9A21B;  /* amber on a dark ground — dark text only */
  --bb-amber-soft:   #FDF1DA;
  --bb-blue:         #1D4ED8;
  --bb-blue-soft:    #E8EEFD;
  --bb-plum:         #9D1D66;
  --bb-plum-soft:    #FBEAF4;

  /* --- Type -------------------------------------------------------------
     Display for names and amounts. Sans for interface.
     Mono for EVERY fact that must be checkable: references, timestamps,
     hashes, ID numbers, amounts in tables. That rule survives the rebrand
     unchanged — it is the one piece of the original character kept on purpose.

     Instrument Serif is gone. Space Grotesk sets tighter and darker at the
     same size, so the ramp below did not need to move; --bb-track-display
     exists because a grotesque at display size needs negative tracking where
     the serif did not. */
  --bb-font-display: "Space Grotesk", ui-sans-serif, system-ui, sans-serif;
  --bb-font-ui:      "Instrument Sans", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --bb-font-mono:    "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --bb-size-display: 34px;
  --bb-size-amount:  30px;
  --bb-size-h1:      25px;
  --bb-size-h2:      17px;
  --bb-size-h3:      15px;
  --bb-size-body:    15px;
  --bb-size-small:   13px;
  --bb-size-fine:    12px;
  --bb-size-meta:    11px;   /* mono metadata */
  --bb-size-label:   10px;   /* mono eyebrow labels, uppercase */

  --bb-track-label:   0.12em; /* letter-spacing for mono eyebrow labels */
  --bb-track-display: -0.03em; /* the grotesque needs it; the old serif did not */
  --bb-leading-body: 1.55;

  /* --- Space ------------------------------------------------------------- */
  --bb-space-1: 4px;
  --bb-space-2: 8px;
  --bb-space-3: 12px;
  --bb-space-4: 16px;
  --bb-space-5: 20px;
  --bb-space-6: 26px;
  --bb-space-7: 34px;
  --bb-space-8: 44px;

  /* --- Structure ----------------------------------------------------------
     Corners are rounded now. The previous rule here forbade a radius token
     outright, on the argument that square corners were what stopped the
     product looking like every other marketplace. That was overruled
     deliberately, and the argument it rested on is answered by the accent
     discipline above rather than by the corners.

     Four steps, and no more. A radius that does not appear here is wrong. */
  --bb-radius-sm:   8px;    /* buttons, fields, chips, small tiles */
  --bb-radius-md:   12px;   /* icon plates, stat blocks, inset panels */
  --bb-radius-lg:   16px;   /* cards, sheets, the search panel */
  --bb-radius-pill: 999px;  /* status pills and category chips only */

  --bb-border:      1px solid var(--bb-line-strong);
  --bb-border-hair: 1px solid var(--bb-line-hair);
  --bb-border-ink:  1px solid var(--bb-ink);

  --bb-tap-min:     44px;  /* minimum touch target — enforce on every control */
  --bb-phone:       390px;
  --bb-content-max: 1360px;

  /* --- Elevation ----------------------------------------------------------
     A card is a sheet lying on a desk; a field is cut into the sheet; a
     selected control is pressed in. This used to end "there are no bevels, no
     gloss and no glows" — that was overruled on 2026-09-29, see Glass below.
     These shadows still do the lifting and pressing; glass.css adds the rest.

     Every shadow is mixed from the ink rather than from neutral black. Black
     greys the paper and kills the warmth the palette exists for, so the ink is
     published as channels here purely so rgba() can reach it. Nothing else may
     use --bb-ink-rgb.

     The hard contact edge the paper metaphor called for is gone with the square
     corners — on a rounded card it reads as a printing misregistration. What is
     left is a tight near-shadow and a wide soft one. */
  --bb-ink-rgb: 20, 15, 43;   /* = --bb-ink, for rgba() only */

  --bb-lift-1: 0 1px 2px rgba(var(--bb-ink-rgb), 0.05), 0 4px 10px rgba(var(--bb-ink-rgb), 0.04);
  --bb-lift-2: 0 2px 4px rgba(var(--bb-ink-rgb), 0.06), 0 10px 24px rgba(var(--bb-ink-rgb), 0.08);
  --bb-lift-3: 0 6px 14px rgba(var(--bb-ink-rgb), 0.08), 0 22px 48px rgba(var(--bb-ink-rgb), 0.12);

  /* Recessed: a form field cut into the page rather than sitting on it. */
  --bb-sink:  inset 0 1px 2px rgba(var(--bb-ink-rgb), 0.08);
  --bb-press: inset 0 2px 4px rgba(var(--bb-ink-rgb), 0.30);

  /* The top hairline that makes a dark bar read as raised rather than painted. */
  --bb-emboss: inset 0 1px 0 rgba(255, 255, 255, 0.10);

  --bb-rise:   1px;    /* how far a card travels when it lifts */

  /* --- Glass (2026-09-29) --------------------------------------------------
     The paper-depth rule above was overruled by the owner, who asked for the
     glass-and-depth look of the Ticketpro support console. What that means here
     is narrower than it sounds, and glass.css owns all of it:

       - cards and tiles are translucent white over a coloured wash, with a
         bright top edge; they do NOT use backdrop-filter, because a filter
         makes the card the containing block for anything position:fixed
         inside it;
       - the header and the tab bars are frosted (backdrop-filter), because
         content genuinely scrolls under them;
       - the primary button is bevelled, and tiles tilt under the pointer.

     The orange rule is untouched: --bb-brass-bright is still a fill only. These
     channel tokens exist so rgba() can reach the colours, which is the one way
     a hardcoded colour can hide from a hex grep. Nothing else may use them. */
  --bb-white-rgb:  255, 255, 255;
  --bb-brass-rgb:  194, 65, 12;    /* = --bb-brass */
  --bb-violet-rgb: 124, 58, 237;   /* the second glow in the page wash only */

  --bb-glass:      rgba(var(--bb-white-rgb), 0.74);
  --bb-glass-2:    rgba(var(--bb-white-rgb), 0.5);
  --bb-glass-line: rgba(var(--bb-white-rgb), 0.9);
  --bb-glass-bar:  rgba(var(--bb-white-rgb), 0.68);   /* the frosted header */
  --bb-shadow-glass: 0 10px 30px rgba(var(--bb-ink-rgb), 0.08), inset 0 1px 0 rgba(var(--bb-white-rgb), 0.6);
  --bb-shadow-pop:   0 24px 48px rgba(var(--bb-ink-rgb), 0.18);
  --bb-wash:
    radial-gradient(900px 600px at 88% -8%, rgba(var(--bb-brass-rgb), 0.16), transparent 60%),
    radial-gradient(700px 520px at 6% 108%, rgba(var(--bb-violet-rgb), 0.16), transparent 60%);

  /* The chrome: the console bar, the console pills and the footer. Deep indigo,
     lit from the top. White and --bb-chrome-text both clear 11:1 on it, and
     --bb-chrome-muted 5.2:1 on the lightest stop. */
  --bb-chrome-hi:    #34237A;
  --bb-chrome:       #1E1350;
  --bb-chrome-lo:    #0D0826;
  --bb-chrome-text:  #DAD3F6;
  --bb-chrome-muted: #A99FD6;
  --bb-chrome-accent: #FF7A1A;       /* the current-tab bar on the chrome; 6.4:1 */
  --bb-chrome-gradient: linear-gradient(170deg, var(--bb-chrome-hi) 0%, var(--bb-chrome) 60%, var(--bb-chrome-lo) 100%);
  --bb-primary-bevel: linear-gradient(180deg, #D4521A, var(--bb-brass) 55%, #A9380A);
  --bb-motion: 140ms cubic-bezier(0.2, 0, 0.2, 1);
}

/* ==========================================================================
   Base
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bb-paper);
  color: var(--bb-ink);
  font-family: var(--bb-font-ui);
  font-size: var(--bb-size-body);
  line-height: var(--bb-leading-body);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--bb-brass-text); text-decoration: none; }
a:hover { color: var(--bb-ink); text-decoration: underline; }

/* A link sitting inside a sentence must not rely on colour alone to be
   recognisable as a link — WCAG 1.4.1. Standalone links in navigation, cards
   and buttons are positioned and styled distinctly, so they keep the clean
   rule above; only links surrounded by prose are underlined. */
:where(p, li, .bb-body, .bb-small, .bb-fine, .bb-note, .bb-gapnote, .bb-check__text) a {
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
}

/* ==========================================================================
   Primitives
   ========================================================================== */

/* Mono eyebrow label — sits above a value. Used everywhere. */
.bb-label {
  font-family: var(--bb-font-mono);
  font-size: var(--bb-size-label);
  letter-spacing: var(--bb-track-label);
  text-transform: uppercase;
  color: var(--bb-ink-faint);
}

/* Any checkable fact: reference, timestamp, hash, amount in a table. */
.bb-fact {
  font-family: var(--bb-font-mono);
  font-size: var(--bb-size-meta);
  color: var(--bb-ink-muted);
}

.bb-amount {
  font-family: var(--bb-font-display);
  font-size: var(--bb-size-amount);
  font-weight: 700;
  letter-spacing: var(--bb-track-display);
  line-height: 1.05;
}

/* A card is a sheet of paper lying on the page. Sheets rise, fields sink,
   controls press, dark bars emboss — that is the whole depth vocabulary. */
.bb-card {
  background: var(--bb-surface);
  border: var(--bb-border);
  border-radius: var(--bb-radius-lg);
  box-shadow: var(--bb-lift-1);
}

/* A card that rounds its corners has to clip whatever sits in them, or a
   full-bleed head or photograph squares them off again from the inside. */
.bb-card > *:first-child { border-top-left-radius: inherit; border-top-right-radius: inherit; }
.bb-card > *:last-child  { border-bottom-left-radius: inherit; border-bottom-right-radius: inherit; }

.bb-card__head {
  padding: var(--bb-space-3) var(--bb-space-4);
  border-bottom: var(--bb-border-hair);
}

.bb-card__body { padding: var(--bb-space-4); }

/* Status pills ------------------------------------------------------------ */

.bb-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 11px;
  border-radius: var(--bb-radius-pill);
  font-family: var(--bb-font-mono);
  font-size: var(--bb-size-meta);
  letter-spacing: 0.08em;
}
.bb-pill--live     { background: var(--bb-surface);     border: 1px solid var(--bb-brass);      color: var(--bb-brass-text); }
.bb-pill--verified { background: var(--bb-verify-soft); border: 1px solid var(--bb-verify-line); color: var(--bb-verify); }
.bb-pill--deadline,
.bb-pill--alert    { background: var(--bb-alert-soft);  border: 1px solid var(--bb-alert-line);  color: var(--bb-alert); }

.bb-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

/* Buttons ------------------------------------------------------------------
   Three levels only. Selected state is ALWAYS a dark fill, never a heavier
   border — that consistency is what makes segmented controls readable. */

.bb-btn {
  /* Flex, not block: the label sits dead centre on both axes, and an <a>, a
     <button> and a <label> come out the same height because line-height is
     set here rather than inherited. */
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--bb-space-2);
  width: 100%;
  min-height: var(--bb-tap-min);
  padding: 14px 20px;
  border: 1px solid transparent;
  border-radius: var(--bb-radius-sm);
  font-family: var(--bb-font-display);
  font-size: var(--bb-size-h3);
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  box-shadow: var(--bb-lift-1);
  transition: box-shadow var(--bb-motion), transform var(--bb-motion), background-color var(--bb-motion);
}
/* Each variant names its :hover too. A link-button would otherwise take the
   a:hover ink colour (0,1,1 beats 0,1,0) and a danger button stop being red. */
.bb-btn--primary,   .bb-btn--primary:hover   { background: var(--bb-brass);   color: var(--bb-ink-on-dark); border-color: var(--bb-brass); }
.bb-btn--secondary, .bb-btn--secondary:hover { background: var(--bb-surface); color: var(--bb-ink); border-color: var(--bb-line-strong); }
.bb-btn--tertiary,  .bb-btn--tertiary:hover  { background: var(--bb-surface); color: var(--bb-ink-muted); border-color: var(--bb-line-strong); }
.bb-btn--danger,    .bb-btn--danger:hover    { background: var(--bb-surface); color: var(--bb-alert); border-color: var(--bb-line-strong); }

/* Lift to meet the cursor, then press in under it. The travel is one pixel —
   enough to feel mechanical, too little to read as animation. */
.bb-btn:hover:not(:disabled) {
  box-shadow: var(--bb-lift-2);
  transform: translateY(calc(var(--bb-rise) * -1));
  text-decoration: none;
}
.bb-btn:active:not(:disabled) {
  box-shadow: var(--bb-press);
  transform: translateY(var(--bb-rise));
}
.bb-btn:disabled { box-shadow: none; opacity: 0.45; cursor: not-allowed; }
.bb-btn:focus-visible { outline: 2px solid var(--bb-brass); outline-offset: 2px; }

/* Callout — a bordered-left note. The border colour carries the meaning. */
.bb-note {
  background: var(--bb-surface);
  border-radius: var(--bb-radius-md);
  border-left: 3px solid var(--bb-brass);
  padding: 14px 16px;
  font-size: var(--bb-size-small);
  line-height: 1.6;
  color: var(--bb-ink-body);
  box-shadow: var(--bb-lift-1);
}
.bb-note--brass  { border-left-color: var(--bb-brass); }
.bb-note--verify { border-left-color: var(--bb-verify); }
.bb-note--quiet  { border-left-color: var(--bb-ink-faint); }
.bb-note--alert  { border-left-color: var(--bb-alert); }

/* Evidence rail — the component the whole product rests on. See docs/UI.md.
   It sits one step higher than an ordinary card: on a page of sheets, this is
   the one the buyer is meant to read. */
.bb-evidence {
  background: var(--bb-surface);
  border: var(--bb-border-ink);
  border-radius: var(--bb-radius-lg);
  overflow: hidden;
  box-shadow: var(--bb-lift-2);
}
.bb-evidence__head {
  background: var(--bb-ink);
  color: var(--bb-ink-on-dark);
  padding: 9px var(--bb-space-4);
  display: flex;
  align-items: center;
  gap: 9px;
  font-family: var(--bb-font-mono);
  font-size: var(--bb-size-label);
  letter-spacing: 0.13em;
  box-shadow: var(--bb-emboss);
}
.bb-evidence__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.bb-evidence__cell {
  padding: 13px var(--bb-space-4);
  border-right: var(--bb-border-hair);
  border-top: var(--bb-border-hair);
}
.bb-evidence__cell:nth-child(-n+3) { border-top: none; }
.bb-evidence__cell:nth-child(3n)   { border-right: none; }
.bb-evidence__value {
  font-family: var(--bb-font-mono);
  font-size: var(--bb-size-fine);
  margin-top: var(--bb-space-1);
}
.bb-evidence__value--ok { color: var(--bb-verify); }

/* Image placeholder — keep until real photography exists. */
.bb-photo-placeholder {
  background-color: var(--bb-placeholder);
  background-image: repeating-linear-gradient(
    135deg,
    rgba(var(--bb-ink-rgb), 0.045) 0 14px,
    rgba(var(--bb-ink-rgb), 0) 14px 28px
  );
  border: 1px solid var(--bb-line-strong);
  border-radius: var(--bb-radius-md);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--bb-ink-on-fill);
  font-family: var(--bb-font-mono);
  font-size: var(--bb-size-meta);
  box-shadow: var(--bb-sink);   /* a recessed frame waiting for a photograph */
}

@media (max-width: 640px) {
  :root { --bb-size-display: 28px; --bb-size-amount: 26px; }
}
