/* Saphirion component styles */
@import url("./tokens.css");

/* Cascade layer — see base.css / README.md §2.2. */
@layer base, components, motifs, utilities;

@layer components {

/* Buttons ---------------------------------------------------------------- */
/* IMPORTANT — usage guidance:
   Saphirion decks deliberately avoid buttons. Use cards, tiles, cream pills,
   and the pipeline component instead. Buttons live here for the NLPP product
   UI only (web app, opportunity tracker, partfinder). Don't put them on
   marketing or sales slides.                                                  */
.sph-btn {
  font-family: var(--sph-font-display);
  font-weight: var(--sph-weight-bold);
  font-size: var(--sph-fs-sm);
  letter-spacing: 0.04em;
  padding: 12px 22px;
  border-radius: var(--sph-radius-sm);
  border: 1px solid transparent;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  transition: background var(--sph-dur-fast) var(--sph-ease-standard),
              color var(--sph-dur-fast) var(--sph-ease-standard),
              border-color var(--sph-dur-fast) var(--sph-ease-standard),
              transform var(--sph-dur-fast) var(--sph-ease-standard);
  text-decoration: none;
  white-space: nowrap;
}
.sph-btn:active { transform: translateY(1px); }
.sph-btn:focus-visible {
  outline: 2px solid var(--sph-focus, var(--sph-primary-deep));
  outline-offset: 2px;
}
.sph-btn--primary   { background: var(--sph-dark); color: var(--sph-white); }
.sph-btn--primary:hover { background: #000; }
.sph-btn--accent    { background: var(--sph-interactive, var(--sph-primary-deep)); color: var(--sph-white); }
.sph-btn--accent:hover { background: var(--sph-interactive-hover, var(--sph-primary-deep)); }
.sph-btn--danger    { background: var(--sph-info); color: var(--sph-white); }
.sph-btn--danger:hover { background: #4a0000; }
.sph-btn--ghost     { background: transparent; color: var(--sph-text); border-color: var(--sph-border-strong); }
.sph-btn--ghost:hover { background: var(--sph-secondary); color: var(--sph-dark); }
/* Ghost on a DARK surface — white label + light hairline border. On hover it
   fills with the cream brand surface and the label flips to dark ink, so it
   stays readable. (A plain --ghost forced to white text via markup would keep
   white-on-cream on hover — unreadable; use this variant instead.) */
.sph-btn--ghost-on-dark       { background: transparent; color: var(--sph-white); border-color: rgba(221, 220, 197, 0.4); }
.sph-btn--ghost-on-dark:hover { background: var(--sph-secondary); color: var(--sph-dark); border-color: var(--sph-secondary); }
.sph-btn--link      { background: transparent; color: var(--sph-info); padding: 6px 0; border-radius:0; border-bottom: 1px solid currentColor; }
.sph-btn--sm { padding: 8px 14px; font-size: var(--sph-fs-xs); }
.sph-btn--lg { padding: 16px 28px; font-size: var(--sph-fs-base); }

/* Chips / Badges --------------------------------------------------------- */
.sph-badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px;
  font: var(--sph-weight-bold) var(--sph-fs-xs)/1 var(--sph-font-display);
  letter-spacing: 0.06em; text-transform: uppercase;
  border-radius: var(--sph-radius-pill);
  background: var(--sph-secondary); color: var(--sph-dark);
}
.sph-badge--primary { background: var(--sph-primary); color: #fff; }
.sph-badge--success { background: var(--sph-success); color: #fff; }
.sph-badge--warning { background: var(--sph-warning); color: var(--sph-dark); }
.sph-badge--danger  { background: var(--sph-danger);  color: #fff; }
.sph-badge--info    { background: var(--sph-info);    color: #fff; }
.sph-badge--ghost   { background: transparent; color: var(--sph-text); box-shadow: inset 0 0 0 1px var(--sph-border-strong); }

/* Cards ----------------------------------------------------------------- */
.sph-card {
  background: var(--sph-surface);
  border: 1px solid var(--sph-border);
  border-radius: var(--sph-radius-lg);
  padding: var(--sph-space-7);
  box-shadow: var(--sph-shadow-sm);
}
/* Feature and metric cards share one box — declared once here so the two
   stay in lock-step. A flex column lets a footer element (a bottom CTA, a
   stat row) pin to the card floor with margin-top:auto. The 4 px top edge
   is shown by the feature card as the Donkey-Brown accent stripe; the
   metric card keeps it (transparent) so both carry an identical box and
   line up side by side. Each variant below sets only what differs — the
   edge colour and the surface. */
.sph-card--feature,
.sph-card--metric {
  display: flex;
  flex-direction: column;
  border-top-width: 4px;
}
.sph-card--feature {
  border-top-color: var(--sph-primary);
}
.sph-card--metric {
  background: var(--sph-bg-inverse);
  color: var(--sph-text-on-dark);
  border-color: transparent;     /* hides the 1 px sides + the 4 px top edge */
}
/* The metric card is a dark San Juan surface — lift each text element to a
   legible tone on it (a bare .sph-stat__value / __label, or a nested
   .sph-stat). White value as the hero; loafer eyebrow and label. */
.sph-card--metric .sph-eyebrow     { color: var(--sph-loafer); }
.sph-card--metric .sph-stat__value { color: var(--sph-white); }
.sph-card--metric .sph-stat__label { color: var(--sph-loafer); }

/* Stat / metric ---------------------------------------------------------- */
.sph-stat { display: flex; flex-direction: column; gap: 8px; }
.sph-stat__value {
  font: var(--sph-weight-bold) var(--sph-fs-4xl)/1 var(--sph-font-display);
  letter-spacing: var(--sph-tracking-tight);
  color: var(--sph-primary);
}
.sph-stat__label {
  font: var(--sph-weight-regular) var(--sph-fs-sm)/1.3 var(--sph-font-body);
  color: var(--sph-text-muted);
  text-transform: uppercase; letter-spacing: var(--sph-tracking-wide);
}

/* Stat block — deck-scale stat with colored top-border, label, value, and
   a descriptive sentence. Used on ROI and outcome slides. Differs from
   `sph-stat` (web-scale) in size and in carrying a description line.
   Value scale: --sph-fs-5xl (88px). The optional <sub> inside the value
   renders as a smaller currency / unit (28px, muted).                       */
.sph-stat-block {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: 24px;
  border-top: 3px solid var(--sph-tone, var(--sph-primary));
}
.sph-stat-block__label {
  font: 600 14px/1 var(--sph-font-display);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sph-tone, var(--sph-primary));
  margin: 0;
}
.sph-stat-block__value {
  font: 800 88px/1 var(--sph-font-display);
  letter-spacing: -0.025em;
  color: var(--sph-dark);
  margin: 0;
}
.sph-stat-block__value sub,
.sph-stat-block__value .unit {
  font: 600 28px/1 var(--sph-font-display);
  color: var(--sph-text-muted);
  letter-spacing: 0;
  vertical-align: baseline;
  margin-left: 4px;
}
.sph-stat-block__desc {
  font: 500 16px/1.45 var(--sph-font-display);
  color: var(--sph-text-soft);
  margin: 0;
  max-width: 30ch;
}
/* Border + label take the tone (tone-system layer): every palette tone.
   `--heart` (an off-palette, non-tone alias) keeps its own Info mapping. */
.sph-stat-block--heart    { border-top-color: var(--sph-info); }
.sph-stat-block--heart    .sph-stat-block__label { color: var(--sph-info); }

/* Pull-quote — the deck's display proposition copy. Work Sans ExtraBold
   at display size, **non-italic**. The legacy brand guide called for
   Lobster here — we don't do that anymore. Weight and size carry the
   emphasis; inline <em> renders in Lonestar red (also non-italic) to
   isolate the key words. The `--longform` modifier loosens leading and
   is intended for multi-clause sentences broken at semantic boundaries
   with explicit <br>. See README §8 "Vertical typography rhythm on
   dense slides".                                                            */
.sph-pull-quote {
  font: 800 clamp(36px, 4.4vw, 56px)/1.15 var(--sph-font-display);
  letter-spacing: -0.01em;
  color: var(--sph-dark);
  margin: 0;
}
.sph-pull-quote em,
.sph-pull-quote .sph-accent {
  color: var(--sph-info);
  font-style: normal; /* override the browser default <em> italic */
}
.sph-pull-quote--longform {
  font-size: clamp(28px, 3.2vw, 40px);
  line-height: 1.35;
}
.sph-pull-quote--on-dark { color: #fff; }
.sph-pull-quote--on-dark em,
.sph-pull-quote--on-dark .sph-accent { color: var(--sph-primary); }
/* Muted accent — the quieter half of a two-colour emphasis (e.g. "cost" vs
   "value"); mirrors .sph-accent's scoping. DeckLang: ~word~ → --muted. */
.sph-pull-quote .sph-accent--muted { color: var(--sph-text-muted); font-style: normal; }
.sph-pull-quote--on-dark .sph-accent--muted { color: var(--sph-loafer); }
/* Attribution line — DeckLang `quote { attribution { … } }` renders a <cite> after the
   quote copy. The `font` shorthand resets the browser's <cite> italic AND the inherited
   display clamp; the treatment is the V2 attribution line (tracked uppercase, body ink),
   matching .sph-statement__attr's name row. Lives HERE (not deck-shell) so web fragments
   get it from the mounted components.css alone (eg9).                                    */
.sph-pull-quote cite {
  display: block;
  margin-top: var(--sph-space-4);
  font: 700 var(--sph-fs-xs)/1.4 var(--sph-font-display);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sph-text);
}
.sph-pull-quote--on-dark cite { color: var(--sph-loafer); }

/* Form fields ----------------------------------------------------------- */
.sph-field { display: grid; gap: 6px; }
.sph-label {
  font: var(--sph-weight-bold) var(--sph-fs-xs)/1.2 var(--sph-font-display);
  letter-spacing: var(--sph-tracking-wide); text-transform: uppercase;
  color: var(--sph-text-soft);
}
.sph-input, .sph-select, .sph-textarea {
  font: var(--sph-weight-regular) var(--sph-fs-base)/1.4 var(--sph-font-body);
  color: var(--sph-text);
  background: var(--sph-surface);
  border: 1px solid var(--sph-border);
  border-radius: var(--sph-radius-sm);
  padding: 10px 12px;
  outline: none;
  transition: border-color var(--sph-dur-fast) var(--sph-ease-standard), box-shadow var(--sph-dur-fast);
}
.sph-input:focus, .sph-select:focus, .sph-textarea:focus {
  border-color: var(--sph-focus, var(--sph-primary-deep));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--sph-focus, var(--sph-primary)) 28%, transparent);
}
/* Selects drop the native platform control: no OS arrow, no OS gradient. The
   chevron is the theme-keyed --sph-chevron glyph (see tokens.css). Declared
   AFTER the shared input rule: its `background:` shorthand would otherwise
   reset the chevron background-image.                                        */
.sph-select {
  appearance: none;
  -webkit-appearance: none;
  background-image: var(--sph-chevron, none);
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 12px 8px;
  padding-inline-end: 38px;
}

/* Tables ---------------------------------------------------------------- */
.sph-table {
  width: 100%; border-collapse: collapse;
  font-family: var(--sph-font-ui);
  font-size: var(--sph-fs-sm);
}
.sph-table th, .sph-table td {
  text-align: left; padding: 10px 14px;
  border-bottom: 1px solid var(--sph-border);
}
.sph-table th {
  font-weight: var(--sph-weight-bold);
  font-size: var(--sph-fs-xs);
  text-transform: uppercase; letter-spacing: var(--sph-tracking-wide);
  color: var(--sph-text-muted);
  background: var(--sph-bg-subtle);
}
.sph-table tbody tr:hover { background: var(--sph-bg-subtle); }

/* Deck-tuned table — modifier for 1920×1080 surfaces. Headers stay at the
   uppercase-12 floor (smallest legible at projector distance); body cells
   read at body-text size (--sph-fs-md, 18px) / Medium / 1.4 line-height so a
   table cell never looks smaller than a `text` paragraph on a large canvas.
   Header carries a 2px primary bottom-border instead of the subtle 1px;
   row-th (the first cell when used as a label) is 14 px Bold to anchor
   the row.                                                                  */
.sph-table--deck {
  font-size: var(--sph-fs-md);
}
.sph-table--deck th {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--sph-text);
  background: transparent;
  border-bottom: 2px solid var(--sph-primary);
  padding: 14px 16px;
}
.sph-table--deck td {
  font-weight: 500;
  line-height: 1.4;
  padding: 14px 16px;
  color: var(--sph-text);
}
.sph-table--deck tbody th,
.sph-table--deck th[scope="row"] {
  /* The first column is the row anchor: larger than the body cells
     (--sph-fs-md, 18px) and bold so the labels lead each row. Switch it off
     with `first-column plain` (see .sph-table--plain-first below). */
  font-size: var(--sph-fs-lg);
  font-weight: 700;
  text-transform: none;
  letter-spacing: 0;
  color: var(--sph-text);
  background: transparent;
  border-bottom: 1px solid var(--sph-border);
}
/* `first-column plain` — make the first column read like every other cell
   (it stays a <th scope="row"> for a11y; this only neutralizes the styling). */
.sph-table--deck.sph-table--plain-first tbody th,
.sph-table--deck.sph-table--plain-first th[scope="row"] {
  font-size: var(--sph-fs-md);
  font-weight: var(--sph-weight-medium);
}
/* Caption — the table's headline. Larger than body text (--sph-fs-lg) and
   extrabold so it reads as the table's title; keeps the uppercase tracked
   primary treatment that marks it as a heading label. */
.sph-table--deck caption {
  caption-side: top; text-align: left;
  font: 800 var(--sph-fs-lg)/1.2 var(--sph-font-display);
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--sph-primary);
  padding-bottom: 16px;
}
/* Marked row — highlight a key row (e.g. the booked train). */
.sph-table--deck tbody tr.is-marked th,
.sph-table--deck tbody tr.is-marked td { background: var(--sph-bg-callout); }
.sph-table--deck tbody tr.is-marked th[scope="row"] { color: var(--sph-primary); }
/* Per-cell tone — `cells { … { tone burgundy { -12% } } … }` tints one cell and colours
   its value, reusing the shared --sph-tone layer so every palette tone works. A light wash
   keeps the grid calm; pair with `weight bold` for a stronger callout. (A whole-row
   is-marked highlight is more specific and still wins its background.) */
.sph-table--deck th.sph-cell-tone,
.sph-table--deck td.sph-cell-tone {
  background: color-mix(in srgb, var(--sph-tone) 16%, transparent);
  color: var(--sph-tone);
}
/* Frame row — DE-emphasis (the opposite of is-marked): a soft secondary tint
   marking bounding / framing rows (e.g. the Practitioner & Group anchor rows
   that bracket a tier table). Quieter than the body, not louder.            */
.sph-table--deck tbody tr.is-frame th,
.sph-table--deck tbody tr.is-frame td { background: var(--sph-bg-subtle); color: var(--sph-text-muted); }
/* Numeric column — right-align figures and lock to tabular figures so digits
   line up. Add `class="num"` to the relevant <th>/<td> cells.                */
.sph-table--deck th.num,
.sph-table--deck td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
/* Totals row — a `tfoot` row carries a 2px dark top-rule and bold figures.
   Generic: any deck table can close with a totals row. */
.sph-table--deck tfoot th,
.sph-table--deck tfoot td {
  border-top: 2px solid var(--sph-dark);
  border-bottom: 0;
  font-weight: 700;
  color: var(--sph-dark);
  padding: 14px 16px;
}

/* Dividers & rules ------------------------------------------------------ */
.sph-rule { border: 0; border-top: 1px solid var(--sph-border); margin: var(--sph-space-7) 0; }
.sph-rule--brand { border-top: 2px solid var(--sph-primary); }

/* Marks used in "smarter | better | faster" style lockups */
.sph-pipe { color: var(--sph-primary); padding: 0 .35em; font-weight: var(--sph-weight-regular); }

/* ============================================================
   Tagline lockup — "The Value Intelligence Company" (positioning,
   descriptor cap) + "Data · Value · Impact" (three-word punch line).
   Use as a single stack on covers, footers, sign-offs, hero blocks.
   Pair with a logo when available.
   ============================================================ */
.sph-tagline {
  display: flex; flex-direction: column;
}
.sph-tagline--sm  { gap: 8px;  }
.sph-tagline--md  { gap: 12px; }   /* default */
.sph-tagline--lg  { gap: 18px; }
.sph-tagline:not(.sph-tagline--sm):not(.sph-tagline--lg) { gap: 12px; }

/* Positioning line — small caps, primary red, wide tracking. */
.sph-tagline__descriptor {
  font-family: var(--sph-font-display);
  font-weight: var(--sph-weight-semibold);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--sph-primary);
  font-size: var(--sph-fs-sm);            /* 14px default */
  line-height: 1;
}
.sph-tagline--sm .sph-tagline__descriptor { font-size: var(--sph-fs-xs); }
.sph-tagline--lg .sph-tagline__descriptor { font-size: var(--sph-fs-md); }

