/* Lucid — one stylesheet for every custom admin screen.

   Loaded through UNFOLD["STYLES"] so it applies to the dashboard, the plan
   cockpit and the report pages alike; previously each template carried its own
   <style> block and the dashboard silently missed half of them.

   Two things to know before editing:

   1. Unfold ships Tailwind v4, whose theme variables hold COMPLETE colour
      values — `--color-base-200` is `oklch(92.8% .006 264.531)`, not the bare
      "R G B" triplet Tailwind v3 used. So write `var(--color-base-200)`, never
      `rgb(var(--color-base-200))`: the latter expands to `rgb(oklch(...))`,
      which is invalid, and the whole declaration is dropped — which is exactly
      how the buttons ended up with no background. For translucency use
      `color-mix(in oklab, var(--x) 15%, transparent)`.

   2. Unfold's bundle only contains the Tailwind utilities Unfold itself uses.
      Anything else we reference has to be defined here (see "missing
      utilities" at the bottom) — there is no Tailwind build in this project
      and deliberately so: one hand-written stylesheet is easier to reason
      about than a build step for a dozen screens.
*/

:root {
/* Complete colour values, matching how Unfold's own variables are written.
     Bare "R G B" triplets only work inside rgb(), and nothing here uses that
     form any more. */
--lucid-danger: rgb(220 38 38);
--lucid-warn:   rgb(217 119 6);
--lucid-ok:     rgb(22 163 74);
--lucid-info:   rgb(37 99 235);
}
.dark {
/* Lifted for contrast against a dark background. */
--lucid-danger: rgb(248 113 113);
--lucid-warn:   rgb(251 191 36);
--lucid-ok:     rgb(74 222 128);
--lucid-info:   rgb(96 165 250);
}

.lucid-card {
    border: 1px solid var(--color-base-200);
    border-radius: .5rem;
    padding: 1.25rem;
    background: var(--color-base-50);
}
.dark .lucid-card { border-color: var(--color-base-800); background: var(--color-base-900); }

.lucid-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 1rem; }
.lucid-metric { font-size: 1.6rem; font-weight: 600; line-height: 1.2; }
.lucid-label { font-size: .72rem; text-transform: uppercase; letter-spacing: .05em; opacity: .6; }
.lucid-danger { color: var(--lucid-danger); }
.lucid-warn   { color: var(--lucid-warn); }
.lucid-ok     { color: var(--lucid-ok); }

/* ---- filter bar: match Unfold's form controls -------------------- */
.lucid-bar { display: flex; flex-wrap: wrap; gap: .75rem; align-items: flex-end; margin-bottom: 1.25rem; }
.lucid-bar label { display: block; font-size: .72rem; opacity: .7; margin-bottom: .25rem; }
.lucid-bar input[type="date"],
.lucid-bar input[type="number"],
.lucid-bar input[type="text"],
.lucid-select {
    appearance: none;
    border: 1px solid var(--color-base-200);
    background: var(--color-base-50);
    color: var(--color-font-default-light);
    border-radius: .375rem;
    padding: .45rem 2rem .45rem .65rem;
    font-size: .8125rem;
    line-height: 1.25rem;
    min-width: 9rem;
    box-shadow: 0 1px 2px rgb(0 0 0 / .04);
}
.dark .lucid-bar input[type="date"],
.dark .lucid-bar input[type="number"],
.dark .lucid-bar input[type="text"],
.dark .lucid-select {
    border-color: var(--color-base-700);
    background: var(--color-base-900);
    color: var(--color-font-default-dark);
}
.lucid-select {
    /* Unfold's chevron, inlined so no external asset is needed. */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%239ca3af' stroke-width='2'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M19 9l-7 7-7-7'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right .5rem center;
    background-size: 1.1em;
}
.lucid-select:focus,
.lucid-bar input:focus {
    outline: 2px solid color-mix(in oklab, var(--color-primary-500) 45%, transparent);
    outline-offset: 1px;
    border-color: var(--color-primary-500);
}

/* Inputs inside tables and cards (the cockpit grid) get the same treatment
     as the filter bar — otherwise the editable columns look like raw HTML. */
.lucid-table input,
.lucid-card input:not([type="checkbox"]):not([type="radio"]) {
    border: 1px solid var(--color-base-200);
    background: var(--color-base-50);
    color: var(--color-font-default-light);
    border-radius: .375rem;
    padding: .35rem .55rem;
    font-size: .8125rem;
}
.dark .lucid-table input,
.dark .lucid-card input:not([type="checkbox"]):not([type="radio"]) {
    border-color: var(--color-base-700);
    background: var(--color-base-950);
    color: var(--color-font-default-dark);
}
.lucid-table input:focus,
.lucid-card input:focus {
    outline: 2px solid color-mix(in oklab, var(--color-primary-500) 45%, transparent);
    outline-offset: 1px;
    border-color: var(--color-primary-500);
}
/* The number a user is actively deciding should look decided. */
.lucid-table input.js-qty { font-weight: 600; }

.lucid-btn {
    background: var(--color-primary-600);
    color: #fff; padding: .5rem .9rem; border-radius: .375rem;
    font-weight: 500; font-size: .8125rem; border: 0; cursor: pointer;
}
.lucid-btn:hover { background: var(--color-primary-700); }
.lucid-btn-ghost {
    border: 1px solid var(--color-base-200);
    padding: .45rem .8rem; border-radius: .375rem; font-size: .8125rem;
}
.dark .lucid-btn-ghost { border-color: var(--color-base-700); }
.lucid-btn-ghost:hover { border-color: var(--color-primary-500); }

/* ---- tables ------------------------------------------------------ */
.lucid-table { width: 100%; border-collapse: collapse; font-size: .85rem; }
.lucid-table th {
    text-align: left; font-size: .68rem; text-transform: uppercase;
    letter-spacing: .04em; opacity: .6; padding: .5rem .6rem; font-weight: 600;
}
.lucid-table td { padding: .55rem .6rem; border-top: 1px solid var(--color-base-200); }
.dark .lucid-table td { border-color: var(--color-base-800); }
.lucid-table tbody tr:hover td { background: color-mix(in oklab, var(--color-base-100) 60%, transparent); }
.dark .lucid-table tbody tr:hover td { background: color-mix(in oklab, var(--color-base-800) 40%, transparent); }
.lucid-scroll { overflow-x: auto; }

/* ---- status pills ------------------------------------------------ */
.lucid-pill {
    display: inline-block; padding: .1rem .5rem; border-radius: 999px;
    font-size: .68rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
}
.lucid-pill-short { background: color-mix(in oklab, var(--lucid-danger) 15%, transparent); color: var(--lucid-danger); }
.lucid-pill-late  { background: color-mix(in oklab, var(--lucid-warn) 18%, transparent);  color: var(--lucid-warn); }
.lucid-pill-over  { background: color-mix(in oklab, var(--lucid-info) 15%, transparent);  color: var(--lucid-info); }
.lucid-pill-ok    { background: color-mix(in oklab, var(--lucid-ok) 15%, transparent);    color: var(--lucid-ok); }
/* Severity aliases, for pills whose subject is not a coverage verdict. */
.lucid-pill-bad   { background: color-mix(in oklab, var(--lucid-danger) 15%, transparent); color: var(--lucid-danger); }
.lucid-pill-warn  { background: color-mix(in oklab, var(--lucid-warn) 18%, transparent);   color: var(--lucid-warn); }
.lucid-pill-good  { background: color-mix(in oklab, var(--lucid-ok) 15%, transparent);     color: var(--lucid-ok); }

/* ---- utilities Unfold's bundle does not ship -------------------------------
   Used across the custom templates for visual hierarchy. Without them every
   caption renders at full strength and the hierarchy collapses. */
.opacity-40 { opacity: .4; }
.opacity-60 { opacity: .6; }
.opacity-70 { opacity: .7; }
.opacity-80 { opacity: .8; }
.tracking-wide { letter-spacing: .025em; }

