/* =============================================================================
   TRAILWISE  ·  design kit v1.0  ·  15 August 2026
   Light theme only. Drop-in: <link rel="stylesheet" href="trailwise.css">

   Everything here was lifted from the marketing site built in August 2026 and
   is in production use there, EXCEPT the blocks marked NEW FOR TOOLS, which
   extend the same language into UI the site never needed (forms beyond one
   dialog, tables, app shell, status, charts).

   Fonts: Space Grotesk (display) + Noto Sans (body), self-host or
   <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;700&family=Noto+Sans:wght@400;500;600&display=swap" rel="stylesheet">
   ============================================================================= */

/* -----------------------------------------------------------------------------
   1  TOKENS
   -------------------------------------------------------------------------- */
:root{
  /* --- brand ------------------------------------------------------------- */
  --ws-ink:#15344B;          /* display type, dark surfaces. 12.9:1 on paper  */
  --ws-teal:#03B8A5;         /* brand. FILLS AND SHAPES ONLY, never text      */
  --ws-teal-deep:#00786C;    /* the text-safe teal. 5.4:1 paper, 4.8:1 sky    */
  --ws-aqua:rgba(0,255,229,.2); /* the highlighter marker                     */
  --ws-sky:#E2F5FF;          /* the pale band that separates sections         */
  --ws-sky-2:#D8F1FF;        /* image placeholder, one step down              */
  --ws-paper:#FFFFFF;
  --ws-body:#000000;         /* body copy is true black, not ink              */
  --ws-duo:#1C5F91;          /* the single blue every duotone photo prints in */

  /* --- lines and washes -------------------------------------------------- */
  --ws-line:rgba(21,52,75,.14);
  --ws-line-strong:rgba(21,52,75,.28);
  --ws-line-light:rgba(255,255,255,.2);   /* on ink surfaces                  */
  --ws-muted:#6A7F8E;                     /* NEW: solid muted ink, 4.2:1      */

  /* --- geometry ---------------------------------------------------------- */
  --ws-gutter:20px;
  --ws-maxw:1416px;
  --ws-radius:32px;          /* cards, panels, dialogs. The big one.          */
  --ws-radius-sm:0px;        /* controls are square. This is a brand decision */
  --ws-header-h:104px;
  --ws-seam:clamp(64px,12vh,150px);  /* how far a card rides into the band    */

  /* --- spacing scale (NEW FOR TOOLS: the site sized by clamp per section) - */
  --ws-s1:4px;  --ws-s2:8px;  --ws-s3:12px; --ws-s4:16px;
  --ws-s5:24px; --ws-s6:32px; --ws-s7:48px; --ws-s8:64px; --ws-s9:96px;

  /* --- type -------------------------------------------------------------- */
  --ws-font-display:'Space Grotesk',system-ui,sans-serif;
  --ws-font-body:'Noto Sans',system-ui,sans-serif;
  --ws-font-mono:ui-monospace,'SF Mono',Menlo,monospace;   /* NEW FOR TOOLS   */

  --ws-fs-mega:clamp(3.6rem,17.6vw,261px);
  --ws-fs-h1:clamp(2.9rem,8.1vw,120px);
  --ws-fs-h2:clamp(2.2rem,4.05vw,60px);
  --ws-fs-h3:clamp(1.9rem,3.1vw,46px);
  --ws-fs-h4:clamp(1.4rem,2.16vw,32px);
  --ws-fs-lede:clamp(1.1rem,1.82vw,27px);
  --ws-fs-body:clamp(1rem,1.21vw,18px);
  --ws-fs-prose:clamp(1.05rem,1.32vw,20px);   /* long-form reading column     */
  --ws-fs-nav:16px;
  --ws-fs-ui:15px;           /* NEW FOR TOOLS: dense UI baseline              */
  --ws-fs-micro:13px;

  /* --- motion ------------------------------------------------------------ */
  --ws-ease:cubic-bezier(.22,.61,.36,1);
  --ws-dur-micro:220ms;      /* hover, focus, colour                          */
  --ws-dur:800ms;            /* reveals                                       */

  /* --- elevation --------------------------------------------------------- */
  --ws-shadow-card:0 0 0 1px var(--ws-line),0 30px 60px -40px rgba(21,52,75,.45);
  --ws-shadow-lift:0 0 0 1px var(--ws-line),0 40px 80px -40px rgba(21,52,75,.55);
  --ws-shadow-dialog:0 60px 120px -50px rgba(21,52,75,.7);

  /* --- status (NEW FOR TOOLS) -------------------------------------------- */
  --ws-good:#0CA30C;   --ws-good-ink:#046B04;
  --ws-warn:#FAB219;   --ws-warn-ink:#8A5A00;
  --ws-serious:#EC835A;--ws-serious-ink:#9A4418;
  --ws-crit:#D03B3B;   --ws-crit-ink:#A32B2B;

  /* --- charts (NEW FOR TOOLS, validated, see the primer) ----------------- */
  --ws-series-1:#00A08F;  /* teal    */
  --ws-series-2:#E2622A;  /* orange  */
  --ws-series-3:#1C5F91;  /* blue    */
  --ws-series-4:#B58200;  /* amber   */
  --ws-series-5:#C25E8E;  /* magenta */
  --ws-series-6:#2F7D32;  /* green   */
  --ws-series-7:#5B4BA8;  /* violet  */
  --ws-series-8:#C0392B;  /* red     */
  --ws-grid:rgba(21,52,75,.10);
  --ws-axis:rgba(21,52,75,.28);
}
@media (min-width:1024px){ :root{ --ws-gutter:32px; } }
@media (max-width:1024px){ :root{ --ws-header-h:88px; } }