/* Punch line — Data · Value · Impact. Bold display, tight tracking.
   This is a lockup: the three words never wrap — `nowrap` keeps them on one
   line in every container. Size the container to fit; don't let it break. */
.sph-tagline__primary {
  font-family: var(--sph-font-display);
  font-weight: var(--sph-weight-bold);
  letter-spacing: -0.01em;
  font-size: var(--sph-fs-2xl);           /* 36px default */
  line-height: 1.05;
  color: var(--sph-text);
  white-space: nowrap;
}
.sph-tagline--sm .sph-tagline__primary { font-size: var(--sph-fs-xl);  }
.sph-tagline--lg .sph-tagline__primary { font-size: var(--sph-fs-4xl); }

/* The word separator is the brand's geometric square — the shared DS
   `.dvi-dot` utility (defined in motifs.css), ALWAYS in the primary brand
   colour (Donkey Brown): that's the brand cue. `.dvi-dot` draws the square
   with `background: currentColor`, so the colour set here is what it paints.
   A round middle-dot glyph is not used in the lockup. */
.sph-tagline__primary .dvi-dot { color: var(--sph-primary); }

/* Inverse pairing for dark backgrounds. */
.sph-tagline--on-dark .sph-tagline__primary  { color: #fff; }
.sph-tagline--on-dark .sph-tagline__descriptor { color: var(--sph-primary); }

/* ============================================================
   DVI mark — the geometric Data·Value·Impact brand lockup.
   Each word pairs with its geometric form: ▭ square = DATA,
   ● circle = VALUE, ▶ triangle = IMPACT (the DATA2VALUE shape
   language; the square is the same glyph as `.dvi-dot`). The
   glyphs are em-scaled, so the mark works BOTH standalone (a
   `dvi` body element) and INLINE (the `:dvi:` token dropped
   mid-sentence rides the surrounding font-size and baseline).
   Standalone shapes + words inherit the text colour (ink on light,
   cream / white on dark), except VALUE and its circle, which are
   brand-locked to primary like `.sph-tagline__primary .dvi-dot`.
   Inline `:…:` forms always inherit their surrounding text colour.
   `--compact` drops the words for a shapes-only mark (▭ ● ▶).
   ============================================================ */
.sph-dvi {
  font-family: var(--sph-font-display);
  font-weight: var(--sph-weight-bold);
  letter-spacing: -0.01em;
  white-space: nowrap;
}
/* Each shape is a square em-box painted with the current text colour;
   circle rounds it, triangle clips it to a right-pointing wedge. */
.sph-dvi__shape {
  display: inline-block;
  width: 0.62em;
  height: 0.62em;
  background: currentColor;
  vertical-align: -0.04em;
}
.sph-dvi__shape--square   { border-radius: 0; clip-path: none; }
.sph-dvi__shape--circle   { border-radius: 50%; }
.sph-dvi__shape--triangle { clip-path: polygon(0 0, 100% 50%, 0 100%); }
.sph-dvi__word { margin-left: 0.3em; }
.sph-dvi__word + .sph-dvi__shape { margin-left: 0.66em; }                 /* gap before the next group */
.sph-dvi--compact .sph-dvi__shape + .sph-dvi__shape { margin-left: 0.4em; } /* shapes-only spacing */
/* The standalone brand cue: VALUE and its circle use the primary colour. */
.sph-dvi__shape--circle,
.sph-dvi__word--value { color: var(--sph-primary); }
/* Inline tokens ride the surrounding size and colour. The more-specific colour
   reset deliberately cancels the standalone VALUE cue for every `:…:` form. */
.sph-dvi--inline { font-size: inherit; }
.sph-dvi--inline .sph-dvi__shape--circle,
.sph-dvi--inline .sph-dvi__word--value { color: inherit; }
/* Force pure white for the non-brand parts on a dark surface (opt-in, like the tagline). */
.sph-dvi--on-dark { color: #fff; }

/* Value pill — NLPP-specific; colored by how value compares to price */
.sph-value {
  display: inline-flex; align-items: baseline; gap: 6px;
  padding: 6px 12px; border-radius: var(--sph-radius-sm);
  font: var(--sph-weight-bold) var(--sph-fs-sm)/1 var(--sph-font-ui);
}
.sph-value--over  { background: rgba(75,169,0,.12);  color: var(--sph-success); }   /* value > price   */
.sph-value--fair  { background: rgba(3,168,230,.12); color: var(--sph-accent-sky); }/* value ≈ price   */
.sph-value--under { background: rgba(244,0,93,.10);  color: var(--sph-danger); }    /* value < price   */

/* Squared bullet list ----------------------------------------------------- */
/* A single squared bullet whose colour follows the parent card/tile accent.
   IMPORTANT: base.css styles every `ul li` with a square ::marker — this list
   resets that marker so it renders ONE bullet, never two. Define the squared
   list ONCE here; never re-implement it per deck. */
.sq-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
.sq-list li {
  position: relative; list-style: none; padding-left: 20px;
  /* Bullets read at body-text size — match `.sph-lead` (text) exactly so a
     `bullets` list never looks smaller than a `text` paragraph. Define once. */
  font: var(--sph-weight-medium) var(--sph-slide-body-size)/var(--sph-lh-normal) var(--sph-font-body);
  color: var(--sph-text-soft);
}
.sq-list li::marker { content: ""; }   /* kill the inherited base.css square marker */
.sq-list li::before {
  content: ""; position: absolute; left: 0; top: .42em;
  width: 9px; height: 9px; background: var(--sph-primary);
}
/* Bullet colour follows the parent card / tile accent: --sph-tone is set on
   the toned card/tile (tone-system layer) and inherited by the list, so every
   palette tone tints the bullets — no per-tone rules. Untoned falls back to
   the brand primary, matching the global .sq-list bullet above. */
.sph-card-cream .sq-list li::before,
.num-tile .sq-list li::before { background: var(--sph-tone, var(--sph-primary)); }

/* Card audience pill ------------------------------------------------------ */
/* A first-class "who this is for" tag — pins top-right of a cream card,
   visually distinct from the descriptive `__eyebrow` kicker, with the colour
   following the card accent. Frees `__eyebrow` to describe the card itself. */
.sph-card-cream:has(.sph-card-cream__audience) { position: relative; }
.sph-card-cream__audience {
  position: absolute;
  top: var(--sph-space-6);
  right: var(--sph-space-6);
  font: var(--sph-weight-bold) var(--sph-fs-micro)/1 var(--sph-font-display);
  letter-spacing: var(--sph-tracking-wider);
  text-transform: uppercase;
  padding: 6px 11px;
  border-radius: 999px;
  /* Background follows the card's tone tint (the same --sph-card-tone-tint the card
     itself uses), so the pill harmonises with the card on EVERY tone — not just the
     cream/camel cases where the old fixed loafer-soft happened to match. */
  background: var(--sph-card-tone-tint, var(--sph-loafer-soft));
  /* Pill border + text follow the card accent (tone-system layer): all tones. */
  border: 1px solid var(--sph-tone, var(--sph-primary));
  color: var(--sph-tone, var(--sph-primary));
}

} /* end @layer */