/* ---- dashboard ----------------------------------------------------------- */
.lucid-dash-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(205px, 1fr)); gap: 1rem; }
/* Dashboard cells: small numbers, many to a row, two a row on a phone. */
.lucid-cells { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: .6rem; }
@media (max-width: 480px) { .lucid-cells { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.lucid-cell { display: block; border: 1px solid var(--color-base-200); border-radius: .4rem; padding: .5rem .65rem; min-width: 0; }
.dark .lucid-cell { border-color: var(--color-base-800); }
.lucid-cell .lucid-metric { font-size: 1.15rem; overflow-wrap: anywhere; }
.lucid-cell-sub { font-size: .7rem; opacity: .6; }
.lucid-section { margin-bottom: 1.25rem; }
.lucid-section-head { display: flex; justify-content: space-between; gap: .5rem; flex-wrap: wrap; align-items: baseline; margin-bottom: .45rem; }
.lucid-lists { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: .6rem; margin-top: .6rem; }
.lucid-panel {
border: 1px solid var(--color-base-200);
border-radius: .5rem;
padding: 1.25rem;
background: var(--color-base-50);
}
.dark .lucid-panel { border-color: var(--color-base-800); background: var(--color-base-900); }

/* A panel title on the left and its verdict on the right. The verdict is the
   part people read first, so it gets the end of the line, not a footnote. */
.lucid-panel-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; margin-bottom: .5rem;
}


/* ---- plan cockpit --------------------------------------------------------- */
/* The product name is printed once per group; a rule marks where the next
   garment starts, so sixty editable rows still read as twenty things. */
.lucid-table tr.is-group-start td { border-top: 1px solid var(--color-base-300); }
.dark .lucid-table tr.is-group-start td { border-top-color: var(--color-base-700); }
.lucid-est {
font-size: .6rem; text-transform: uppercase; letter-spacing: .04em;
opacity: .55; margin-left: .3rem;
}

/* ---- period bar & tabs ---------------------------------------------------- */
.lucid-periodbar {
padding: .75rem 1rem;
border: 1px solid var(--color-base-200);
border-radius: .5rem;
background: var(--color-base-50);
}
.dark .lucid-periodbar { border-color: var(--color-base-800); background: var(--color-base-900); }

.lucid-tabs { display: flex; gap: .25rem; margin-bottom: 1.25rem; flex-wrap: wrap; }
.lucid-tab {
padding: .45rem .9rem;
border-radius: .375rem;
font-size: .8125rem;
font-weight: 500;
border: 1px solid transparent;
color: inherit;
}
.lucid-tab:hover { background: color-mix(in oklab, var(--color-base-500) 10%, transparent); }
.lucid-tab.is-active {
background: var(--color-primary-600);
color: #fff;
}

/* ---- "needs a decision" list ---------------------------------------------
   The dashboard's first block. Rows are links, because every item here is
   something you go and do; a dot carries the severity so the list can be
   scanned without reading. */
.lucid-attention { display: flex; flex-direction: column; }
.lucid-attention-row {
  display: flex; align-items: center; gap: .75rem;
  padding: .7rem .25rem;
  border-top: 1px solid var(--color-base-200);
  color: inherit;
}
.dark .lucid-attention-row { border-top-color: var(--color-base-800); }
.lucid-attention-row:first-child { border-top: 0; }
.lucid-attention-row:hover { background: color-mix(in oklab, var(--color-base-500) 8%, transparent); }
.lucid-attention-dot { width: .5rem; height: .5rem; border-radius: 999px; flex: none; }
.lucid-attention-row.is-critical .lucid-attention-dot { background: var(--lucid-danger); }
.lucid-attention-row.is-warning  .lucid-attention-dot { background: var(--lucid-warn); }
.lucid-attention-row.is-info     .lucid-attention-dot { background: var(--lucid-info); }
.lucid-attention-text { flex: 1; font-size: .875rem; display: flex; gap: .5rem; flex-wrap: wrap; }
.lucid-attention-action { font-size: .8125rem; opacity: .7; white-space: nowrap; }
.lucid-attention-row:hover .lucid-attention-action { opacity: 1; }

/* The reasoning behind each suggestion, visible rather than hover-only —
   it is the thing that makes a proposed number trustworthy. */
.lucid-basis {
  font-size: .68rem;
  line-height: 1.25;
  opacity: .6;
  max-width: 16rem;
  margin-left: auto;
  text-align: right;
  margin-top: .15rem;
}

.lucid-unit { font-size: .8rem; font-weight: 400; opacity: .55; }
/* Something went wrong, or there is nothing yet — either way, say so and give
   somewhere to go. A blank chart frame reads as "all clear". */
.lucid-empty {
  display: flex; align-items: center; justify-content: center; gap: .4rem;
  height: 100%; min-height: 5rem; font-size: .85rem; opacity: .75; text-align: center;
}

/* ---- chart legend --------------------------------------------------------
   A Gantt whose colours are only explained in JavaScript is a puzzle. */
.lucid-legend { display: flex; gap: 1rem; flex-wrap: wrap; margin-top: .75rem; font-size: .75rem; opacity: .8; }
.lucid-legend span { display: inline-flex; align-items: center; gap: .35rem; }
.lucid-swatch { width: 1.1rem; height: .5rem; border-radius: 2px; display: inline-block; }
.lucid-swatch[data-status="ordered"]   { background: #d97706; }
.dark .lucid-swatch[data-status="ordered"] { background: #fbbf24; }
.lucid-swatch[data-status="received"]  { background: var(--lucid-ok); }
.lucid-swatch[data-status="cancelled"] { background: #9ca3af; }
.lucid-swatch.is-late { background: transparent; border: 2px solid var(--lucid-danger); }

/* ==========================================================================
   Production flow — one garment's chain as connected boxes.

   Two screens share this block: the picker (which garment?) and the graph.
   The graph's columns are laid out by CSS; the wires between them are SVG
   drawn from measured card positions, because the server cannot know where a
   card lands once its name wraps to two lines.
   ========================================================================== */

/* ---- the picker ---------------------------------------------------------- */
.lucid-pick-grid {
  display: grid; gap: .7rem;
  grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
}
.lucid-pick {
  position: relative;
  display: block; padding: .8rem .9rem;
  border: 1px solid var(--color-base-200); border-radius: .6rem;
  text-decoration: none; color: inherit;
  transition: border-color .12s, transform .12s;
}
.dark .lucid-pick { border-color: var(--color-base-800); }
.lucid-pick:hover {
  border-color: var(--color-primary-500);
  transform: translateY(-1px);
}
/* A garment with no recipe has nothing to draw; say so before the click. */
.lucid-pick.is-flat { opacity: .6; }
.lucid-pick-name { font-size: .85rem; font-weight: 600; line-height: 1.2; }
.lucid-pick-qty {
  font-size: 1.6rem; font-weight: 300; line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--color-primary-500);
}
.lucid-pick-foot {
  display: flex; align-items: center; gap: .4rem;
  font-size: .68rem; opacity: .6;
}

/* ---- the header ---------------------------------------------------------- */
.lucid-flow-head-row { display: flex; align-items: flex-start; gap: 1rem; flex-wrap: wrap; }
.lucid-flow-title { font-size: 1.35rem; font-weight: 600; line-height: 1.15; }
.lucid-break {
  display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap;
  margin-top: .75rem; padding: .55rem .7rem; border-radius: .5rem;
  background: color-mix(in oklab, var(--lucid-danger) 9%, transparent);
}
.lucid-break.is-ok { background: color-mix(in oklab, var(--lucid-ok) 9%, transparent); }

/* ---- the graph ----------------------------------------------------------- */
/* `width: max-content` so the wires' coordinate space is the *content*, not
   the scroll viewport — an absolutely positioned SVG inside a scroller stays
   put while the boxes slide away underneath it. */
.lucid-graph { position: relative; width: max-content; min-width: 100%; padding: .25rem 0 .5rem; }
.lucid-wires { position: absolute; inset: 0; pointer-events: none; overflow: visible; }
.lucid-wire { fill: none; stroke-width: 1.5; opacity: .75; }
.lucid-wire[data-flow="late"]    { stroke: var(--lucid-danger); stroke-width: 2.2; }
.lucid-wire[data-flow="missing"] { stroke: var(--lucid-warn); stroke-dasharray: 5 4; }
.lucid-wire[data-flow="running"] { stroke: var(--lucid-info); }
.lucid-wire[data-flow="done"]    { stroke: var(--lucid-ok); }
/* The label sits on top of its own wire, so it gets a halo in the card colour
   rather than a box — a box that size is bigger than the number in it. */
.lucid-wire-label {
  font-size: .62rem; fill: currentColor; opacity: .65;
  font-variant-numeric: tabular-nums;
  paint-order: stroke fill;
  stroke: var(--color-base-50); stroke-width: 3px; stroke-linejoin: round;
}
.dark .lucid-wire-label { stroke: var(--color-base-900); }

/* Columns are recipe depth. `align-items: center` keeps the wires short and
   roughly horizontal, which is what makes the chain readable at a glance. */
.lucid-graph-cols { display: flex; align-items: center; gap: 4rem; }
.lucid-graph-col { display: flex; flex-direction: column; gap: .9rem; width: 15rem; flex: none; }
.lucid-graph-coltitle { text-align: center; }

/* ---- one box ------------------------------------------------------------- */
.lucid-node {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; gap: .3rem;
  padding: .6rem .7rem;
  border: 1px solid var(--color-base-200); border-radius: .55rem;
  background: var(--color-base-50);
  border-inline-start-width: 3px;
}
.dark .lucid-node { border-color: var(--color-base-800); background: var(--color-base-900); }
.lucid-node[data-flow="late"]    { border-inline-start-color: var(--lucid-danger); }
.lucid-node[data-flow="missing"] { border-inline-start-color: var(--lucid-warn); }
.lucid-node[data-flow="running"] { border-inline-start-color: var(--lucid-info); }
.lucid-node[data-flow="done"]    { border-inline-start-color: var(--lucid-ok); }
/* Buying and making are different kinds of work; a dashed edge separates them
   without spending a second colour on it. */
.lucid-node[data-kind="make"] { border-inline-start-style: double; border-inline-start-width: 4px; }

.lucid-node-head {
  display: flex; align-items: center; gap: .35rem;
  font-size: .66rem; text-transform: uppercase; letter-spacing: .04em; opacity: .6;
}
.lucid-node-title {
  font-size: .92rem; font-weight: 600; line-height: 1.15;
  text-decoration: none; color: inherit;
}
.lucid-node-title:hover { text-decoration: underline; }
.lucid-node-share { font-size: .7rem; }
.lucid-node-share b { font-variant-numeric: tabular-nums; }

/* How much of this step reality already covers. A half-filled meter is
   half-solved, which three numbers side by side cannot say. */
.lucid-node-meter {
  height: .35rem; border-radius: 999px; overflow: hidden;
  background: color-mix(in oklab, var(--color-base-500) 16%, transparent);
}
.lucid-node-meter-fill { display: block; height: 100%; }
.lucid-node-meter-fill[data-flow="late"]    { background: var(--lucid-danger); }
.lucid-node-meter-fill[data-flow="missing"] { background: var(--lucid-warn); }
.lucid-node-meter-fill[data-flow="running"] { background: var(--lucid-info); }
.lucid-node-meter-fill[data-flow="done"]    { background: var(--lucid-ok); }

.lucid-node-facts {
  display: flex; gap: .5rem; flex-wrap: wrap;
  font-size: .66rem; opacity: .7; font-variant-numeric: tabular-nums;
}
.lucid-node-facts .lucid-danger { opacity: 1; font-weight: 600; }
.lucid-node-when { font-size: .66rem; opacity: .6; }

/* The strip is the same date window for every box on the page, so two blocks
   at the same x really are the same week. */
.lucid-node-track {
  position: relative; height: .9rem; margin-top: .1rem;
  border-top: 1px dashed color-mix(in oklab, var(--color-base-500) 20%, transparent);
}
/* A one-day order at nine-month scale is a quarter of a pixel; a floor of 8
   keeps it a block rather than a speck, and a speck reads as absent. */
.lucid-node-bar {
  position: absolute; top: .2rem; height: .6rem; min-width: 8px;
  border-radius: .15rem; border: 1px solid transparent;
}
.lucid-node-bar[data-flow="late"] {
  background: color-mix(in oklab, var(--lucid-danger) 22%, transparent);
  border-color: var(--lucid-danger);
}
.lucid-node-bar[data-flow="missing"] {
  background: color-mix(in oklab, var(--lucid-warn) 18%, transparent);
  border-color: var(--lucid-warn); border-style: dashed;
}
.lucid-node-bar[data-flow="running"] {
  background: color-mix(in oklab, var(--lucid-info) 18%, transparent);
  border-color: var(--lucid-info);
}
.lucid-node-bar[data-flow="done"] {
  background: color-mix(in oklab, var(--lucid-ok) 18%, transparent);
  border-color: var(--lucid-ok);
}
.lucid-node-none { font-size: .62rem; opacity: .4; line-height: .9rem; }

/* Naming the upstream cause is the whole point: a step blocked by its input
   is not independently fixable, and chasing it wastes a morning. */
.lucid-node-blocked {
  font-size: .64rem; padding: .18rem .35rem; border-radius: .25rem;
  background: color-mix(in oklab, var(--lucid-warn) 14%, transparent);
}

.lucid-dot { width: .6rem; height: .6rem; border-radius: 999px; display: inline-block; flex: none; }
.lucid-dot[data-flow="late"]    { background: var(--lucid-danger); }
.lucid-dot[data-flow="missing"] { background: var(--lucid-warn); }
.lucid-dot[data-flow="running"] { background: var(--lucid-info); }
.lucid-dot[data-flow="done"]    { background: var(--lucid-ok); }

/* ---- plan-versus-reality bar --------------------------------------------
   One bar per garment, segmented by where the cover comes from. Replaces six
   numeric columns people were asked to subtract in their heads. */
.lucid-cover { display: flex; height: 1.15rem; border-radius: .25rem; overflow: hidden;
               background: color-mix(in oklab, var(--color-base-500) 12%, transparent); }
.lucid-cover i { display: block; height: 100%; }
.lucid-cover i[data-part="sold"]      { background: color-mix(in oklab, var(--lucid-ok) 70%, transparent); }
.lucid-cover i[data-part="stock"]     { background: var(--lucid-ok); }
.lucid-cover i[data-part="progress"]  { background: var(--lucid-info); }
.lucid-cover i[data-part="uncovered"] { background: color-mix(in oklab, var(--lucid-danger) 55%, transparent); }
.lucid-cover-key { display: flex; gap: .9rem; flex-wrap: wrap; font-size: .7rem; opacity: .75; }
.lucid-cover-key i { width: .9rem; height: .55rem; border-radius: 2px; display: inline-block; margin-inline-end: .3rem; }

/* ------------------------------------------------------------ plans

   A plan's year is the most important thing about it, so it is typeset like a
   headline rather than hidden inside a dropdown label. */

.lucid-year { margin-bottom: 1.75rem; }
.lucid-year-head {
  display: flex; align-items: baseline; gap: .75rem;
  padding-bottom: .4rem; margin-bottom: .6rem;
  border-bottom: 1px solid var(--color-base-200);
}
.dark .lucid-year-head { border-bottom-color: var(--color-base-800); }
.lucid-year-number { font-size: 1.6rem; font-weight: 650; letter-spacing: -.02em; }

.lucid-plan-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: .75rem;
}
.lucid-plan-card {
  display: block; position: relative;
  padding: .85rem 1rem;
  border: 1px solid var(--color-base-200);
  border-radius: .55rem;
  text-decoration: none; color: inherit;
  transition: border-color .12s, background .12s;
}
.dark .lucid-plan-card { border-color: var(--color-base-800); }
.lucid-plan-card:hover {
  border-color: var(--color-primary-500);
  background: color-mix(in oklab, var(--color-primary-500) 6%, transparent);
}
.lucid-plan-card.is-objective { border-left: 3px solid var(--lucid-warn); }
.lucid-plan-name { font-weight: 600; display: flex; align-items: center; gap: .4rem; }
.lucid-plan-year {
  position: absolute; top: .7rem; right: 1rem;
  font-size: 1.5rem; font-weight: 650; opacity: .13;
  letter-spacing: -.02em; line-height: 1;
}
.lucid-plan-facts {
  display: flex; flex-wrap: wrap; gap: .6rem;
  font-size: .72rem; opacity: .8; margin-top: .35rem;
}
.lucid-plan-status { font-size: .68rem; opacity: .5; margin-top: .3rem; text-transform: uppercase; }

/* Which plan the year is actually run on.
 *
 * The shelf used to print the plan's lifecycle `status` here, so three plans on
 * a year all read ACTIVE and the one question a planner arrives with — "which
 * of these is the real one" — had no answer on the page. `standing` answers it
 * instead, and the selected card is marked strongly enough to find without
 * reading: one per year, by database constraint. */
.lucid-plan-open { display: block; text-decoration: none; color: inherit; }
.lucid-plan-standing {
  display: flex; align-items: center; gap: .4rem;
  font-size: .68rem; margin-top: .45rem; text-transform: uppercase;
  letter-spacing: .04em; opacity: .55;
}
.lucid-plan-standing[data-standing="running-the-year"] { opacity: 1; color: var(--lucid-ok); font-weight: 600; }
.lucid-plan-standing[data-standing="used-by-default"] { opacity: .85; color: var(--lucid-warn); }
.lucid-plan-card.is-selected {
  border-color: var(--lucid-ok);
  box-shadow: inset 3px 0 0 var(--lucid-ok);
}
.lucid-plan-pick { margin-left: auto; }
.lucid-plan-pick .lucid-btn-ghost { font-size: .68rem; padding: .1rem .45rem; }
.lucid-plan-card:not(:hover) .lucid-plan-pick { opacity: 0; }
.lucid-plan-card:hover .lucid-plan-pick { opacity: 1; }

.lucid-year-runs { margin-left: auto; font-size: .74rem; opacity: .75; }
.lucid-year-runs.is-undecided { color: var(--lucid-warn); opacity: 1; }

/* The cockpit header: year, name, state, and every other plan one click away. */
.lucid-plan-head {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  padding-bottom: .9rem; margin-bottom: 1rem;
  border-bottom: 1px solid var(--color-base-200);
}
.dark .lucid-plan-head { border-bottom-color: var(--color-base-800); }
.lucid-plan-back {
  display: inline-block; margin-inline-start: -.5rem;
  font-size: 1.2rem; text-decoration: none; opacity: .5;
  padding: .2rem .5rem; border-radius: .35rem;
}
.lucid-plan-back:hover { opacity: 1; background: color-mix(in oklab, var(--color-base-500) 10%, transparent); }
.lucid-plan-title { display: flex; align-items: center; gap: .9rem; }
.lucid-plan-title-year {
  font-size: 2.4rem; font-weight: 700; line-height: 1;
  letter-spacing: -.03em;
  color: var(--color-primary-500);
}
.lucid-plan-title-name { font-size: 1.05rem; font-weight: 600; display: flex; align-items: center; gap: .45rem; }
.lucid-plan-title-sub { font-size: .74rem; opacity: .7; }

.lucid-plan-switch { display: flex; gap: 1rem; margin-inline-start: auto; flex-wrap: wrap; }
.lucid-plan-switch-year { display: flex; align-items: center; gap: .3rem; }
.lucid-chip {
  font-size: .72rem; padding: .2rem .55rem; border-radius: 999px;
  border: 1px solid var(--color-base-300); text-decoration: none; color: inherit;
}
.dark .lucid-chip { border-color: var(--color-base-700); }
.lucid-chip:hover { border-color: var(--color-primary-500); }
.lucid-chip.is-active {
  background: var(--color-primary-500);
  border-color: var(--color-primary-500);
  color: white;
}
.lucid-check { display: flex; align-items: center; gap: .4rem; font-size: .8rem; white-space: nowrap; }

/* ------------------------------------------------------------------ plan detail
   The panel behind a cockpit row. It sits inside the table, so it has to look
   like a drawer rather than another row of data — hence the inset background
   and the left rule tying it to the row above. */
.lucid-cell-expand { white-space: nowrap; }
.lucid-expand {
  border: 0; background: none; cursor: pointer; font-size: 1rem; line-height: 1;
  padding: .1rem .35rem; margin-inline-end: .25rem; border-radius: .25rem;
  color: var(--color-base-500);
}
.lucid-expand:hover { background: color-mix(in oklab, var(--color-primary-500) 14%, transparent); }
.lucid-expand[aria-expanded="true"] { color: var(--color-primary-500); }

.lucid-detail-row > td { padding: 0 !important; background: color-mix(in oklab, var(--color-base-500) 6%, transparent); }
.lucid-detail-slot { padding: 1rem 1rem 1rem 2.25rem; border-inline-start: 3px solid var(--color-primary-500); }
.lucid-detail { display: grid; gap: 1.25rem; }
.lucid-detail-block { display: grid; gap: .4rem; }
.lucid-detail-head { display: flex; align-items: baseline; gap: 1rem; flex-wrap: wrap; }
.lucid-detail-legend { display: flex; gap: .75rem; font-size: .7rem; opacity: .75; margin-inline-start: auto; }
.lucid-swatch { display: inline-block; width: .6rem; height: .6rem; border-radius: .15rem; margin-inline-end: .3rem; }

/* One column per month. Bars overlap rather than stack: plan and actual are two
   answers to the same question, and stacking them would read as a sum. */
.lucid-mstrip { display: flex; gap: .35rem; align-items: flex-end; height: 7rem; }
.lucid-mcol { flex: 1; display: flex; flex-direction: column; height: 100%; }
.lucid-mcol.is-closed { opacity: .38; }
.lucid-mcol-stack { position: relative; flex: 1; display: flex; align-items: flex-end; gap: 2px; }
.lucid-mcol-bar { flex: 1; min-height: 2px; border-radius: .15rem .15rem 0 0; }
.lucid-mcol-tick { position: absolute; left: 0; right: 0; height: 2px; }
.lucid-mcol-label { font-size: .62rem; text-align: center; opacity: .65; padding-top: .25rem; }

.lucid-swatch[data-kind="plan"],     .lucid-mcol-bar[data-kind="plan"]     { background: color-mix(in oklab, var(--color-primary-500) 55%, transparent); }
.lucid-swatch[data-kind="preorder"], .lucid-mcol-bar[data-kind="preorder"] { background: color-mix(in oklab, var(--lucid-warn) 65%, transparent); }
.lucid-swatch[data-kind="actual"],   .lucid-mcol-bar[data-kind="actual"]   { background: var(--color-base-600); }
.lucid-swatch[data-kind="proposed"], .lucid-mcol-tick[data-kind="proposed"]{ background: var(--lucid-danger); }

.lucid-detail-drift { display: flex; gap: 2rem; align-items: center; flex-wrap: wrap; }
.lucid-detail-drift.is-off .lucid-detail-ratio { color: var(--lucid-danger); }
.lucid-detail-ratio { font-size: 1.35rem; font-weight: 600; }
.lucid-metric-sm { font-size: 1.35rem; font-weight: 600; }
.lucid-detail-windows { list-style: none; padding: 0; margin: 0; display: grid; gap: .3rem; }

/* A scenario has to be visibly not-the-live-plan, or somebody edits the wrong
   one for twenty minutes before noticing. */
.lucid-scenario-note { border-inline-start: 3px solid var(--lucid-warn); }
.lucid-plan-actions { display: flex; gap: .5rem; align-items: center; }
.lucid-chip.is-selected { border-color: var(--lucid-ok); font-weight: 600; }


/* A caveat that changes what the numbers beside it mean.
 *
 * Not a warning — nothing is broken — but the forecast-accuracy tiles read as
 * findings ("0% off plan") when they are sometimes identities, and a reader who
 * misses that draws exactly the wrong conclusion. Placed above the numbers
 * rather than under them for the same reason. */
.lucid-note {
  border-left: 3px solid var(--lucid-warn);
  background: color-mix(in oklab, var(--lucid-warn) 7%, transparent);
  padding: .6rem .8rem; border-radius: .35rem;
  font-size: .8rem; line-height: 1.45;
}
.lucid-note > div + div { margin-top: .45rem; }


/* Mid-year, the year total is not the thing you choose — it is settled plus
 * what you choose. Showing the sum as a consequence of the editable half is
 * the whole point: an annual box in August reads as control over the year and
 * gives you control over about a third of it. */
.lucid-split { display: flex; align-items: center; justify-content: flex-end; gap: .3rem; }
.lucid-split-sold {
  display: inline-flex; flex-direction: column; align-items: flex-end;
  font-variant-numeric: tabular-nums; opacity: .55; line-height: 1;
}
.lucid-split-sold i { font-style: normal; font-size: .58rem; text-transform: uppercase; letter-spacing: .04em; }
.lucid-split-plus { opacity: .4; }
.lucid-split-year { font-size: .66rem; opacity: .6; text-align: right; margin-top: .15rem; }
.lucid-split-year b { font-variant-numeric: tabular-nums; opacity: .95; }

/* The chart mixes a planned side with a committed one. Amber rather than grey:
 * it is not a footnote, it is the reason the balance looks the way it does. */
.lucid-basis-note { color: var(--lucid-warn); opacity: .85; }
.lucid-basis-note a { text-decoration: underline; }

/* Offer windows, on the collapsed row. "1sp · 2psp" is deliberately terse: it
 * has to fit beside the channel and be scannable down sixty rows. Red when
 * there are none, because that line cannot resolve at all. */
.lucid-windows {
  display: inline-block; margin-left: .4rem; padding: .05rem .3rem;
  font-size: .6rem; font-variant-numeric: tabular-nums; letter-spacing: .02em;
  border-radius: .25rem; opacity: .75; vertical-align: 1px;
  background: color-mix(in oklab, var(--color-base-500) 14%, transparent);
}
.dark .lucid-windows { background: color-mix(in oklab, var(--color-base-100) 10%, transparent); }
/* No window is not "planned at zero" — the line cannot resolve at all (C9), so
 * it reads as the failure it is rather than as a quiet count of nothing. */
.lucid-windows.is-missing {
  color: var(--lucid-danger); opacity: 1; font-weight: 600;
  background: color-mix(in oklab, var(--lucid-danger) 16%, transparent);
}

/* The two comparison curves: this garment past, and the one it is modelled on.
 * Dots rather than a drawn line — twelve of them read as a curve, cost no
 * chart library, and never disagree with the bar they sit above. */
.lucid-mcol-dot {
  position: absolute; left: 50%; width: .34rem; height: .34rem;
  margin-left: -.17rem; margin-bottom: -.17rem; border-radius: 50%;
  pointer-events: auto;
}
.lucid-mcol-dot[data-kind=history] { background: var(--color-base-400); }
.lucid-mcol-dot[data-kind=reference] {
  background: transparent; border: 1.5px solid var(--lucid-warn);
}
.lucid-swatch[data-kind=history] { background: var(--color-base-400); }
.lucid-swatch[data-kind=reference] {
  background: transparent; border: 1.5px solid var(--lucid-warn);
}

/* A preorder month is a different kind of month, not a quieter one: the orders
 * land here and the goods leave later (C1). Hatched so the strip shows when the
 * campaign was open without needing the list underneath. */
.lucid-mcol.is-presale .lucid-mcol-stack {
  background-image: repeating-linear-gradient(
    45deg, transparent, transparent 3px,
    color-mix(in oklab, var(--lucid-warn) 14%, transparent) 3px,
    color-mix(in oklab, var(--lucid-warn) 14%, transparent) 6px);
}

.lucid-shape-bar { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin-top: .6rem; }
.lucid-shape-pick { display: flex; align-items: center; gap: .35rem; margin-left: auto; }
.lucid-shape-pick .lucid-select { font-size: .72rem; padding: .1rem .3rem; }

/* ---------------------------------------------------------------- the product row
   The cockpit is one row per garment; its channels live in a panel underneath.
   That panel is rendered with the page and merely hidden, because its inputs
   are what the form submits — a row nobody opened still has to save. */

.lucid-channels-row > td,
tr.js-channels-row > td {
  padding: 0 !important;
  background: color-mix(in oklab, var(--color-base-500) 6%, transparent);
}
.lucid-channel-table { width: 100%; margin: 0 1rem 1rem 2.25rem; width: calc(100% - 3.25rem); }
.lucid-table-tight th, .lucid-table-tight td { padding-block: .3rem; font-size: .8rem; }
.lucid-channel-table thead th { font-size: .68rem; text-transform: uppercase; opacity: .6; }

/* Stacked bands: one per channel, offset by the running total beneath it, so a
   column's height is the production run and each band is where it goes. Unlike
   the single-line strip above — where plan and actual overlap because they are
   two answers to one question — these genuinely sum. */
.lucid-mcol-band {
  position: absolute;
  left: 0;
  right: 0;
  min-height: 2px;
  border-radius: .15rem .15rem 0 0;
}
.lucid-mcol-band[data-band="0"], .lucid-swatch[data-band="0"] { background: color-mix(in oklab, var(--color-primary-500) 70%, transparent); }
.lucid-mcol-band[data-band="1"], .lucid-swatch[data-band="1"] { background: color-mix(in oklab, var(--lucid-warn) 70%, transparent); }
.lucid-mcol-band[data-band="2"], .lucid-swatch[data-band="2"] { background: color-mix(in oklab, var(--lucid-ok) 60%, transparent); }
.lucid-mcol-band[data-band="3"], .lucid-swatch[data-band="3"] { background: color-mix(in oklab, var(--color-base-500) 55%, transparent); }
/* A fifth channel is not a design, it is a warning — but it must still draw. */
.lucid-mcol-band[data-band="4"], .lucid-swatch[data-band="4"] { background: color-mix(in oklab, var(--lucid-danger) 55%, transparent); }
.lucid-mcol-tick[data-kind="actual"] { background: var(--color-base-700); }
/* Last year on the same axis: solid where it sold, dashed where it is still plan. */
.lucid-mcol-tick[data-kind="last-year"] { height: 0; border-top: 2px solid var(--color-base-400); }
.lucid-mcol-tick[data-kind="last-year"].is-planned { border-top-style: dashed; }
.lucid-swatch[data-kind="last-year"] { background: var(--color-base-400); }
/* The preorder slice sits at the bottom of its channel's band, striped. */
.lucid-mcol-preorder {
  position: absolute; left: 0; right: 0; bottom: 0;
  background: repeating-linear-gradient(135deg, rgba(0,0,0,.28) 0 3px, transparent 3px 6px);
}
.lucid-swatch[data-kind="preorder-part"] {
  background: repeating-linear-gradient(135deg, var(--color-base-500) 0 2px, transparent 2px 4px);
}

/* The product row reads as the heading of its own block. */
tr.js-product-row > td { font-weight: 500; }
tr.js-product-row .lucid-basis { font-weight: 400; }

/* ------------------------------------------------------------- data quality
   Severity is a colour and a rank at once: blocked is the only one that means
   "this row is not in the database", so it is the only one that reads as red.
   Assumed is amber rather than grey on purpose — a derived value looks exactly
   like a stated one everywhere else in the app. */

.lucid-steps { display: flex; gap: .5rem; flex-wrap: wrap; }
.lucid-step {
  flex: 1 1 7rem; min-width: 7rem; padding: .6rem .7rem; border-radius: .4rem;
  text-decoration: none; color: inherit;
  background: color-mix(in oklab, var(--color-base-500) 8%, transparent);
  border-inline-start: 3px solid var(--color-base-400);
}
.lucid-step:hover { background: color-mix(in oklab, var(--color-primary-500) 12%, transparent); }
.lucid-step-count { font-size: 1.35rem; font-weight: 600; line-height: 1.1; }
.lucid-step-label { font-size: .68rem; opacity: .7; text-transform: uppercase; letter-spacing: .02em; }
.lucid-step[data-worst="blocked"]  { border-inline-start-color: var(--lucid-danger); }
.lucid-step[data-worst="degraded"] { border-inline-start-color: var(--lucid-warn); }
.lucid-step[data-worst="assumed"]  { border-inline-start-color: #d97706; }
.lucid-step[data-worst="ignored"]  { border-inline-start-color: var(--color-base-400); }

.lucid-issue { border-inline-start: 3px solid var(--color-base-400); }
.lucid-issue[data-severity="blocked"]  { border-inline-start-color: var(--lucid-danger); }
.lucid-issue[data-severity="degraded"] { border-inline-start-color: var(--lucid-warn); }
.lucid-issue[data-severity="assumed"]  { border-inline-start-color: #d97706; }
.lucid-issue-head { display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap; }
.lucid-issue-text { flex: 1; }
.lucid-issue-count {
  font-variant-numeric: tabular-nums; font-weight: 600;
  padding: .05rem .45rem; border-radius: .3rem;
  background: color-mix(in oklab, var(--color-base-500) 14%, transparent);
}
.lucid-issue-step { font-size: .66rem; text-transform: uppercase; opacity: .6; letter-spacing: .03em; }
.lucid-issue-why { font-size: .8rem; opacity: .8; margin-top: .35rem; }
.lucid-issue-fix { font-size: .8rem; margin-top: .25rem; color: var(--color-primary-500); }
.lucid-issue-rows summary { font-size: .72rem; opacity: .65; cursor: pointer; margin-top: .4rem; }
.lucid-pill[data-severity="blocked"]  { background: color-mix(in oklab, var(--lucid-danger) 22%, transparent); }
.lucid-pill[data-severity="degraded"] { background: color-mix(in oklab, var(--lucid-warn) 25%, transparent); }
.lucid-pill[data-severity="assumed"]  { background: color-mix(in oklab, #d97706 25%, transparent); }
.lucid-pill[data-severity="ignored"]  { background: color-mix(in oklab, var(--color-base-500) 18%, transparent); }
.lucid-btn-ghost.is-active { background: color-mix(in oklab, var(--color-primary-500) 18%, transparent); }

/* Setup instructions: commands are meant to be copied, so they get room and a
   background rather than being squeezed into the body text. */
.lucid-code {
  background: color-mix(in oklab, var(--color-base-500) 12%, transparent);
  border-radius: .4rem; padding: .7rem .9rem; font-size: .78rem;
  overflow-x: auto; white-space: pre; line-height: 1.5;
}

/* --------------------------------------------------------- colourway split
   What a production run becomes. One bar per colourway, sharing the run's
   scale, because the question this answers — "how many Ecru do I cut" — is
   comparative: the interesting fact is that Ecru is half of it. */
.lucid-cw { display: flex; flex-direction: column; gap: .3rem; }
.lucid-cw-item {
  display: grid; grid-template-columns: 1fr 8rem 3.5rem; align-items: center; gap: .75rem;
}
.lucid-cw-bar {
  height: 10px; border-radius: 99px;
  background: color-mix(in oklab, currentColor 8%, transparent);
  overflow: hidden;
}
.lucid-cw-bar i {
  display: block; height: 100%; border-radius: 99px;
  background: color-mix(in oklab, var(--color-primary-500) 70%, transparent);
}
.lucid-cw-name { font-size: .8rem; opacity: .8; }
.lucid-cw-units { font-size: .85rem; font-weight: 600; text-align: right; }

/* ------------------------------------------------------------- month pins
   Closed by default. Pinning a month is a deliberate, occasional act, and
   twelve permanently open boxes per channel would bury the annual number the
   cockpit exists to show. */
.lucid-pins > summary {
  cursor: pointer; display: flex; align-items: baseline; gap: .6rem;
  list-style: none;
}
.lucid-pins > summary::-webkit-details-marker { display: none; }
.lucid-pins > summary::before { content: "\203A"; display: inline-block; opacity: .5; }
.lucid-pins[open] > summary::before { transform: rotate(90deg); }
.lucid-pinrow { margin-bottom: 1rem; }
.lucid-pinrow-head { display: flex; align-items: baseline; gap: .5rem; margin-bottom: .35rem; }
.lucid-pingrid {
  display: grid; grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: .3rem; margin-bottom: .5rem;
}
.lucid-pingrid label { display: flex; flex-direction: column; gap: .15rem; }
.lucid-pingrid span {
  font-size: 10px; text-transform: uppercase; letter-spacing: .04em; opacity: .6; text-align: center;
}
.lucid-pingrid input {
  width: 100%; padding: .25rem .2rem; text-align: center; font-size: .8rem;
  border: 1px solid color-mix(in oklab, currentColor 20%, transparent);
  border-radius: 6px; background: transparent; color: inherit;
}
.lucid-pingrid input::placeholder { opacity: .35; }
.lucid-btn-sm { padding: .3rem .7rem; font-size: .78rem; }

@media (max-width: 900px) {
  .lucid-pingrid { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .lucid-cw-item { grid-template-columns: 1fr 5rem 3rem; }
}
/* A colourway with no history is still real — it just has nothing to say yet. */
.lucid-cw-item.is-quiet { opacity: .45; }
.lucid-pinsub {
  font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
  opacity: .55; margin: .5rem 0 .25rem;
}
.lucid-pingrid.is-preorder input {
  border-style: dashed;
}
.lucid-pinnote { font-size: .78rem; opacity: .7; margin-left: .6rem; }

/* The curve's own number, under each pin box. Under and not inside: a
   placeholder disappears at the first keystroke — the moment you are deciding
   whether to disagree with it — and a grey number inside an input reads as a
   value somebody already entered. */
.lucid-pingrid label { position: relative; }
.lucid-hint {
  display: block; text-align: center; font-style: normal;
  font-size: .62rem; opacity: .5; font-variant-numeric: tabular-nums;
  margin-top: .1rem; cursor: help;
}
.lucid-pingrid label.is-pinned .lucid-hint { opacity: .75; }
.lucid-pingrid label.is-pinned input { border-color: var(--color-primary-500); }

/* ------------------------------------------------------------------ stock sheet
   One table that reads and counts. The count columns exist in the markup all
   the time and only show in count mode, so turning it on never re-renders. */
.lucid-stock .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.lucid-stock-tools { align-items: center; margin-bottom: .75rem; }
.lucid-stock-tools .lucid-tabs { margin-bottom: 0; }
.lucid-stock-tools label.lucid-check { display: flex; margin: 0; opacity: .8; font-size: .8rem; }
.lucid-stock-tools input[type="search"] {
    border: 1px solid var(--color-base-200); background: var(--color-base-50);
    border-radius: .375rem; padding: .35rem .55rem; font-size: .8125rem; min-width: 14rem;
}
.dark .lucid-stock-tools input[type="search"] { border-color: var(--color-base-700); background: var(--color-base-900); }
.lucid-stock-spacer { flex: 1; }
.lucid-stock-head td { padding-top: .9rem; font-size: .8rem; }
.lucid-stock-table tr[data-row] td:first-child { padding-left: 1.4rem; }
.lucid-spark { color: var(--color-primary-500); display: block; }
.lucid-stock .lucid-count-col { display: none; }
.lucid-stock.is-counting .lucid-count-col { display: table-cell; }
.lucid-stock .js-count { width: 6.5rem; text-align: right; }
.lucid-stock tr.is-counted .js-diff { color: var(--lucid-ok); font-weight: 600; }
.lucid-stock tr.is-off .js-diff { color: var(--lucid-warn); }
.lucid-stock tr.is-bad .js-diff, .lucid-stock tr.is-bad .js-count { color: var(--lucid-danger); }
.lucid-stock tr.is-counted td { background: color-mix(in oklab, var(--color-primary-500) 6%, transparent); }
.lucid-stock-savebar {
    display: none; position: sticky; bottom: 0; z-index: 5; margin-top: 1rem;
    justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap;
    padding: .75rem 1rem; border-radius: .5rem; font-size: .85rem;
    background: var(--color-base-50); border: 1px solid var(--color-primary-500);
    box-shadow: 0 -4px 16px rgb(0 0 0 / .08);
}
.dark .lucid-stock-savebar { background: var(--color-base-900); }
.lucid-stock.is-counting .lucid-stock-savebar { display: flex; }
.lucid-stock-savebar .lucid-bar { margin: 0; }
.lucid-stock-savebar .lucid-btn:disabled { opacity: .45; cursor: not-allowed; }
/* ------------------------------------------------------------------ margins
   One small card per garment; the percentage is the thing the eye lands on,
   coloured against the period's own weighted margin. A card with no known
   cost is greyed, never shown as a margin. */
.lucid-margins-note { font-size: .8rem; opacity: .75; margin: 0 0 .75rem; max-width: 70rem; }
.lucid-margins-tools { align-items: center; margin-bottom: .75rem; }
.lucid-margins-tools .lucid-tabs { margin-bottom: 0; }
.lucid-margin-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: .75rem; }
.lucid-margin-card {
    border: 1px solid var(--color-base-200); border-radius: .5rem; padding: .8rem .9rem;
    background: var(--color-base-50); display: flex; flex-direction: column; gap: .35rem; min-width: 0;
}
.dark .lucid-margin-card { border-color: var(--color-base-800); background: var(--color-base-900); }
.lucid-margin-head { display: flex; align-items: center; gap: .55rem; min-width: 0; }
.lucid-margin-head img, .lucid-margin-nothumb {
    width: 36px; height: 36px; object-fit: cover; border-radius: .375rem; flex: none;
    background: color-mix(in oklab, var(--color-base-500) 15%, transparent);
}
.lucid-margin-name { font-weight: 600; font-size: .9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lucid-margin-pct { font-size: 1.75rem; font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; }
.lucid-margin-card.is-good .lucid-margin-pct, .lucid-margin-tone.is-good { color: var(--lucid-ok); }
.lucid-margin-card.is-ok .lucid-margin-pct, .lucid-margin-tone.is-ok { color: var(--lucid-warn); }
.lucid-margin-card.is-bad .lucid-margin-pct, .lucid-margin-tone.is-bad { color: var(--lucid-danger); }
.lucid-margin-bar { height: 4px; border-radius: 2px; background: color-mix(in oklab, var(--color-base-500) 18%, transparent); }
.lucid-margin-bar span { display: block; height: 100%; border-radius: 2px; background: currentColor; }
.lucid-margin-card.is-good .lucid-margin-bar { color: var(--lucid-ok); }
.lucid-margin-card.is-ok .lucid-margin-bar { color: var(--lucid-warn); }
.lucid-margin-card.is-bad .lucid-margin-bar { color: var(--lucid-danger); }
.lucid-margin-card.is-unknown { opacity: .55; }
.lucid-margin-card.is-unknown .lucid-margin-pct { font-size: 1.1rem; font-weight: 600; padding: .3rem 0; }
.lucid-margin-why { font-size: .72rem; opacity: .75; }
.lucid-margin-figures { display: grid; grid-template-columns: repeat(3, auto); gap: .25rem .6rem; margin: .2rem 0 0; }
.lucid-margin-figures dt { font-size: .64rem; text-transform: uppercase; letter-spacing: .04em; opacity: .6; }
.lucid-margin-figures dd { margin: 0; font-size: .82rem; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.lucid-margin-detail summary { font-size: .75rem; opacity: .7; cursor: pointer; }
.lucid-margin-card:has(.lucid-margin-detail[open]) { grid-column: span 2; }
.lucid-margin-detail table { margin-top: .35rem; font-size: .75rem; }
.lucid-margin-detail .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.lucid-margin-detail tr.is-unknown { opacity: .6; }
/* Sales with no cost: excluded or included. Each figure that differs is in the
   page twice; the container's class says which one shows. */
.lucid-margins:not(.is-including) [data-show="in"],
.lucid-margins.is-including [data-show="ex"] { display: none !important; }
.lucid-uncosted {
    margin: 0 0 1rem; padding: .75rem .9rem; border-radius: .5rem; font-size: .85rem;
    border: 1px solid color-mix(in oklab, var(--lucid-warn) 45%, transparent);
    border-left: 4px solid var(--lucid-warn);
    background: color-mix(in oklab, var(--lucid-warn) 9%, transparent);
}
.lucid-uncosted-head { display: flex; gap: .75rem 1.25rem; align-items: center; justify-content: space-between; flex-wrap: wrap; }
.lucid-uncosted-msg { flex: 1 1 32rem; }
.lucid-uncosted-msg a { color: var(--color-primary-600); white-space: nowrap; }
.dark .lucid-uncosted-msg a { color: var(--color-primary-400); }
.lucid-uncosted-msg a:hover { text-decoration: underline; }
.lucid-uncosted-toggle { display: flex; align-items: center; gap: .5rem; font-size: .78rem; }
.lucid-uncosted-toggle > span { opacity: .75; }
.lucid-uncosted-toggle .lucid-tabs { margin-bottom: 0; }
.lucid-uncosted-mode { margin: .45rem 0 0; font-size: .78rem; opacity: .8; }
.lucid-uncosted-list summary { margin-top: .45rem; font-size: .78rem; cursor: pointer; opacity: .8; }
.lucid-uncosted-list table { margin-top: .4rem; font-size: .78rem; }
.lucid-uncosted-list .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.lucid-uncosted-list td.lucid-margin-why { max-width: 32rem; }
/* ---------------------------------------------------------------- budgets
   The budget grid (money/budget_grid.html) and the budget-vs-actual table on
   Money & scenarios. Numbers right-aligned and tabular, because a column of
   euros is read by its last digits. */
.lucid-budget td, .lucid-budget th { white-space: nowrap; }
.lucid-budget td.num, .lucid-budget th.num { text-align: right; font-variant-numeric: tabular-nums; }
.lucid-budget input.lucid-budget-cell { width: 5rem; text-align: right; font-variant-numeric: tabular-nums; }
.lucid-budget input.lucid-budget-small { width: 3.8rem; text-align: right; }
.lucid-budget select {
    font-size: .75rem; padding: .3rem; border-radius: .375rem;
    border: 1px solid var(--color-base-200); background: transparent;
}
.dark .lucid-budget select { border-color: var(--color-base-700); }
/* Changed since the page loaded and not saved yet — the grid never autosaves.
   Prefixed with .lucid-card to outrank the generic card-input rule above. */
.lucid-card .lucid-budget input.is-dirty, .lucid-card .lucid-budget select.is-dirty,
.dark .lucid-card .lucid-budget input.is-dirty, .dark .lucid-card .lucid-budget select.is-dirty {
    border-color: var(--color-primary-500);
    background: color-mix(in oklab, var(--color-primary-500) 12%, transparent);
}
.lucid-budget tr.is-total td { font-weight: 600; border-top-width: 2px; }
/* Months still ahead: their "actual" is what is recorded so far, not final. */
.lucid-budget .is-future { background: color-mix(in oklab, var(--color-base-500) 7%, transparent); }
.lucid-budget tr.is-sub td { border-top: 0; padding-top: .15rem; padding-bottom: .15rem; font-size: .78rem; }
.lucid-budget tr.is-sub td:first-child { opacity: .6; padding-left: 1.4rem; }
.lucid-dirty-note { font-size: .8rem; color: var(--color-primary-600); visibility: hidden; }
.lucid-dirty-note.is-shown { visibility: visible; }

/* ------------------------------------------------------------ data quality
   insights/quality.html: the share of checks that pass, the first five things
   to fix, and import lines already fixed (struck through, not hidden: "what
   was fixed since the last import" is part of the answer). */
.lucid-dq-bar { height: .4rem; border-radius: 999px; background: color-mix(in oklab, var(--color-base-500) 18%, transparent); overflow: hidden; }
.lucid-dq-bar span { display: block; height: 100%; background: var(--lucid-ok); }
.lucid-dq-first { list-style: decimal; padding-left: 1.4rem; font-size: .875rem; }
.lucid-dq-first li { margin: .45rem 0; }
.lucid-dq-fix { padding-left: .7rem; border-left: 2px solid var(--color-primary-500); }
.lucid-dq-lines { list-style: disc; padding-left: 1.2rem; margin-top: .3rem; }
.lucid-dq-lines li.is-fixed { text-decoration: line-through; opacity: .55; }
.lucid-dq a:not(.lucid-tab):not(.lucid-btn):not(.lucid-btn-ghost) { color: var(--color-primary-600); }
.dark .lucid-dq a:not(.lucid-tab):not(.lucid-btn):not(.lucid-btn-ghost) { color: var(--color-primary-400); }
.lucid-dq a:not(.lucid-tab):hover { text-decoration: underline; }


/* ---- plans financiers -------------------------------------------------------
   planning/financial_plans.html (cards, create panel) and financial_plan.html
   (title edited in place, years, statements per year, months as the detail).
   Real and planned read from the month columns: closed months greyed, a
   marker on the first planned one. */
.lucid-fp-intro { display: flex; gap: 1rem; align-items: flex-start; justify-content: space-between; flex-wrap: wrap; }
.lucid-fp-intro p { max-width: 52rem; }
[class*="lucid-fp"] [hidden], [class*="lucid-fp"][hidden] { display: none !important; }

.lucid-fp-span {
    display: inline-block; font-size: .72rem; font-weight: 600; padding: .1rem .55rem; border-radius: 999px;
    background: color-mix(in oklab, var(--color-primary-500) 12%, transparent); color: var(--color-primary-700);
    white-space: nowrap;
}
.dark .lucid-fp-span { color: var(--color-primary-300); }

/* cards */
.lucid-fp-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 380px), 1fr)); gap: 1rem; }
.lucid-fp-kpis { grid-template-columns: repeat(auto-fit, minmax(165px, 1fr)); }
.lucid-fp-kpis .lucid-metric { font-size: 1.2rem; white-space: nowrap; }
.lucid-fp-card { display: flex; flex-direction: column; transition: border-color .15s, box-shadow .15s; }
.lucid-fp-card:hover { border-color: var(--color-primary-500); box-shadow: 0 2px 10px rgb(0 0 0 / .06); }
.lucid-fp-card-head { display: flex; justify-content: space-between; gap: .75rem; align-items: baseline; }
.lucid-fp-card-name { font-size: 1.05rem; font-weight: 600; }
.lucid-fp-figs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .75rem; margin-top: 1rem; }
.lucid-fp-fig { font-size: 1.05rem; font-weight: 600; white-space: nowrap; }
.lucid-fp-figs .lucid-label { min-height: 2.3em; }
.lucid-fp-spark-wrap { margin-top: .9rem; }
.lucid-fp-spark { width: 100%; height: 56px; overflow: visible; }
.lucid-fp-spark-zero { stroke: var(--lucid-danger); stroke-opacity: .45; stroke-dasharray: 3 3; stroke-width: 1; vector-effect: non-scaling-stroke; }
.lucid-fp-spark-split { stroke: currentColor; stroke-opacity: .25; stroke-dasharray: 2 3; stroke-width: 1; vector-effect: non-scaling-stroke; }
.lucid-fp-spark circle { fill: currentColor; }
.lucid-fp-spark circle.is-neg { fill: var(--lucid-danger); }
.lucid-fp-spark-legend { display: flex; justify-content: space-between; margin-top: .2rem; }
.lucid-fp-card-plans { margin-top: .9rem; padding-top: .7rem; border-top: 1px solid var(--color-base-200); font-size: .8rem; }
.dark .lucid-fp-card-plans { border-color: var(--color-base-800); }
.lucid-fp-card-plans li { display: flex; gap: .6rem; padding: .1rem 0; }
.lucid-fp-card-plans li span { opacity: .75; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lucid-fp-empty { text-align: center; padding: 2.5rem 1.25rem; }
.lucid-fp-empty p { max-width: 34rem; margin-left: auto; margin-right: auto; }
.lucid-fp-empty-mark {
    width: 2.75rem; height: 2.75rem; border-radius: 999px; margin: 0 auto .75rem; display: grid; place-items: center;
    font-weight: 700; font-size: 1.2rem; color: var(--color-primary-600);
    background: color-mix(in oklab, var(--color-primary-500) 12%, transparent);
}

/* the create panel and the in-place forms */
.lucid-fp-new { max-width: 60rem; }
.lucid-fp-new-head, .lucid-fp-new-foot { display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap; }
.lucid-fp-new-head { margin-bottom: .9rem; }
.lucid-fp-new-foot { justify-content: flex-start; margin-top: 1.1rem; }
.lucid-fp-fields { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .8rem 1rem; }
.lucid-fp-field { display: flex; flex-direction: column; gap: .3rem; font-size: .78rem; }
.lucid-fp-field > span { opacity: .7; }
.lucid-fp-field.is-wide { grid-column: span 3; }
@media (min-width: 900px) { .lucid-fp-field.is-wide { grid-column: span 3; } }
.lucid-fp-field input, .lucid-fp-field textarea, .lucid-fp-field select { width: 100%; }
.lucid-fp-field textarea {
    border: 1px solid var(--color-base-200); background: var(--color-base-50); border-radius: .375rem;
    padding: .35rem .55rem; font-size: .8125rem; color: inherit;
}
.dark .lucid-fp-field textarea { border-color: var(--color-base-700); background: var(--color-base-950); }
.lucid-fp-pick { display: grid; gap: .5rem; }
.lucid-fp-pick-row { display: grid; grid-template-columns: 4rem minmax(0, 26rem); gap: .2rem 1rem; align-items: center; }
.lucid-fp-pick-row .lucid-fp-hypo { grid-column: 2; }
.lucid-fp-pick-year { font-weight: 600; }
.lucid-fp-hypo {
    padding: .35rem .6rem; border-radius: .375rem; border-left: 3px solid var(--lucid-warn);
    background: color-mix(in oklab, var(--lucid-warn) 9%, transparent);
}
.lucid-fp-title { margin-bottom: 1rem; }
.lucid-fp-title-show { display: flex; gap: .75rem; align-items: center; flex-wrap: wrap; }
.lucid-fp-addnote { opacity: .6; }
.lucid-fp-addnote:hover { opacity: 1; color: var(--color-primary-600); }
.lucid-fp-title-form { display: grid; gap: .7rem; max-width: 44rem; margin-top: .75rem; }
.lucid-fp-title-form .lucid-fp-name-input { font-size: 1.05rem !important; font-weight: 600; }
.lucid-fp-title-actions { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
.lucid-fp-delete { margin-left: auto; color: var(--lucid-danger); }
@media (max-width: 640px) {
    .lucid-fp-fields, .lucid-fp-figs { grid-template-columns: minmax(0, 1fr); }
    .lucid-fp-field.is-wide { grid-column: auto; }
}

/* the years */
.lucid-fp-years-head { display: flex; justify-content: space-between; gap: .75rem; align-items: center; flex-wrap: wrap; }
.lucid-fp-years-tools { display: flex; gap: .4rem; align-items: center; flex-wrap: wrap; }
.lucid-fp-years-tools form { display: inline; }
.lucid-fp-span-edit { position: relative; }
.lucid-fp-span-edit summary { list-style: none; cursor: pointer; display: inline-block; }
.lucid-fp-span-edit summary::-webkit-details-marker { display: none; }
.lucid-fp-span-form {
    position: absolute; right: 0; top: calc(100% + .35rem); z-index: 5; width: 20rem;
    display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; padding: .8rem; font-size: .8rem;
    border: 1px solid var(--color-base-200); border-radius: .5rem; background: var(--color-base-50);
    box-shadow: 0 6px 20px rgb(0 0 0 / .12);
}
.dark .lucid-fp-span-form { border-color: var(--color-base-700); background: var(--color-base-900); }
.lucid-fp-span-form .lucid-select { min-width: 0; }
.lucid-fp-years { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: .75rem; }
.lucid-fp-year-num { font-weight: 600; margin-bottom: .2rem; }
.lucid-fp-year .lucid-select { width: 100%; }

/* the statements */
.lucid-fp-h2 { font-size: 1rem; font-weight: 600; }
.lucid-fp-statement-head { display: flex; justify-content: space-between; align-items: baseline; gap: .75rem; flex-wrap: wrap; margin-bottom: .6rem; }
.lucid-fp-statement-tools { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; }
.lucid-fp-hypotheses { list-style: disc; padding-left: 1.2rem; }
.lucid-fp-hypotheses li { margin: .3rem 0; }
.lucid-fp-table { font-size: .8rem; white-space: nowrap; }
.lucid-fp-table td, .lucid-fp-table th { padding: .32rem .5rem; text-align: right; }
.lucid-fp-table td:first-child, .lucid-fp-table th:first-child {
    text-align: left; position: sticky; left: 0; z-index: 1;
    background: var(--color-base-50); min-width: 17rem;
}
.dark .lucid-fp-table td:first-child, .dark .lucid-fp-table th:first-child { background: var(--color-base-900); }
.lucid-fp-annual td:not(:first-child), .lucid-fp-annual th:not(:first-child) { min-width: 7.5rem; }
.lucid-fp-plan-name {
    font-weight: 400; text-transform: none; letter-spacing: 0; opacity: .8; font-size: .68rem;
    max-width: 8.5rem; margin-left: auto; overflow: hidden; text-overflow: ellipsis;
}
.lucid-fp-code { display: inline-block; min-width: 2.6rem; font-variant-numeric: tabular-nums; opacity: .45; font-size: .72rem; }
.lucid-fp-table .is-total-col { font-weight: 600; border-left: 1px solid var(--color-base-300); }
.dark .lucid-fp-table .is-total-col { border-color: var(--color-base-700); }
.lucid-fp-table tr.is-head td { font-size: .68rem; text-transform: uppercase; letter-spacing: .04em; opacity: .7; padding-top: .9rem; text-align: left; }
.lucid-fp-table tr.is-line td:first-child { font-weight: 500; }
.lucid-fp-table tr.is-total td, .lucid-fp-table tr.is-balance td { font-weight: 700; border-top: 2px solid var(--color-base-300); }
.dark .lucid-fp-table tr.is-total td, .dark .lucid-fp-table tr.is-balance td { border-color: var(--color-base-700); }
.lucid-fp-table tr.is-strong td { font-size: .86rem; }
.lucid-fp-table tr.is-minor td, .lucid-fp-table tr.is-pct td { font-size: .74rem; opacity: .7; font-style: italic; }
.lucid-fp-table tr.is-detail { display: none; }
.lucid-fp-statement.is-detailed tr.is-detail { display: table-row; }
.lucid-fp-table tr.is-detail td { font-size: .74rem; opacity: .75; border-top-style: dotted; }
.lucid-fp-table tr.is-detail td:first-child { padding-left: 3.1rem; }
.lucid-fp-table .is-neg { color: var(--lucid-danger); }
.lucid-fp-table td.is-closed, .lucid-fp-table th.is-closed { background: color-mix(in oklab, var(--color-base-500) 8%, transparent); color: color-mix(in oklab, currentColor 70%, transparent); }
.lucid-fp-table .is-first { border-left: 2px solid var(--color-primary-500); }
.lucid-fp-table th.is-first { position: relative; padding-top: 1.1rem; }
.lucid-fp-from {
    position: absolute; top: .1rem; left: .35rem; font-size: .6rem; font-weight: 700; letter-spacing: .03em;
    color: var(--color-primary-600); text-transform: none;
}
.dark .lucid-fp-from { color: var(--color-primary-400); }
.lucid-fp-months > summary { list-style: revert; }

/* ---- sorties de production: en stock / commandé / à commander ------------ */
/* One stacked bar per sortie and per row. The three parts are a sum (they
   make the need), so they stack; the colours keep the tokens' meaning:
   covered (ok), on its way (info), still to do (warn). */
.lucid-stackbar {
    display: flex; height: .8rem; border-radius: 999px; overflow: hidden;
    background: var(--color-base-200); min-width: 6rem;
}
.dark .lucid-stackbar { background: var(--color-base-800); }
.lucid-stackbar.is-small { height: .45rem; }
.lucid-stackbar > span { display: block; height: 100%; }
.lucid-stackbar .is-stock, .lucid-sortie-legend i.is-stock, .lucid-sortie-figures i.is-stock { background: var(--lucid-ok); }
.lucid-stackbar .is-ordered, .lucid-sortie-legend i.is-ordered, .lucid-sortie-figures i.is-ordered { background: var(--lucid-info); }
.lucid-stackbar .is-todo, .lucid-sortie-legend i.is-todo, .lucid-sortie-figures i.is-todo { background: var(--lucid-warn); }
.lucid-sortie-legend { display: flex; flex-wrap: wrap; gap: 1rem; align-items: center; font-size: .78rem; }
.lucid-sortie-legend .lucid-label { margin-right: auto; }
.lucid-sortie-legend i, .lucid-sortie-figures i {
    display: inline-block; width: .6rem; height: .6rem; border-radius: 2px; margin-right: .35rem;
}
.lucid-sortie {
    display: grid; grid-template-columns: 12rem 8rem minmax(14rem, 1fr) 13rem;
    gap: .5rem 1.25rem; align-items: center; padding: .85rem .5rem;
    border-top: 1px solid var(--color-base-200); border-radius: .35rem;
}
.dark .lucid-sortie { border-top-color: var(--color-base-800); }
.lucid-sortie:hover { background: color-mix(in oklab, var(--color-primary-500) 6%, transparent); }
.lucid-sortie.is-open { box-shadow: inset 3px 0 0 var(--color-primary-500); }
.lucid-sortie-name { display: flex; flex-direction: column; gap: .15rem; align-items: flex-start; }
.lucid-sortie-total { white-space: nowrap; }
.lucid-sortie-figures { display: flex; flex-wrap: wrap; gap: .25rem 1rem; margin-top: .4rem; font-size: .8rem; font-variant-numeric: tabular-nums; }
.lucid-sortie-meta { font-size: .82rem; line-height: 1.6; }
.lucid-sortie-meta .lucid-label { display: inline-block; min-width: 7.5rem; }
@media (max-width: 900px) { .lucid-sortie { grid-template-columns: 1fr 1fr; } }
.lucid-sortie-detail > summary { display: flex; gap: .5rem; align-items: baseline; cursor: pointer; flex-wrap: wrap; }
.lucid-cover-table { white-space: nowrap; }
.lucid-cover-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.lucid-cover-table .bar { width: 6rem; }
.lucid-cover-table .bar .lucid-stackbar { min-width: 4.5rem; }
.lucid-cover-table td, .lucid-cover-table th { padding-left: .4rem; padding-right: .4rem; }
.lucid-cover-table .thumb { width: 2.5rem; padding-right: 0; }
.lucid-cover-table .name { white-space: normal; min-width: 11rem; }
.lucid-cover-orders { list-style: disc; padding-left: 1.2rem; }
.lucid-cover-orders li { margin: .2rem 0; }