/* The angled edge. Registered so it can transition: a plain custom property
   inside clip-path() jumps between values instead of animating. */
@property --ws-cut{syntax:'<length>';inherits:true;initial-value:12px}

/* -----------------------------------------------------------------------------
   2  BASE
   -------------------------------------------------------------------------- */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--ws-paper);color:var(--ws-body);
  font-family:var(--ws-font-body);font-weight:500;
  font-size:var(--ws-fs-body);line-height:1.33;letter-spacing:.02em;
  -webkit-font-smoothing:antialiased;
}
img{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
h1,h2,h3,h4{margin:0}
p{margin:0}
:focus-visible{outline:3px solid var(--ws-ink);outline-offset:3px}

/* -----------------------------------------------------------------------------
   3  TYPE
   .d puts anything into the display face. The scale classes set size only, so
   .d.h2 is display at h2 size and .h2 alone is body at h2 size.
   -------------------------------------------------------------------------- */
.ws-d{font-family:var(--ws-font-display);font-weight:500;letter-spacing:-.05em;
  color:var(--ws-ink);text-wrap:balance}
.ws-mega{font-size:var(--ws-fs-mega);line-height:.83}
.ws-h1{font-size:var(--ws-fs-h1);line-height:1.09}
.ws-h2{font-size:var(--ws-fs-h2);line-height:1.17}
.ws-h3{font-size:var(--ws-fs-h3);line-height:1.28;font-weight:700}
.ws-h4{font-size:var(--ws-fs-h4);line-height:1.28}
.ws-lede{font-size:var(--ws-fs-lede);line-height:1.55;letter-spacing:.02em}
.ws-body{font-size:var(--ws-fs-body);line-height:1.33;letter-spacing:.02em}
.ws-ui{font-size:var(--ws-fs-ui);line-height:1.45}
.ws-label{font-family:var(--ws-font-body);font-weight:600;font-size:var(--ws-fs-nav);
  line-height:1.375;text-transform:uppercase;letter-spacing:.02em}
.ws-micro{font-size:var(--ws-fs-micro);letter-spacing:.06em;text-transform:uppercase;
  font-weight:600;color:var(--ws-ink);opacity:.5}
.ws-num{font-variant-numeric:tabular-nums}

/* The highlighter. ONE SPAN PER VISUAL LINE — a marker across a wrapping
   headline loses its block on every line after the first. */
.ws-mark{position:relative;isolation:isolate;padding:2px 8px;display:inline-block}
.ws-mark::before{content:"";position:absolute;z-index:-1;left:0;right:2px;bottom:1px;
  height:.82em;background:var(--ws-aqua);transform:rotate(-.4deg)}

/* Long-form reading column. Capped in ch, not px, so it holds the same number
   of characters whatever the clamp resolves to. */
.ws-prose{max-width:68ch;font-size:var(--ws-fs-prose);line-height:1.62;letter-spacing:.01em}
.ws-prose p{margin:0 0 1.2em}
.ws-prose h2{font-family:var(--ws-font-display);font-weight:500;letter-spacing:-.04em;
  color:var(--ws-ink);font-size:clamp(1.5rem,2.3vw,34px);line-height:1.2;
  margin:clamp(46px,6.5vh,80px) 0 clamp(16px,2.2vh,24px)}
.ws-prose p > strong{color:var(--ws-ink);font-weight:700}
.ws-prose blockquote{margin:clamp(34px,4.6vh,56px) 0;padding-left:clamp(18px,2vw,28px);
  border-left:2px solid var(--ws-teal);font-family:var(--ws-font-display);font-weight:500;
  letter-spacing:-.03em;color:var(--ws-ink);font-size:clamp(1.3rem,1.95vw,29px);line-height:1.3}

/* -----------------------------------------------------------------------------
   4  LAYOUT
   -------------------------------------------------------------------------- */
.ws-wrap{max-width:var(--ws-maxw);margin-inline:auto;padding-inline:var(--ws-gutter)}
.ws-band{background:var(--ws-sky)}
.ws-band-ink{background:var(--ws-ink);color:#fff}
.ws-band-ink .ws-d{color:#fff}
.ws-section{padding-block:clamp(60px,9vh,120px)}
.ws-stack{display:flex;flex-direction:column;gap:var(--ws-s4)}
.ws-row{display:flex;align-items:center;gap:var(--ws-s3);flex-wrap:wrap}

/* -----------------------------------------------------------------------------
   5  BUTTONS   the angled edge
   Three things are deliberate:
   · the fill is on ::before, not the element. clip-path clips everything an
     element paints, its outline included, so a clipped button loses its focus
     ring. Clipping only the fill layer leaves the element's box rectangular
     and the ring draws on that.
   · the ANGLE is the constant, not the inset. 12/38 and 18/57 are both ~17.5°.
   · padding compensates for the diagonal but never changes on hover, so the
     label is fixed and only the notch moves.
   -------------------------------------------------------------------------- */
.ws-btn{
  --ws-cut:12px; --ws-cut-hover:18px; --ws-btn-bg:var(--ws-paper);
  position:relative;isolation:isolate;
  display:inline-flex;align-items:center;justify-content:center;gap:12px;
  padding:8px 16px 8px 22px;min-height:38px;border:0;border-radius:var(--ws-radius-sm);
  cursor:pointer;font-family:var(--ws-font-body);font-weight:600;
  font-size:var(--ws-fs-nav);line-height:1.375;text-transform:uppercase;
  letter-spacing:.02em;background:transparent;color:#fff;white-space:nowrap;
  transition:--ws-cut 260ms var(--ws-ease),transform var(--ws-dur-micro) var(--ws-ease);
}
.ws-btn::before{
  content:"";position:absolute;inset:0;z-index:-1;background:var(--ws-teal);
  clip-path:polygon(var(--ws-cut) 0,100% 0,100% 100%,0 100%);
  transition:background var(--ws-dur-micro) var(--ws-ease);
}
.ws-btn:hover{--ws-cut:var(--ws-cut-hover)}
.ws-btn:hover::before{background:var(--ws-ink)}
.ws-btn:active{transform:translateY(1px)}
.ws-btn:disabled,.ws-btn[aria-disabled="true"]{opacity:.4;pointer-events:none}

.ws-btn-lg{--ws-cut:18px;--ws-cut-hover:26px;padding:16px 28px 16px 37px;
  min-height:56px;font-size:18px}
.ws-btn-sm{--ws-cut:9px;--ws-cut-hover:13px;padding:5px 12px 5px 17px;
  min-height:30px;font-size:13px}

/* Quiet is a text control. It gets no shape: the secondary action is the one
   not asking for attention, and a shape would argue with that. */
.ws-btn-quiet{color:var(--ws-body)}
.ws-btn-quiet::before,.ws-btn-quiet:hover::before{background:transparent}
.ws-btn-quiet:hover{--ws-cut:12px;color:var(--ws-teal-deep)}

/* clip-path cuts an inset box-shadow off along the diagonal, so the outline is
   two clipped layers: ::before is the stroke, ::after is the fill inset by its
   width. Same polygon on both, which lays an even stroke along the angle. */
.ws-btn-outline{color:var(--ws-ink)}
.ws-btn-outline::before{background:var(--ws-ink)}
.ws-btn-outline::after{
  content:"";position:absolute;inset:1.5px;z-index:-1;background:var(--ws-btn-bg);
  clip-path:polygon(var(--ws-cut) 0,100% 0,100% 100%,0 100%);
  transition:background var(--ws-dur-micro) var(--ws-ease);
}
.ws-btn-outline:hover{color:#fff}
.ws-btn-outline:hover::after{background:var(--ws-ink)}

/* Destructive. NEW FOR TOOLS. */
.ws-btn-danger::before{background:var(--ws-crit)}
.ws-btn-danger:hover::before{background:var(--ws-crit-ink)}

/* -----------------------------------------------------------------------------
   6  FORMS   the site had one dialog; this extends it
   -------------------------------------------------------------------------- */
.ws-field{display:block;margin-top:var(--ws-s5)}
.ws-field > label,.ws-label-field{
  display:block;font-family:var(--ws-font-body);font-weight:600;font-size:var(--ws-fs-micro);
  letter-spacing:.06em;text-transform:uppercase;color:var(--ws-ink);margin-bottom:var(--ws-s2);
}
.ws-input,.ws-select,.ws-textarea{
  width:100%;font-family:var(--ws-font-body);font-size:17px;color:var(--ws-body);
  background:var(--ws-paper);border:1px solid var(--ws-line);border-radius:var(--ws-radius-sm);
  padding:14px 16px;min-height:54px;
  transition:border-color var(--ws-dur-micro) var(--ws-ease);
}
.ws-textarea{min-height:120px;line-height:1.45;resize:vertical}
.ws-select{appearance:none;padding-right:44px;
  background-image:linear-gradient(45deg,transparent 50%,var(--ws-ink) 50%),
                   linear-gradient(135deg,var(--ws-ink) 50%,transparent 50%);
  background-position:calc(100% - 22px) 24px,calc(100% - 16px) 24px;
  background-size:6px 6px,6px 6px;background-repeat:no-repeat}
.ws-input:hover,.ws-select:hover,.ws-textarea:hover{border-color:var(--ws-line-strong)}
.ws-input:focus,.ws-select:focus,.ws-textarea:focus{
  outline:3px solid var(--ws-teal);outline-offset:1px;border-color:transparent}
.ws-input::placeholder,.ws-textarea::placeholder{color:var(--ws-body);opacity:.38}
.ws-hint{margin:var(--ws-s2) 0 0;font-size:14px;color:var(--ws-body);opacity:.6}
.ws-field[data-invalid] .ws-input,
.ws-field[data-invalid] .ws-select,
.ws-field[data-invalid] .ws-textarea{border-color:var(--ws-crit);border-width:1.5px}
.ws-error{margin:var(--ws-s2) 0 0;font-size:14px;color:var(--ws-crit-ink);font-weight:600}
.ws-field-row{display:grid;grid-template-columns:1fr 1fr;gap:var(--ws-s4)}
@media (max-width:560px){.ws-field-row{grid-template-columns:1fr}}

/* check, radio, switch — square like everything else */
.ws-check{display:inline-flex;align-items:flex-start;gap:var(--ws-s3);cursor:pointer;
  font-size:var(--ws-fs-ui);line-height:1.45}
.ws-check input[type=checkbox],.ws-check input[type=radio]{
  appearance:none;flex:none;width:20px;height:20px;margin:1px 0 0;cursor:pointer;
  border:1.5px solid var(--ws-line-strong);background:var(--ws-paper);
  border-radius:var(--ws-radius-sm);transition:all var(--ws-dur-micro) var(--ws-ease)}
.ws-check input[type=radio]{border-radius:50%}
.ws-check input:checked{background:var(--ws-teal);border-color:var(--ws-teal)}
.ws-check input[type=checkbox]:checked{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.5l3.2 3.2L13 5' fill='none' stroke='%23fff' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-size:14px;background-position:center;background-repeat:no-repeat}
.ws-check input[type=radio]:checked{box-shadow:inset 0 0 0 4px var(--ws-paper)}
.ws-check input:focus-visible{outline:3px solid var(--ws-ink);outline-offset:2px}

.ws-switch{position:relative;display:inline-flex;align-items:center;gap:var(--ws-s3);cursor:pointer}
.ws-switch input{appearance:none;width:46px;height:26px;margin:0;cursor:pointer;
  background:var(--ws-line-strong);transition:background var(--ws-dur-micro) var(--ws-ease)}
.ws-switch input::after{content:"";position:absolute;left:3px;top:3px;width:20px;height:20px;
  background:var(--ws-paper);transition:transform var(--ws-dur-micro) var(--ws-ease)}
.ws-switch input:checked{background:var(--ws-teal)}
.ws-switch input:checked::after{transform:translateX(20px)}

/* Segmented control, from the pricing page. The indicator is a sliding block,
   so it needs a JS nudge on resize and after any pane swap. */
.ws-seg{position:relative;display:inline-flex;background:var(--ws-sky);padding:4px}
.ws-seg button{
  position:relative;z-index:1;appearance:none;border:0;background:none;cursor:pointer;
  font-family:var(--ws-font-body);font-weight:600;font-size:var(--ws-fs-nav);
  letter-spacing:.02em;color:var(--ws-body);opacity:.6;padding:12px 26px;white-space:nowrap;
  transition:color 260ms var(--ws-ease),opacity 260ms var(--ws-ease)}
.ws-seg button[aria-pressed="true"]{color:#fff;opacity:1}
.ws-seg-i{position:absolute;z-index:0;top:4px;bottom:4px;left:0;background:var(--ws-ink);
  transition:transform 380ms var(--ws-ease),width 380ms var(--ws-ease)}

/* -----------------------------------------------------------------------------
   7  SURFACES
   -------------------------------------------------------------------------- */
.ws-card{background:var(--ws-paper);border-radius:var(--ws-radius);
  padding:clamp(24px,2.6vw,40px);box-shadow:var(--ws-shadow-card);
  transition:transform 260ms var(--ws-ease),box-shadow 260ms var(--ws-ease)}
.ws-card-hover:hover{transform:translateY(-6px);box-shadow:var(--ws-shadow-lift)}
.ws-card-lead{box-shadow:0 0 0 2px var(--ws-teal),0 40px 80px -38px rgba(21,52,75,.5)}
/* Flat panel for dense UI. NEW FOR TOOLS: the 32px radius is too soft at
   dashboard density, so tool panels use a hairline and a small radius. */
.ws-panel{background:var(--ws-paper);border:1px solid var(--ws-line);
  border-radius:8px;padding:var(--ws-s5)}
.ws-panel-head{display:flex;align-items:baseline;justify-content:space-between;
  gap:var(--ws-s4);margin-bottom:var(--ws-s4);padding-bottom:var(--ws-s3);
  border-bottom:1px solid var(--ws-line)}

.ws-dialog-veil{position:fixed;inset:0;z-index:200;display:none;
  background:rgba(21,52,75,.55);backdrop-filter:blur(3px);
  padding:clamp(16px,4vh,56px) var(--ws-gutter);overflow:auto}
.ws-dialog-veil.on{display:grid;place-items:start center}
.ws-dialog{position:relative;width:min(660px,100%);background:var(--ws-paper);
  border-radius:var(--ws-radius);padding:clamp(28px,4vw,52px);
  box-shadow:var(--ws-shadow-dialog);
  opacity:0;transform:translateY(20px) scale(.98);
  transition:opacity 420ms var(--ws-ease),transform 420ms var(--ws-ease)}
.ws-dialog-veil.on .ws-dialog{opacity:1;transform:none}

/* -----------------------------------------------------------------------------
   8  STATUS, BADGES, ALERTS   NEW FOR TOOLS
   A status colour never carries meaning alone. Always icon or label too.
   -------------------------------------------------------------------------- */
.ws-badge{display:inline-flex;align-items:center;gap:6px;
  font-family:var(--ws-font-body);font-weight:600;font-size:11px;letter-spacing:.08em;
  text-transform:uppercase;background:var(--ws-teal);color:#fff;padding:6px 10px;
  white-space:nowrap}
.ws-badge-ink{background:var(--ws-ink)}
.ws-badge-quiet{background:var(--ws-sky);color:var(--ws-ink)}
.ws-badge-good{background:var(--ws-good-ink)}
.ws-badge-warn{background:var(--ws-warn);color:var(--ws-ink)}
.ws-badge-crit{background:var(--ws-crit-ink)}

.ws-dot{display:inline-block;width:8px;height:8px;flex:none;background:var(--ws-muted)}
.ws-dot-good{background:var(--ws-good)} .ws-dot-warn{background:var(--ws-warn)}
.ws-dot-serious{background:var(--ws-serious)} .ws-dot-crit{background:var(--ws-crit)}

.ws-alert{display:flex;gap:var(--ws-s3);padding:var(--ws-s4);
  border-left:3px solid var(--ws-muted);background:rgba(21,52,75,.04);
  font-size:var(--ws-fs-ui);line-height:1.5}
.ws-alert strong{display:block;color:var(--ws-ink)}
.ws-alert-good{border-left-color:var(--ws-good);background:rgba(12,163,12,.06)}
.ws-alert-warn{border-left-color:var(--ws-warn);background:rgba(250,178,25,.10)}
.ws-alert-crit{border-left-color:var(--ws-crit);background:rgba(208,59,59,.07)}

/* Confidence, the product's own idea: a signal says how much it knows. */
.ws-conf{display:inline-flex;align-items:center;gap:6px;font-size:var(--ws-fs-micro);
  font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--ws-muted)}
.ws-conf-bar{display:inline-flex;gap:2px}
.ws-conf-bar i{width:14px;height:4px;background:var(--ws-line-strong)}
.ws-conf-bar i.on{background:var(--ws-teal-deep)}

/* -----------------------------------------------------------------------------
   9  TABLES   NEW FOR TOOLS
   Ruled, not zebra. Numbers tabular and right-aligned.
   -------------------------------------------------------------------------- */
.ws-table{width:100%;border-collapse:collapse;font-size:var(--ws-fs-ui)}
.ws-table th{
  position:sticky;top:0;z-index:1;background:var(--ws-paper);text-align:left;
  font-family:var(--ws-font-body);font-weight:600;font-size:11px;letter-spacing:.09em;
  text-transform:uppercase;color:var(--ws-teal-deep);
  padding:10px var(--ws-s3);border-bottom:1.5px solid var(--ws-line-strong);white-space:nowrap}
.ws-table td{padding:12px var(--ws-s3);border-bottom:1px solid var(--ws-line);
  vertical-align:top}
.ws-table tbody tr:hover{background:var(--ws-sky)}
.ws-table .num{text-align:right;font-variant-numeric:tabular-nums}
.ws-table th.num{text-align:right}
.ws-table-compact td{padding:7px var(--ws-s3)}

/* -----------------------------------------------------------------------------
   10  APP SHELL   NEW FOR TOOLS
   -------------------------------------------------------------------------- */
.ws-app{display:grid;grid-template-columns:248px minmax(0,1fr);min-height:100vh}
@media (max-width:900px){.ws-app{grid-template-columns:minmax(0,1fr)}.ws-side{display:none}}
.ws-side{background:var(--ws-ink);color:#fff;padding:var(--ws-s5) 0;
  display:flex;flex-direction:column;gap:var(--ws-s5)}
.ws-side .brand{font-family:var(--ws-font-display);font-weight:500;letter-spacing:-.05em;
  font-size:24px;color:#fff;padding-inline:var(--ws-s5)}
.ws-side h4{font-size:11px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--ws-teal);margin:0 0 var(--ws-s2);padding-inline:var(--ws-s5)}
.ws-side nav{display:flex;flex-direction:column}
.ws-side nav a{padding:10px var(--ws-s5);font-size:var(--ws-fs-ui);
  color:rgba(255,255,255,.72);border-left:3px solid transparent;
  transition:color var(--ws-dur-micro) var(--ws-ease),
             border-color var(--ws-dur-micro) var(--ws-ease)}
.ws-side nav a:hover{color:#fff}
.ws-side nav a[aria-current]{color:#fff;border-left-color:var(--ws-teal);font-weight:600}
.ws-main{min-width:0;padding:var(--ws-s6) var(--ws-s6) var(--ws-s9)}
.ws-topbar{display:flex;align-items:center;justify-content:space-between;gap:var(--ws-s4);
  padding-bottom:var(--ws-s5);margin-bottom:var(--ws-s6);border-bottom:1px solid var(--ws-line)}
.ws-crumbs{display:flex;gap:var(--ws-s2);font-size:var(--ws-fs-micro);color:var(--ws-muted)}
.ws-crumbs a:hover{color:var(--ws-teal-deep)}

.ws-stat{display:flex;flex-direction:column;gap:6px}
.ws-stat .k{font-size:11px;letter-spacing:.09em;text-transform:uppercase;
  font-weight:600;color:var(--ws-teal-deep)}
.ws-stat .v{font-family:var(--ws-font-display);font-weight:500;letter-spacing:-.04em;
  font-size:clamp(28px,3vw,44px);line-height:1;color:var(--ws-ink);
  font-variant-numeric:tabular-nums}
.ws-stat .d{font-size:var(--ws-fs-micro);color:var(--ws-muted)}

.ws-empty{text-align:center;padding:var(--ws-s9) var(--ws-s5);color:var(--ws-muted)}
.ws-empty .ws-d{margin-bottom:var(--ws-s3)}

/* -----------------------------------------------------------------------------
   11  CHARTS   NEW FOR TOOLS
   Assign series in fixed order, never cycled. Above 3 concurrent series in a
   scatter or small-multiple, fold to Other or facet — see the primer.
   -------------------------------------------------------------------------- */
.ws-viz{--surface:var(--ws-paper);--text-primary:var(--ws-ink);
  --text-secondary:var(--ws-muted);font-family:var(--ws-font-body)}
.ws-viz .grid{stroke:var(--ws-grid);stroke-width:1}
.ws-viz .axis{stroke:var(--ws-axis);stroke-width:1}
.ws-viz .tick{fill:var(--ws-muted);font-size:12px;font-variant-numeric:tabular-nums}
.ws-viz .line{fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.ws-viz .mark{stroke:var(--ws-paper);stroke-width:2}
.ws-legend{display:flex;flex-wrap:wrap;gap:var(--ws-s4);font-size:var(--ws-fs-micro);
  color:var(--ws-ink)}
.ws-legend span{display:inline-flex;align-items:center;gap:6px}
.ws-legend i{width:10px;height:10px;flex:none}

/* -----------------------------------------------------------------------------
   12  MOTION
   Scroll-driven motion writes ONE custom property per frame to a stage element
   and lets CSS do the rest. Never a listener per item.
   -------------------------------------------------------------------------- */
[data-reveal]{opacity:0;transform:translateY(24px);
  transition:opacity var(--ws-dur) var(--ws-ease),transform var(--ws-dur) var(--ws-ease)}
[data-reveal].on{opacity:1;transform:none}
.ws-progress{position:fixed;left:0;right:0;top:var(--ws-header-h);height:3px;z-index:60;
  pointer-events:none}
.ws-progress i{display:block;height:100%;background:var(--ws-teal);
  transform:scaleX(var(--pg,0));transform-origin:0 50%}

@media (prefers-reduced-motion:reduce){
  [data-reveal]{opacity:1!important;transform:none!important}
  *{transition:none!important;animation:none!important}
}

/* -----------------------------------------------------------------------------
   13  UTILITIES
   -------------------------------------------------------------------------- */
.ws-ink{color:var(--ws-ink)} .ws-teal{color:var(--ws-teal-deep)}
.ws-muted-t{color:var(--ws-muted)}
.ws-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);
  white-space:nowrap}
