/* BlackOS — Admin brand kit */
:root{
  /* SavvyFaire design system — cream canvas · red commit · purple ✦ AI · teal Ari · amber passport. */

  /* ══ WHAT A THING IS, VERSUS HOW IT IS GOING ═════════════════════════════════════════════════
     Asa, 23 Sep 2026, on the booking file's timeline: "can we colour code these icons and status
     logically please."

     THE TWO AXES, AND THE RULE FOR WHICH COLOUR SAYS WHICH. A line on a trip has a TYPE that never
     changes — it is a flight, for the whole of its life — and a STATE that changes constantly. They
     are different questions and must not share a colour, or the answer to one is read as the answer
     to the other.

       the icon says WHAT IT IS      → these --t-* hues, one per type, the same hue everywhere
       the node and the chip say HOW IT IS GOING → green ready · ink booked · amber held · red blocked

     WHY IT READ AS NO CODE AT ALL. The booking file tinted the ICON by state, so a day where every
     line was booked drew five identical black discs: the state was said three times over (icon, node
     and chip) and the type not once — which is the one thing you scan a timeline for.

     These lived on :root in canvas.css, which only the planner loads, so the booking file could not
     have used them even deliberately. They belong here, in the one stylesheet every page loads. */
  --t-flight:#2D6BD6; --t-stay:#8B5CD6; --t-cab:#0F8E68; --t-cruise:#0E9BA8;
  --t-meal:#D6602D; --t-kids:#D14BA0; --t-attraction:#C7A008; --t-other:#767E8E;
  /* The tint each one wears behind a glyph. Written out rather than colour-mix()'d so the value is
     the same in every browser and can be read here without running anything. */
  --t-flight-bg:#E7EEFA; --t-stay-bg:#F0EAFB; --t-cab-bg:#E3F4EE; --t-cruise-bg:#E2F4F6;
  --t-meal-bg:#FBEBE3; --t-kids-bg:#FAE8F3; --t-attraction-bg:#F9F3DC; --t-other-bg:#EEF0F3;

  --ink:#080706; --ink-soft:#3F3A35; --paper:#ffffff;
  --cream:#F9F2EB; --cream-2:#F3EEE8; --cream-3:#E1DCD7;
  /* FIELD CONTRAST — look B (Asa, 16 Sep 2026: "white on white … the background is darker and the entry fields are
     lighter, so it's easier on the eye" → chose B, "consistently", from site/admin/mockups/field-contrast.mockup.html).
     The page is a shade darker than the cream it was, cards stay white, and every entry field is the palest cream
     with a stronger border and a soft inner shadow, with a dark ring on focus. Read-only values are text, not boxes. */
  /* Softened, Asa 16 Sep 2026: "the darker background is too dark and too stark — make it slight, and the lighter
     off-white lighter too." The page sits halfway between the old cream #F9F2EB and look B's #EFE8DF. */
  --page:#F4EDE5; --field:#FEFDFB; --field-line:#BDB3A6;
  --field-shadow:inset 0 1px 2px rgba(42,35,32,.08); --field-ring:0 0 0 3px rgba(63,58,53,.14);
  --stone:#675E54; --stone-soft:#504B47; --line:#E1DCD7;
  /* CHROME — the app's ordinary furniture: buttons, links, selected tabs, focus rings.
     It is deliberately NOT red. .btn takes its fill from --plum, so making this red would put
     ten red buttons on a single screen and spend the one colour that is supposed to mean
     "a human is committing something". Warm espresso instead: it sits on the cream canvas as a
     considered choice rather than the cold #1A1A1A placeholder that used to overwrite it. */
  --plum:#3F3A35; --plum-deep:#2A2622; --plum-tint:#F1EAE2;
  --accent-rgb:63,58,53; --accent-deep-rgb:42,38,34;
  /* COMMIT — red, and only ever red for this. One per screen, applied explicitly so it can never
     leak into chrome by inheriting a token. */
  --commit:#BD2424; --commit-deep:#8E1B1B; --commit-tint:#F6E0E0;
  --purple:#7F77DD; --purple-bg:#EEEDFE;                       /* AI ✦ */
  --teal:#1D9E75; --teal-bg:#E1F5EE;                           /* Ari (staff) */
  --amber:#BA7517; --amber-bg:#F7EEDD;                         /* Passport / personal */
  --good:#1D9E75; --good-bg:#E1F5EE; --warn:#BA7517; --warn-bg:#F7EEDD; --bad:#BD2424; --bad-bg:#F6E0E0;
  --disp:'Plus Jakarta Sans',system-ui,sans-serif; --body:'Inter',system-ui,sans-serif;
  --shadow:0 18px 44px rgba(42,35,32,.10); --shadow-sm:0 6px 18px rgba(42,35,32,.06);
  --r-chip:999px; --r-card:14px; --r-panel:16px;
  /* ── THE SCALES ────────────────────────────────────────────────────────────────────────────
     Measured across site/ on 8 Sep 2026: 35 distinct font sizes (7.5px to 26px, including
     8.5, 9.5, 10.5, 11.5, 12.5, 13.5, 14.5 and 15.5) and 20 distinct border radii (2, 3, 4, 5,
     6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 24, 99, 999). Nobody chose 20 radii; each
     was chosen once, alone, and never compared with the other nineteen.

     These are the ramps everything NEW is built from. They are deliberately short: a scale you
     can hold in your head is a scale people actually use. The existing off-ramp values are not
     rewritten here — that is a visual change to screens already approved, and it is a separate,
     deliberate pass. What stops the drift getting worse is the design gate, which now counts
     off-ramp values and fails when the number goes up. */
  --t-micro:9px;    /* source tags, stamps — the smallest thing that may carry meaning */
  --t-label:10px;   /* THE EYEBROW. Small caps, .07em, 700. */
  --t-xs:11px;      /* secondary metadata under a line */
  --t-sm:12.5px;    /* table cells, chips, dense body */
  --t-md:13.5px;    /* body, a row's own name */
  --t-lg:15px;      /* a sub-head */
  --t-xl:19px;      /* a tile's figure */
  --t-fig:22px;     /* a counter's figure and a sheet's title — Asa, 16 Sep 2026, "strictly follow"
                       the approved booking mockup, which sets both at 22-23px */
  --t-2xl:26px;     /* a page or record title */

  --r-xs:4px; --r-sm:8px; --r-md:12px;   /* with --r-card 14, --r-panel 16, --r-chip 999 above */
}
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:var(--body);background:var(--page);color:var(--ink);line-height:1.55;-webkit-font-smoothing:antialiased}
.serif{font-family:var(--disp)}
a{color:var(--plum);text-decoration:none}
h1,h2{font-family:var(--disp);font-weight:700;line-height:1.12;letter-spacing:-.01em}
h3{font-family:var(--body);font-weight:700;line-height:1.2;letter-spacing:-.005em}
.muted{color:var(--stone-soft)}
.small{font-size:12.5px}
button,input,select,textarea{font-family:inherit}
input,select,textarea{width:100%;padding:11px 13px;border:1px solid var(--field-line);border-radius:12px;font-size:13.5px;background:var(--field);color:var(--ink);box-shadow:var(--field-shadow)}
/* The old line read "input:focus,select,textarea:focus" — the bare "select" gave every dropdown the focus border all
   the time. Each control is focused on its own now, with the ring. */
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--plum);box-shadow:var(--field-shadow),var(--field-ring)}
input[type=checkbox],input[type=radio],input[type=range],input[type=color],input[type=file]{box-shadow:none;background:transparent}
/* Inputs that are deliberately borderless — the top search, the command bar, the big figure editors — stay flat. */
.tb-search input,.cmd input,.slc-dv input,.slc-dv select{box-shadow:none}
label{display:block;font-size:12.5px;font-weight:600;color:var(--ink-soft);margin:0 0 5px;letter-spacing:.01em}
.field{margin-bottom:14px}
.row{display:grid;gap:12px}
.row.c2{grid-template-columns:1fr 1fr}.row.c3{grid-template-columns:1fr 1fr 1fr}
@media(max-width:640px){.row.c2,.row.c3{grid-template-columns:1fr}}
.btn{display:inline-flex;align-items:center;gap:7px;padding:11px 18px;border:1px solid var(--plum);border-radius:var(--r-chip);background:var(--plum);color:#fff;font-weight:600;font-size:13.5px;cursor:pointer;transition:.15s}
.btn:hover{background:var(--plum-deep);border-color:var(--plum-deep)}
.btn.ghost{background:#fff;color:var(--plum)}.btn.ghost:hover{background:var(--plum-tint)}
/* COMMIT — the one action on a screen where a human takes responsibility for something.
   Red is spent here and nowhere else; if two of these appear on one screen, one of them is
   not really a commit and should be a ghost. */
.btn.commit{background:var(--commit);border-color:var(--commit)}
.btn.commit:hover{background:var(--commit-deep);border-color:var(--commit-deep)}
.btn.commit.ghost{background:#fff;color:var(--commit);border-color:var(--commit)}
.btn.commit.ghost:hover{background:var(--commit-tint)}
.btn.sm{padding:7px 13px;font-size:12.5px}
.btn.dark{background:var(--ink);border-color:var(--ink)}.btn.dark:hover{background:#000}
.chip{display:inline-flex;align-items:center;gap:5px;padding:3px 10px;border-radius:var(--r-chip);font-size:11px;font-weight:600;background:var(--cream-2);color:var(--ink-soft)}
.chip.good{background:var(--good-bg);color:var(--good)}.chip.warn{background:var(--warn-bg);color:var(--warn)}.chip.bad{background:var(--bad-bg);color:var(--bad)}
.card{background:var(--paper);border:1px solid var(--line);border-radius:16px;padding:22px;box-shadow:var(--shadow-sm)}

/* ══ THE PRIMITIVES ════════════════════════════════════════════════════════════════════════════
   Eight shapes the app actually has, each written ONCE, here, in the shared system.

   They were not invented — they were EXTRACTED. Measured on 8 Sep 2026, app.html carried 1,054
   lines of CSS in 25 per-page namespaces (jr- bi- pd- ppl- vk- tp- tb- katy- …), and those
   namespaces were re-deriving the same handful of shapes with slightly different numbers each
   time: the panel card existed three times at two radii, the small-caps eyebrow six times at
   three sizes and three weights, the status row twice as near-identical copies. Nothing was
   wrong with any one of them; the problem was that a fix to one silently missed the others,
   which is exactly how .ppl-p and .bi-pax drifted apart.

   The old class names are kept as ALIASES so no markup had to change. A page keeps calling its
   card .bi-card; it simply now gets the same card as everybody else. New work should use the
   unprefixed name.

   NOTE — .card above and .panel below are DIFFERENT SHAPES, deliberately:
     .card   is a single padded box. Content sits straight inside it.
     .panel  is a box with a header bar and a body, and clips its children (overflow:hidden), so
             a table or a list of rows can run edge to edge inside it.
   Merging them was tempting and would have been wrong — .card's 22px padding is load-bearing on
   dozens of screens.
   ═══════════════════════════════════════════════════════════════════════════════════════════ */

/* 1 · PANEL — header bar + body. Radius comes from the token, so it is one number, not three
      (it was 14px on .pd-card and 15px on .bi-card). */
.panel,.pd-card{
  background:var(--paper);border:1px solid var(--line);border-radius:var(--r-card);
  overflow:hidden;box-shadow:0 1px 2px rgba(28,29,31,.035);margin-bottom:14px}

/* 2 · PANEL HEADER — the bar with a bottom rule. THIS is what stops a panel reading flat; an
      eyebrow floating above content is not a header. Aligned flex-start rather than centre so a
      two-line title with a provenance note under it does not drag its right-hand chip down. */
.panel-h,.pd-card-h{
  display:flex;align-items:flex-start;justify-content:space-between;gap:18px;flex-wrap:wrap;
  padding:13px 18px 12px;border-bottom:1px solid var(--cream-2)}

/* 3 · PANEL BODY */
.panel-b,.pd-card-b{padding:14px 18px}
.panel-b.flush,.pd-card-b.flush{padding:0}

/* 4 · EYEBROW — the small-caps kick that says which domain a block belongs to. Six definitions
      became one at 10px/700/.07em, the modal value of the six. .tagpill and .bi-tab b are NOT in
      this group: they sit on the espresso band at weight 800 and are tags, not eyebrows. */
.kick,.eyebrow,.vk-tbl .h{
  font-size:10px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--stone)}

/* 5 · PROVENANCE — which table this block binds to. The house signature: it makes a screen
      self-documenting and it is the thing that makes a block look considered rather than bare. */
.prov{font-size:11px;color:#9C9B97;margin-top:2px}

/* 6 · STATUS ROW — one person, one task, one segment. A soft tint across the whole row IS the status
      system (no edge rail): teal ready, amber a gap, red blocking. It reads down a column without a pill. */
.rowitem{
  display:flex;align-items:flex-start;gap:13px;padding:13px 18px;
  border-bottom:1px solid var(--cream-3);position:relative}
.rowitem:last-of-type{border-bottom:0}
.rowitem.ok{background:rgba(29,158,117,.05)}
.rowitem.gap{background:rgba(186,117,23,.07)}
.rowitem.stop{background:rgba(189,36,36,.05)}

/* 7 · INITIALS — the round mark at the head of a status row, tinted by that row's state. */
.ini{
  flex:0 0 auto;width:34px;height:34px;border-radius:50%;display:grid;place-items:center;
  background:var(--cream);color:var(--stone);font-size:11px;font-weight:700;letter-spacing:.03em}
.rowitem.ok .ini{background:rgba(29,158,117,.12);color:var(--good)}
.rowitem.stop .ini{background:rgba(189,36,36,.10);color:var(--bad)}

/* 8 · METER — a bar is decoration until a sentence states the reading underneath it. */
.meter{height:8px;border-radius:99px;background:var(--sunk,#EFE9DF);overflow:hidden;display:flex}
.meter i{height:100%;display:block}
table{width:100%;border-collapse:collapse;font-size:13.5px}
th{text-align:left;font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--stone-soft);font-weight:700;padding:9px 10px;border-bottom:2px solid var(--cream-3)}
td{padding:10px;border-bottom:1px solid var(--cream-2);vertical-align:top}
tr:hover td{background:var(--cream)}
.num{text-align:right;font-variant-numeric:tabular-nums}
/* pipeline kanban — desktop = all columns, mobile = swipeable full-width columns that stay within the screen */
.board{display:grid;grid-template-columns:repeat(var(--ncol),minmax(180px,1fr));gap:12px;align-items:start;overflow-x:auto}
@media(max-width:760px){.board{grid-template-columns:none;grid-auto-flow:column;grid-auto-columns:86%;scroll-snap-type:x proximity;padding-bottom:8px}.board>*{scroll-snap-align:start}}
.kpi{background:#fff;border:1px solid var(--line);border-radius:12px;padding:13px 15px}
.kpi .v{font-family:var(--body);font-size:19px;font-weight:700;line-height:1.1;letter-spacing:-.015em;font-variant-numeric:tabular-nums;color:var(--ink,#1a1018)}
.kpi .l{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--stone-soft);margin-top:5px;font-weight:600}
.empty{text-align:center;color:var(--stone-soft);padding:40px 20px;font-size:13.5px}

/* ── "boiling over" — generation-motion reveal (staggered shimmer → settle). Brand-tinted (plum + warm gold). ── */
@keyframes gen-shimmer{0%{background-position:-150% 0}100%{background-position:250% 0}}
@keyframes gen-pop{0%{opacity:0;transform:translateY(10px) scale(.985)}100%{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.gen,.gen::after,.gen--in{animation:none!important}.gen>*{opacity:1!important;filter:none!important}}
.gen{position:relative;border:1.5px dashed var(--line,#E2DDD4)!important;overflow:hidden}
.gen>*{opacity:.22;filter:blur(.5px);transition:opacity .4s ease,filter .4s ease}
.gen::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;z-index:3;background:linear-gradient(100deg,transparent 30%,rgba(var(--accent-rgb),.13) 46%,rgba(202,165,61,.14) 56%,transparent 72%);background-size:220% 100%;animation:gen-shimmer 1.05s linear infinite}
.gen--in{animation:gen-pop .42s cubic-bezier(.22,1,.36,1) both}

/* ── AN AIRLINE'S OWN MARK (Asa, 20 Sep 2026: "when we show an airline, can we show the airline's
   logo?"). One box, one size, everywhere an airline appears — proposal, canvas, itinerary, Quick
   Trip, booking file. The box is drawn whether or not there is a logo, so a row of flights lines up
   whichever airlines are in it, and a carrier we have no mark for shows its code rather than a stock
   aeroplane that would claim to be a brand. See site/assets/js/airlinemark.js. */
.al-mark{display:inline-flex;align-items:center;justify-content:center;flex:none;overflow:hidden;
  border-radius:6px;background:var(--cream-2,#F3EEE8);color:var(--stone,#6B6257);
  font-size:9.5px;font-weight:700;letter-spacing:.02em;line-height:1}
.al-mark img{width:100%;height:100%;object-fit:contain;display:block;background:#fff}

/* An airline's real mark standing in the avatar box on a Quick Trip result row. The box keeps the
   .ava size and shape; this only stops the logo being stretched to fill a circle it does not fit. */
.ava-mk{padding:0;background:#fff;overflow:hidden;display:inline-flex;align-items:center;justify-content:center}
.ava-mk .al-mark{width:100%!important;height:100%!important;background:none;border-radius:inherit}
