/* ============================================================================
   SavonAI Design System v3 (CD-030 jobs-first pass, D-074).
   Assembled single-file from the design bundle: tokens (colors/typography/
   spacing/action-kinds) + base + components (v2 sections + jobs-first 19-30)
   + a small repo-compat tail. Source: SavonAI Design System.zip / design_handoff.
   ============================================================================ */

/* ============================================================================
   SavonAI — color tokens
   Light "app" theme (default) + dark "operator" theme (html[data-theme=operator]).
   Heritage names preserved: --ink --mut --line --bg --bg2 --pri --pri-d --acc --acc-d --ok
   ========================================================================== */

:root{
  /* ink + neutrals */
  --ink:#12152e;        /* primary text / headings            */
  --ink-2:#2b3257;      /* secondary heading                  */
  --mut:#5b6178;        /* muted body text                    */
  --faint:#8c92a8;      /* faintest text, captions            */
  --line:#e4e8f1;       /* default border                     */
  --line-2:#eef1f7;     /* hairline divider / inner border    */
  --bg:#ffffff;         /* surface (cards)                    */
  --bg2:#f5f7fc;        /* app canvas                         */
  --bg3:#eef2f8;        /* hover fill / inset                 */

  /* brand : blue primary + amber accent (the "Savo hill" spark) */
  --pri:#0b5cad;  --pri-d:#084a8c;  --pri-tint:#eaf2fb;  --pri-ring:#cfe2f7;
  --acc:#ffb020;  --acc-d:#e0922f;  --acc-tint:#fff6e6;  --acc-ink:#5a3d00;

  /* semantic */
  --ok:#1f9d63;   --ok-tint:#e7f6ee;   --ok-line:#bfe6cf;
  --warn:#c87a12; --warn-tint:#fdf3e2; --warn-line:#f1ddb4;
  --bad:#c4382f;  --bad-tint:#fcebea;  --bad-line:#f3c8c4;
  --on-pri:#ffffff;     /* text on primary fill               */
  --on-acc:#3a2700;     /* text on amber fill                 */
}

/* dark "operator" theme — warm graphite ground (not navy, not purple), high  */
/* contrast. Keeps brand blue + amber so the console reads as the same product.*/
html[data-theme="operator"]{
  --ink:#f7f3ec;  --ink-2:#e3dccf;  --mut:#c6bfb2;  --faint:#a39a8c;  /* D-214: AA/AAA on dark */
  --line:#39342d;  --line-2:#28241f;
  --bg:#26221d;    --bg2:#191611;    --bg3:#332e27;

  --pri:#5fa0f2;  --pri-d:#4a8ae4;  --pri-tint:#1c2a3a;  --pri-ring:#2f496b;
  --acc:#ffc56a;  --acc-d:#e0922f;  --acc-tint:#3a2c12;  --acc-ink:#1c1300;

  --ok:#5cc985;   --ok-tint:#173322;   --ok-line:#285437;
  --warn:#f0b659; --warn-tint:#372813; --warn-line:#574020;
  --bad:#f0837a;  --bad-tint:#3a1d1a;  --bad-line:#5a302b;
  --on-pri:#0a1424; --on-acc:#241700;
}

/* ============================================================================
   SavonAI — typography tokens + type-scale helpers
   Display face: Sora (variable, self-hosted — headings, numbers, brand).
   Body: native system stack (fast, framework-free).
   ========================================================================== */

@font-face{
  font-family:"Sora";
  src:url("fonts/Sora-Variable.ttf");
  font-weight:100 800;
  font-style:normal;
  font-display:swap;
}

:root{
  --font:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,"Helvetica Neue",Arial,sans-serif;
  --font-display:"Sora",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; /* @kind font */
}

/* type scale helpers — display face, weight 600–800, tight tracking */
.t-display{font-family:var(--font-display);font-size:clamp(38px,5.2vw,64px);font-weight:800;letter-spacing:-.03em;line-height:1.04}
.t-h1{font-family:var(--font-display);font-size:clamp(26px,3vw,36px);font-weight:800;letter-spacing:-.022em}
.t-h2{font-family:var(--font-display);font-size:20px;font-weight:700}
.t-h3{font-family:var(--font-display);font-size:16px;font-weight:700}
.t-lead{font-size:clamp(16px,1.6vw,19px);line-height:1.5;color:var(--mut)}
.t-body{font-size:15px;color:var(--ink)}
.t-sm{font-size:13px}
.t-xs{font-size:12px}
.mut{color:var(--mut)}
.faint{color:var(--faint)}
.mono{font-family:var(--mono)}
.nowrap{white-space:nowrap}

/* ============================================================================
   SavonAI — spacing, radius, elevation, layout + z-index tokens
   ========================================================================== */

:root{
  /* spacing scale (4-pt) */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:32px; --s7:48px; --s8:64px;

  /* radius */
  --r-xs:6px; --r-sm:9px; --r:12px; --r-lg:16px; --r-xl:20px; --r-pill:999px;

  /* elevation */
  --sh-1:0 1px 2px rgba(18,21,46,.05);
  --sh-2:0 1px 2px rgba(18,21,46,.04), 0 6px 22px rgba(18,21,46,.07);
  --sh-3:0 2px 4px rgba(18,21,46,.05), 0 18px 50px rgba(18,21,46,.12);
  --ring:0 0 0 3px var(--pri-ring);   /* focus ring */

  /* layout */
  --shell-side:248px;   /* sidebar width            */
  --shell-top:60px;     /* topbar height            */
  --content-max:1120px; /* content max width        */
  /* z-index scale */
  --z-base:1;       /* @kind other */
  --z-sticky:20;    /* @kind other */
  --z-nav:30;       /* @kind other */
  --z-dropdown:40;  /* @kind other */
  --z-modal:60;     /* @kind other */
  --z-toast:80;     /* @kind other */
}

/* operator theme deepens the shadows for the dark ground */
html[data-theme="operator"]{
  --sh-1:0 1px 2px rgba(0,0,0,.45);
  --sh-2:0 1px 2px rgba(0,0,0,.4), 0 8px 24px rgba(0,0,0,.45);
  --sh-3:0 2px 6px rgba(0,0,0,.45), 0 20px 50px rgba(0,0,0,.6);
}

/* ============================================================================
   SavonAI — action-kind tokens  (SPECCED, see ui-redesign.md §v3; CD-030, D-848)
   ----------------------------------------------------------------------------
   The v3 brief's spine is next_action(project, role) -> {label, why, KIND, …}.
   Each KIND must have a recognizable identity. This file adds ONE token family
   for the six kinds — it does NOT introduce a parallel color system: every hue
   is drawn from, or harmonized with, the existing brand + semantic tokens.

   Three semantic families map onto six kinds:
     • "AI is working for you"  → blue  (analyse) + teal (build)
     • "your decision"          → amber (review)              [the Savo spark]
     • "healthy / go / at-rest" → green (golive) · sage (care) · soft (none)

   Each kind exposes four locals via a `.k-<kind>` helper class, so components
   stay kind-agnostic and just read var(--k) / var(--k-tint) / var(--k-on) /
   var(--k-ink):
       --k       strong fill (buttons, dots, accent bars)
       --k-ink   AA-safe text/border version of the hue (on white)
       --k-tint  soft wash background
       --k-on    text color that sits on the strong fill
   ========================================================================== */

:root{
  /* analyse — blue (the AI reads your site) */
  --k-analyse:#0b5cad; --k-analyse-ink:#0b5cad; --k-analyse-tint:#eaf2fb; --k-analyse-on:#ffffff;
  /* build — teal (the AI constructs) */
  --k-build:#0e7c86;   --k-build-ink:#0c6f78;   --k-build-tint:#e0f2f3;   --k-build-on:#ffffff;
  /* review — amber (your call) */
  --k-review:#ffb020;  --k-review-ink:#8a5a0c;  --k-review-tint:#fff6e6;  --k-review-on:#3a2700;
  /* golive — green (go / launch) */
  --k-golive:#1f9d63;  --k-golive-ink:#157a4b;  --k-golive-tint:#e7f6ee;  --k-golive-on:#ffffff;
  /* care — sage (kept healthy) */
  --k-care:#5f7d99;    --k-care-ink:#45647f;    --k-care-tint:#eef2f7;    --k-care-on:#ffffff;
  /* none — soft green (nothing to do — good news, at rest) */
  --k-none:#5f9e7a;    --k-none-ink:#4f6b58;    --k-none-tint:#eef4f0;    --k-none-on:#ffffff;
}

/* operator theme — brighter hues for the warm-graphite dark ground */
html[data-theme="operator"]{
  --k-analyse:#5fa0f2; --k-analyse-ink:#5fa0f2; --k-analyse-tint:#1c2a3a; --k-analyse-on:#0a1424;
  --k-build:#4fc2cc;   --k-build-ink:#4fc2cc;   --k-build-tint:#10312f;   --k-build-on:#06201f;
  --k-review:#ffc56a;  --k-review-ink:#ffc56a;  --k-review-tint:#3a2c12;  --k-review-on:#241700;
  --k-golive:#5cc985;  --k-golive-ink:#5cc985;  --k-golive-tint:#173322;  --k-golive-on:#06210f;
  --k-care:#86a7c4;    --k-care-ink:#86a7c4;    --k-care-tint:#1a2735;    --k-care-on:#08131f;
  --k-none:#8fae95;    --k-none-ink:#8fae95;    --k-none-tint:#202a22;    --k-none-on:#0a160e;
}

/* dark marketing band re-scopes the same kinds (mirrors the operator ground) */
[data-band="dark"]{
  --k-analyse:#5fa0f2; --k-analyse-ink:#5fa0f2; --k-analyse-tint:#1c2a3a; --k-analyse-on:#0a1424;
  --k-build:#4fc2cc;   --k-build-ink:#4fc2cc;   --k-build-tint:#10312f;   --k-build-on:#06201f;
  --k-review:#ffc56a;  --k-review-ink:#ffc56a;  --k-review-tint:#3a2c12;  --k-review-on:#241700;
  --k-golive:#5cc985;  --k-golive-ink:#5cc985;  --k-golive-tint:#173322;  --k-golive-on:#06210f;
  --k-care:#86a7c4;    --k-care-ink:#86a7c4;    --k-care-tint:#1a2735;    --k-care-on:#08131f;
  --k-none:#8fae95;    --k-none-ink:#8fae95;    --k-none-tint:#202a22;    --k-none-on:#0a160e;
}

/* ---- kind helper classes — remap the generic --k locals per kind --------- */
/* Put `.k-review` (etc.) on any jobs-first component; it reads var(--k*).     */
.k-analyse{--k:var(--k-analyse);--k-ink:var(--k-analyse-ink);--k-tint:var(--k-analyse-tint);--k-on:var(--k-analyse-on)}
.k-build  {--k:var(--k-build);  --k-ink:var(--k-build-ink);  --k-tint:var(--k-build-tint);  --k-on:var(--k-build-on)}
.k-review {--k:var(--k-review); --k-ink:var(--k-review-ink); --k-tint:var(--k-review-tint); --k-on:var(--k-review-on)}
.k-golive {--k:var(--k-golive); --k-ink:var(--k-golive-ink); --k-tint:var(--k-golive-tint); --k-on:var(--k-golive-on)}
.k-care   {--k:var(--k-care);   --k-ink:var(--k-care-ink);   --k-tint:var(--k-care-tint);   --k-on:var(--k-care-on)}
.k-none   {--k:var(--k-none);   --k-ink:var(--k-none-ink);   --k-tint:var(--k-none-tint);   --k-on:var(--k-none-on)}

/* a sensible default so a component without a .k-* class still renders */
:root{--k:var(--pri);--k-ink:var(--pri);--k-tint:var(--pri-tint);--k-on:var(--on-pri)}

/* ============================================================================
   SavonAI — reset + base element styles
   ========================================================================== */

*{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--bg2);color:var(--ink);
  font:15px/1.55 var(--font);
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
}
a{color:var(--pri);text-decoration:none}
a:hover{text-decoration:underline}
h1,h2,h3,h4{margin:0;letter-spacing:-.018em;line-height:1.15;color:var(--ink);font-weight:700;font-family:var(--font-display,var(--font))}
p{margin:0}
img{max-width:100%;display:block}
hr{border:0;border-top:1px solid var(--line);margin:var(--s5) 0}
::selection{background:var(--pri-tint)}
:focus-visible{outline:none;box-shadow:var(--ring);border-radius:var(--r-xs)}

/* ============================================================================
   SavonAI — component classes
   App shell · marketing shell · buttons · card/panel · pills/badges/chips ·
   KPI/scorecard · forms · radio-cards · tables · states · sub-nav · auth.
   All driven by the tokens in tokens/*.css.
   ========================================================================== */

/* ---- 3. APP SHELL (surfaces B + C) -------------------------------------- */
.app{display:grid;grid-template-columns:var(--shell-side) 1fr;min-height:100vh}
.app__main{display:flex;flex-direction:column;min-width:0}
.scrim{display:none}

/* sidebar */
.sidebar{
  background:var(--bg);border-right:1px solid var(--line);
  display:flex;flex-direction:column;gap:var(--s2);
  padding:var(--s4) var(--s3);position:sticky;top:0;height:100vh;overflow-y:auto;
}
.sidebar__brand{display:flex;align-items:center;gap:10px;padding:var(--s2) var(--s2) var(--s4);font-weight:800;font-size:18px;color:var(--ink);letter-spacing:-.01em;font-family:var(--font-display)}
.sidebar__brand:hover{text-decoration:none}
.sidebar__brand .ai{color:var(--pri)}
.sidebar__brand svg{width:26px;height:26px;border-radius:7px;display:block;flex:none}
.nav-group{display:flex;flex-direction:column;gap:2px;margin-bottom:var(--s2)}
.nav-group__label{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--faint);padding:var(--s3) var(--s2) var(--s1)}
.nav-item{display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:var(--r-sm);color:var(--mut);font-weight:600;font-size:14px;min-height:40px}
.nav-item:hover{background:var(--bg3);color:var(--ink);text-decoration:none}
.nav-item--active{background:var(--pri-tint);color:var(--pri)}
.nav-item--active:hover{background:var(--pri-tint);color:var(--pri)}
.nav-item .ico{width:18px;height:18px;flex:none;opacity:.85}
.nav-item__badge{margin-left:auto;font-size:11px;font-weight:700;background:var(--bg3);color:var(--mut);border-radius:var(--r-pill);padding:1px 8px}
.sidebar__foot{margin-top:auto;padding-top:var(--s4)}

/* topbar */
.topbar{
  height:var(--shell-top);display:flex;align-items:center;gap:var(--s4);
  padding:0 var(--s5);background:var(--bg);border-bottom:1px solid var(--line);
  position:sticky;top:0;z-index:var(--z-sticky);
}
.topbar__crumbs{display:flex;align-items:center;gap:8px;font-size:14px;color:var(--mut);min-width:0}
.topbar__crumbs a{color:var(--mut);font-weight:600}
.topbar__crumbs a:hover{color:var(--ink)}
.topbar__crumbs .sep{color:var(--faint)}
.topbar__crumbs .cur{color:var(--ink);font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.topbar__right{margin-left:auto;display:flex;align-items:center;gap:var(--s3)}

/* lang switch */
.lang{display:inline-flex;align-items:center;border:1px solid var(--line);border-radius:var(--r-pill);overflow:hidden;font-size:12px;font-weight:700}
.lang a,.lang span{padding:5px 10px;color:var(--mut);display:block}
.lang a:hover{background:var(--bg3);text-decoration:none}
.lang .on{background:var(--pri-tint);color:var(--pri)}

/* AI status indicator */
.ai-status{display:inline-flex;align-items:center;gap:7px;font-size:12px;font-weight:700;color:var(--mut);padding:5px 11px;border:1px solid var(--line);border-radius:var(--r-pill)}
.ai-status .dot{width:8px;height:8px;border-radius:50%;background:var(--ok);box-shadow:0 0 0 3px var(--ok-tint)}
.ai-status--off{color:var(--bad)}
.ai-status--off .dot{background:var(--bad);box-shadow:0 0 0 3px var(--bad-tint)}

/* user menu chip */
.usermenu{display:inline-flex;align-items:center;gap:9px;padding:5px 10px 5px 6px;border:1px solid var(--line);border-radius:var(--r-pill);cursor:pointer;font-weight:600;font-size:13px;color:var(--ink);background:var(--bg)}
.usermenu:hover{background:var(--bg3)}
.avatar{width:28px;height:28px;border-radius:50%;background:var(--pri);color:#fff;display:grid;place-items:center;font-size:12px;font-weight:800;flex:none}
.avatar--amber{background:var(--acc);color:var(--on-acc)}

/* content region */
.content{flex:1;padding:var(--s6) var(--s5) var(--s8);width:100%}
.content__inner{max-width:var(--content-max);margin:0 auto}

/* page header */
.page-head{display:flex;align-items:flex-start;gap:var(--s4);flex-wrap:wrap;margin-bottom:var(--s5)}
.page-head__txt{min-width:0;flex:1}
.page-head h1{font-size:clamp(22px,2.6vw,28px);font-weight:800}
.page-head .sub{color:var(--mut);font-size:15px;margin-top:6px}
.page-head__actions{display:flex;gap:var(--s2);flex-wrap:wrap;align-items:center}

/* ---- 4. MARKETING shell (surface A) ------------------------------------- */
.site{background:var(--bg)}
.topnav{position:sticky;top:0;z-index:var(--z-nav);background:color-mix(in srgb,var(--bg) 85%,transparent);backdrop-filter:saturate(1.4) blur(10px);border-bottom:1px solid var(--line)}
.topnav__in{max-width:var(--content-max);margin:0 auto;padding:0 var(--s5);height:64px;display:flex;align-items:center;gap:var(--s6)}
.brand{display:flex;align-items:center;gap:10px;font-weight:800;font-size:19px;color:var(--ink);letter-spacing:-.01em;font-family:var(--font-display)}
.brand:hover{text-decoration:none}
.brand .ai{color:var(--pri)}
.brand svg{width:28px;height:28px;border-radius:8px;display:block;flex:none}
.topnav__links{display:flex;align-items:center;gap:var(--s5);margin-left:auto}
.topnav__links a:not(.btn){color:var(--mut);font-weight:600;font-size:15px}
.topnav__links a:not(.btn):hover{color:var(--ink);text-decoration:none}
.wrap{max-width:var(--content-max);margin:0 auto;padding:0 var(--s5)}
.wrap--narrow{max-width:760px}
.section{padding:var(--s8) 0}
.section--tint{background:var(--bg2);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.site-foot{background:var(--bg2);border-top:1px solid var(--line);padding:var(--s7) 0;color:var(--mut);font-size:14px}
.site-foot__in{max-width:var(--content-max);margin:0 auto;padding:0 var(--s5);display:flex;flex-wrap:wrap;gap:var(--s4);align-items:center;justify-content:space-between}

/* ---- 5. BUTTONS --------------------------------------------------------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  background:var(--pri);color:var(--on-pri);font-weight:700;font-size:14px;
  border:1px solid transparent;border-radius:var(--r-sm);
  padding:0 16px;min-height:40px;cursor:pointer;transition:.14s ease;
  text-decoration:none;white-space:nowrap;font-family:inherit;
}
.btn:hover{background:var(--pri-d);text-decoration:none;color:var(--on-pri)}
.btn:active{transform:translateY(1px)}
.btn .ico{width:16px;height:16px;flex:none}
.btn--amber{background:var(--acc);color:var(--on-acc);border-color:transparent}
.btn--amber:hover{background:var(--acc-d);color:var(--on-acc)}
.btn--sec{background:var(--bg);color:var(--ink);border-color:var(--line)}
.btn--sec:hover{background:var(--bg3);color:var(--ink)}
.btn--ghost{background:transparent;color:var(--ink);border-color:var(--line)}
.btn--ghost:hover{background:var(--bg3);color:var(--ink)}
.btn--quiet{background:transparent;color:var(--mut);border-color:transparent;padding:0 10px}
.btn--quiet:hover{background:var(--bg3);color:var(--ink)}
.btn--danger{background:var(--bg);color:var(--bad);border-color:var(--bad-line)}
.btn--danger:hover{background:var(--bad-tint);color:var(--bad)}
.btn--link{background:none;border:0;color:var(--pri);padding:0;min-height:0;font-weight:700}
.btn--link:hover{text-decoration:underline;background:none}
.btn--lg{min-height:48px;padding:0 24px;font-size:16px;border-radius:var(--r)}
.btn--sm{min-height:32px;padding:0 12px;font-size:13px;border-radius:var(--r-xs)}
.btn--block{display:flex;width:100%}
.btn--icon{padding:0;width:40px;min-height:40px}
.btn[disabled],.btn[aria-disabled="true"]{opacity:.5;cursor:not-allowed;pointer-events:none}
.btn.is-loading{color:transparent;position:relative;pointer-events:none}
.btn.is-loading::after{content:"";position:absolute;width:16px;height:16px;border-radius:50%;border:2px solid currentColor;border-top-color:transparent;color:#fff;animation:spin .7s linear infinite}
.btn--sec.is-loading::after,.btn--ghost.is-loading::after{color:var(--ink)}
@keyframes spin{to{transform:rotate(360deg)}}

/* ---- 6. CARD + PANEL ---------------------------------------------------- */
.card{background:var(--bg);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--sh-1)}
.card--pad{padding:var(--s5)}
.card--link{display:block;color:inherit;transition:.14s ease}
.card--link:hover{text-decoration:none;border-color:var(--pri-ring);box-shadow:var(--sh-2);transform:translateY(-2px)}

/* panel = card with a header row + body, the workhorse app container */
.panel{background:var(--bg);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--sh-1);overflow:hidden}
.panel__head{display:flex;align-items:center;gap:var(--s3);padding:var(--s4) var(--s5);border-bottom:1px solid var(--line-2)}
.panel__head h3{font-size:15px;font-weight:700}
.panel__head .sub{font-size:13px;color:var(--mut);margin-top:2px}
.panel__head .ico{width:18px;height:18px;color:var(--mut);flex:none}
.panel__head__actions{margin-left:auto;display:flex;gap:var(--s2);align-items:center}
.panel__body{padding:var(--s5)}
.panel__body--flush{padding:0}
.panel__foot{padding:var(--s3) var(--s5);border-top:1px solid var(--line-2);background:var(--bg2);font-size:13px;color:var(--mut);display:flex;gap:var(--s3);align-items:center;flex-wrap:wrap}

/* generic layout helpers */
.row{display:flex;gap:var(--s3);flex-wrap:wrap;align-items:center}
.row--between{justify-content:space-between}
.stack{display:flex;flex-direction:column;gap:var(--s4)}
.stack--sm{gap:var(--s2)}
.grid{display:grid;gap:var(--s4)}
.g2{grid-template-columns:repeat(2,1fr)}
.g3{grid-template-columns:repeat(3,1fr)}
.g4{grid-template-columns:repeat(4,1fr)}
.grid-auto{grid-template-columns:repeat(auto-fill,minmax(260px,1fr))}
/* the dense work layout : main + rail */
.work{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:var(--s5);align-items:start}

/* ---- 7. PILLS / BADGES / CHIPS ------------------------------------------ */
.pill{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;border-radius:var(--r-pill);padding:4px 11px;background:var(--bg3);border:1px solid var(--line);color:var(--mut);white-space:nowrap}
.pill a,.pill.is-link{color:inherit}
.pill .dot{width:7px;height:7px;border-radius:50%;background:currentColor}
.pill--pri{background:var(--pri-tint);border-color:transparent;color:var(--pri)}
.pill--ok{background:var(--ok-tint);border-color:var(--ok-line);color:var(--ok)}
.pill--warn{background:var(--warn-tint);border-color:var(--warn-line);color:var(--warn)}
.pill--bad{background:var(--bad-tint);border-color:var(--bad-line);color:var(--bad)}
.pill--amber{background:var(--acc-tint);border-color:var(--acc-line,var(--acc));color:var(--acc-d)}
.pill--ghost{background:transparent}

.badge{display:inline-flex;align-items:center;gap:5px;font-size:12px;font-weight:700;border-radius:var(--r-pill);padding:3px 9px;line-height:1.2}
.badge--verified{background:var(--ok-tint);border:1px solid var(--ok-line);color:var(--ok)}
.badge--ai{background:var(--acc-tint);border:1px solid var(--acc);color:var(--acc-d)}
.badge--premium{background:var(--pri-tint);border:1px solid transparent;color:var(--pri)}
.badge--tier{background:var(--bg3);border:1px solid var(--line);color:var(--mut)}

/* key:value chip */
.kv{display:inline-flex;align-items:baseline;gap:6px;font-size:13px;background:var(--bg2);border:1px solid var(--line);border-radius:var(--r-sm);padding:5px 10px}
.kv b{font-weight:700;color:var(--ink)}
.kv span{color:var(--mut)}

/* download / code chip */
.chip-dl{display:inline-flex;align-items:center;gap:7px;font-size:13px;font-weight:600;background:var(--bg2);border:1px solid var(--line);border-radius:var(--r-sm);padding:7px 12px;color:var(--ink)}
.chip-dl:hover{background:var(--bg3);text-decoration:none}
.chip-dl .ico{width:15px;height:15px;color:var(--mut)}

/* ---- 8. KPI / SCORECARD ------------------------------------------------- */
.scorecard{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:var(--s3)}
.kpi{background:var(--bg2);border:1px solid var(--line);border-radius:var(--r);padding:var(--s4)}
.kpi__val{font-family:var(--font-display);font-size:30px;font-weight:800;letter-spacing:-.02em;line-height:1;color:var(--ink)}
.kpi__val small{font-size:14px;font-weight:600;color:var(--faint)}
.kpi__label{font-size:12px;color:var(--mut);margin-top:7px;font-weight:600}
.kpi--feature{background:var(--pri-tint);border-color:transparent}
.kpi--feature .kpi__val{color:var(--pri)}
/* score meter bar */
.meter{height:6px;border-radius:var(--r-pill);background:var(--bg3);overflow:hidden;margin-top:10px}
.meter > i{display:block;height:100%;border-radius:inherit;background:var(--pri);transition:width .8s cubic-bezier(.22,.8,.3,1)}
.meter--ok > i{background:var(--ok)}
.meter--warn > i{background:var(--acc)}
.meter--bad > i{background:var(--bad)}

/* ---- 9. FORMS ----------------------------------------------------------- */
.field-label{display:block;font-size:13px;font-weight:600;color:var(--mut);margin-bottom:6px}
.help{font-size:12px;color:var(--faint);margin-top:6px}
.input,.select,.textarea{
  font:inherit;width:100%;color:var(--ink);background:var(--bg);
  border:1px solid var(--line);border-radius:var(--r-sm);padding:10px 12px;min-height:40px;transition:.14s;
}
.textarea{min-height:auto;line-height:1.5;resize:vertical}
.input::placeholder,.textarea::placeholder{color:var(--faint)}
.input:focus,.select:focus,.textarea:focus{outline:none;border-color:var(--pri);box-shadow:var(--ring)}
.input:disabled,.select:disabled{background:var(--bg2);color:var(--faint);cursor:not-allowed}
.select{appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5 6 8l3-3.5' stroke='%235b6178' stroke-width='1.4' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 12px center;padding-right:32px}
.input--invalid{border-color:var(--bad)}
.input--invalid:focus{box-shadow:0 0 0 3px var(--bad-tint)}

/* inline field + action (url -> analyse) */
.field-inline{display:flex;gap:var(--s2);flex-wrap:wrap}
.field-inline .input{flex:1;min-width:200px}
.field-inline .btn{flex:none}
.field-prefix{display:flex;align-items:stretch;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--bg);overflow:hidden;flex:1;min-width:220px}
.field-prefix:focus-within{border-color:var(--pri);box-shadow:var(--ring)}
.field-prefix .px{display:flex;align-items:center;padding:0 4px 0 12px;color:var(--faint);font-size:14px}
.field-prefix .input{border:0;box-shadow:none!important;padding-left:4px}

/* checkbox / radio (native, styled) */
.check{display:inline-flex;align-items:flex-start;gap:9px;font-size:14px;color:var(--ink);cursor:pointer}
.check input{width:18px;height:18px;accent-color:var(--pri);margin:1px 0 0;flex:none}

/* ---- 10. SELECTABLE RADIO-CARDS (style packs + build tiers) ------------- */
.radio-grid{display:grid;gap:var(--s3);grid-template-columns:repeat(auto-fill,minmax(190px,1fr))}
.radio-grid--3{grid-template-columns:repeat(3,1fr)}
.radio-card{position:relative;cursor:pointer;display:block}
.radio-card > input{position:absolute;opacity:0;width:0;height:0;pointer-events:none}
.radio-card__box{
  display:block;height:100%;border:1.5px solid var(--line);border-radius:var(--r);
  padding:var(--s4);background:var(--bg);transition:.14s;
}
.radio-card:hover .radio-card__box{border-color:var(--pri-ring)}
.radio-card > input:checked + .radio-card__box{border-color:var(--pri);box-shadow:0 0 0 3px var(--pri-ring);background:var(--pri-tint)}
.radio-card > input:focus-visible + .radio-card__box{border-color:var(--pri);box-shadow:var(--ring)}
.radio-card__box b{display:block;font-size:15px;font-weight:700}
.radio-card__d{display:block;color:var(--mut);font-size:13px;margin:5px 0 0;line-height:1.45}
.radio-card__lim{display:block;color:var(--faint);font-size:12px;font-weight:600;margin-top:10px}
.radio-card__check{position:absolute;top:12px;right:12px;width:18px;height:18px;border-radius:50%;border:1.5px solid var(--line);display:grid;place-items:center;color:#fff;background:var(--bg)}
.radio-card > input:checked + .radio-card__box .radio-card__check{background:var(--pri);border-color:var(--pri)}
.radio-card > input:checked + .radio-card__box .radio-card__check::after{content:"";width:6px;height:6px;border-radius:50%;background:#fff}
.swatches{display:flex;gap:5px;margin-top:12px}
.swatch{width:22px;height:22px;border-radius:6px;border:1px solid rgba(0,0,0,.12)}

/* ---- 11. TABLES (operator worklists) ------------------------------------ */
.table-wrap{overflow-x:auto}
.table{width:100%;border-collapse:collapse;font-size:14px}
.table th{text-align:left;padding:10px 14px;color:var(--faint);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;border-bottom:1px solid var(--line);background:var(--bg2);position:sticky;top:0}
.table td{padding:12px 14px;border-bottom:1px solid var(--line-2);vertical-align:middle}
.table tr:last-child td{border-bottom:0}
.table tbody tr:hover{background:var(--bg2)}
.table .mono-id{font-family:var(--mono);font-size:12px;color:var(--faint)}
.table-card{background:var(--bg);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--sh-1)}

/* ---- 12. STATES : note / alert / empty / loading / progress / locked ---- */
.alert{display:flex;gap:11px;padding:var(--s4);border-radius:var(--r);border:1px solid;font-size:14px;line-height:1.5}
.alert .ico{width:18px;height:18px;flex:none;margin-top:1px}
.alert__title{font-weight:700}
.alert--info{background:var(--pri-tint);border-color:transparent;color:var(--pri-d)}
.alert--ok{background:var(--ok-tint);border-color:var(--ok-line);color:#15623f}
.alert--warn{background:var(--warn-tint);border-color:var(--warn-line);color:#7a4d09}
.alert--bad{background:var(--bad-tint);border-color:var(--bad-line);color:#8c241c}
html[data-theme="operator"] .alert--info{color:var(--ink)}
html[data-theme="operator"] .alert--ok{color:var(--ok)}
html[data-theme="operator"] .alert--warn{color:var(--warn)}
html[data-theme="operator"] .alert--bad{color:var(--bad)}

/* empty state */
.empty{text-align:center;padding:var(--s8) var(--s5);border:1.5px dashed var(--line);border-radius:var(--r-lg);background:var(--bg2)}
.empty__ico{width:46px;height:46px;border-radius:var(--r);background:var(--bg);border:1px solid var(--line);display:grid;place-items:center;margin:0 auto var(--s4);color:var(--mut)}
.empty h3{font-size:17px}
.empty p{color:var(--mut);max-width:380px;margin:8px auto var(--s4)}

/* loading skeleton */
.skel{position:relative;overflow:hidden;background:var(--bg3);border-radius:var(--r-xs)}
.skel::after{content:"";position:absolute;inset:0;transform:translateX(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--bg) 60%,transparent),transparent);animation:shimmer 1.3s infinite}
@keyframes shimmer{100%{transform:translateX(100%)}}
.skel-line{height:12px;margin:8px 0;border-radius:var(--r-pill)}

/* live progress / running stages */
.run-head{display:flex;align-items:center;gap:11px}
.spinner{width:16px;height:16px;border-radius:50%;border:2px solid var(--pri);border-top-color:transparent;animation:spin .7s linear infinite;flex:none}
.stages{list-style:none;margin:var(--s4) 0 0;padding:0;position:relative}
.stages li{display:flex;gap:12px;padding:0 0 var(--s4);position:relative}
.stages li:last-child{padding-bottom:0}
.stage__rail{display:flex;flex-direction:column;align-items:center;flex:none}
.stage__bullet{width:18px;height:18px;border-radius:50%;border:2px solid var(--line);background:var(--bg);display:grid;place-items:center;z-index:1}
.stages li:not(:last-child) .stage__rail::after{content:"";flex:1;width:2px;background:var(--line);margin-top:2px}
.stage__body{padding-bottom:2px;min-width:0}
.stage__t{font-weight:700;font-size:14px}
.stage__time{font-size:12px;color:var(--faint);font-family:var(--mono)}
.stage--done .stage__bullet{background:var(--ok);border-color:var(--ok);color:#fff}
.stage--done .stage__rail::after{background:var(--ok)}
.stage--active .stage__bullet{border-color:var(--pri);box-shadow:0 0 0 3px var(--pri-ring)}
.stage--active .stage__bullet::after{content:"";width:7px;height:7px;border-radius:50%;background:var(--pri)}
.stage--pending .stage__t{color:var(--faint)}

/* locked / upgrade gate */
.locked{display:flex;gap:var(--s4);align-items:center;padding:var(--s5);border:1px solid var(--line);border-radius:var(--r-lg);background:linear-gradient(180deg,var(--bg2),var(--bg));position:relative}
.locked__ico{width:42px;height:42px;border-radius:var(--r);background:var(--acc-tint);border:1px solid var(--acc);color:var(--acc-d);display:grid;place-items:center;flex:none}
.locked__txt{flex:1;min-width:0}
.locked__txt h4{font-size:15px}
.locked__txt p{font-size:13px;color:var(--mut);margin-top:3px}
.locked-row{opacity:.55;pointer-events:none;filter:saturate(.4)}

/* issue list (label + why + learn more) */
.issues{display:flex;flex-direction:column}
.issue{padding:var(--s4) 0;border-top:1px solid var(--line-2);display:flex;gap:var(--s3)}
.issue:first-child{border-top:0;padding-top:0}
.issue__sev{width:9px;height:9px;border-radius:50%;margin-top:7px;flex:none;background:var(--mut)}
.issue__sev--high{background:var(--bad)}
.issue__sev--med{background:var(--acc)}
.issue__sev--low{background:var(--ok)}
.issue__main{min-width:0;flex:1}
.issue__t{font-weight:700;font-size:14.5px}
.issue__d{color:var(--mut);font-size:13.5px;margin-top:3px;line-height:1.5}
.issue__why{font-size:13px;margin-top:6px;line-height:1.5}
.issue__why b{color:var(--ink)}
.issue__more{font-size:13px;font-weight:700;margin-top:6px;display:inline-block}

/* result row (project_seo audit results) */
.result-row{display:flex;gap:var(--s4);align-items:flex-start;padding:var(--s4) 0;border-top:1px solid var(--line-2)}
.result-row:first-child{border-top:0}
.result-row__main{flex:1;min-width:0}
.result-row__chips{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px}

/* ---- 13. SUB-NAV / TABS ------------------------------------------------- */
.tabs{display:flex;gap:2px;border-bottom:1px solid var(--line);margin-bottom:var(--s5)}
.tab{display:inline-flex;align-items:center;gap:7px;padding:11px 14px;font-weight:600;font-size:14px;color:var(--mut);border-bottom:2px solid transparent;margin-bottom:-1px}
.tab:hover{color:var(--ink);text-decoration:none}
.tab--active{color:var(--pri);border-bottom-color:var(--pri)}
.breadcrumb-back{display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:600;color:var(--mut)}
.breadcrumb-back:hover{color:var(--ink);text-decoration:none}

/* kicker (marketing) */
.kicker{display:inline-flex;align-items:center;gap:7px;font-size:12.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--pri);background:var(--pri-tint);border:1px solid transparent;padding:5px 13px;border-radius:var(--r-pill)}

/* price */
.price{font-family:var(--font-display);font-size:38px;font-weight:800;letter-spacing:-.03em;color:var(--ink)}
.price small{font-size:15px;font-weight:600;color:var(--mut)}

/* utility */
.divider{height:1px;background:var(--line-2);margin:var(--s4) 0}
.mt2{margin-top:var(--s2)}.mt3{margin-top:var(--s3)}.mt4{margin-top:var(--s4)}.mt5{margin-top:var(--s5)}
.center{text-align:center}
.hidden{display:none!important}
.spread{margin-left:auto}

/* ---- 14. RESPONSIVE ----------------------------------------------------- */
.menu-btn{display:none}
@media(max-width:1000px){
  .work{grid-template-columns:1fr}
  .g4{grid-template-columns:repeat(2,1fr)}
  .radio-grid--3{grid-template-columns:1fr}
}
@media(max-width:860px){
  .app{grid-template-columns:1fr}
  .sidebar{position:fixed;left:0;top:0;z-index:var(--z-modal);width:var(--shell-side);transform:translateX(-100%);transition:transform .2s ease;box-shadow:var(--sh-3)}
  .app.nav-open .sidebar{transform:translateX(0)}
  .menu-btn{display:inline-grid}
  .scrim{position:fixed;inset:0;background:rgba(10,12,24,.4);z-index:var(--z-dropdown)}
  .app.nav-open .scrim{display:block}
  .g2,.g3{grid-template-columns:1fr}
  .topnav__links a:not(.btn):not(.lang-link){display:none}
  /* D-214: the header must FIT — brand + lang + CTA on one row, no clipping */
  .topnav__in{gap:var(--s3);padding:0 var(--s4)}
  .topnav__links{gap:var(--s3);min-width:0;flex-shrink:1}
  .topnav__links .btn{padding:9px 14px;font-size:14px;white-space:nowrap}
  .content{padding:var(--s5) var(--s4) var(--s7)}
  .page-head__actions{width:100%}
}
@media(max-width:430px){
  .brand{font-size:19px}
  .brand svg{width:26px;height:26px}
  .topnav__links .btn{padding:8px 10px;font-size:13px}
  .lang{transform:scale(.92);transform-origin:right center}
}
@media(max-width:560px){
  .g4{grid-template-columns:1fr}
  .scorecard{grid-template-columns:repeat(2,1fr)}
}
.menu-btn{width:40px;height:40px;border-radius:var(--r-sm);border:1px solid var(--line);background:var(--bg);place-items:center;cursor:pointer;color:var(--ink)}

/* ---- 15. AUTH LAYOUT ---------------------------------------------------- */
.auth{min-height:100vh;display:grid;grid-template-columns:1.05fr .95fr}
.auth__aside{background:var(--pri);color:#fff;padding:48px 56px;display:flex;flex-direction:column;position:relative;overflow:hidden}
.auth__aside::after{content:"";position:absolute;right:-80px;bottom:-80px;width:340px;height:340px;border-radius:50%;background:rgba(255,255,255,.06)}
.auth__aside .brand{color:#fff}
.auth__aside .brand .ai{color:#fff}
.auth__aside--operator{background:var(--bg2)}
.auth__main{display:flex;align-items:center;justify-content:center;padding:40px 24px;background:var(--bg2)}
.auth__card{width:100%;max-width:420px}
.auth__pt{margin-top:auto}
.reassure{display:flex;gap:12px;align-items:flex-start;margin-top:18px}
.reassure .tick{width:22px;height:22px;border-radius:50%;background:rgba(255,255,255,.16);display:grid;place-items:center;flex:none;margin-top:1px}
@media(max-width:820px){.auth{grid-template-columns:1fr}.auth__aside{display:none}}

/* ---- 16. MARKETING DARK BAND ------------------------------------------- */
/* One dark section per marketing page max — the operator graphite re-scoped */
/* so any component dropped inside re-themes automatically.                  */
/* Usage: <section class="section" data-band="dark">                         */
[data-band="dark"]{
  --ink:#f7f3ec; --ink-2:#e3dccf; --mut:#c6bfb2; --faint:#a39a8c;
  --line:#39342d; --line-2:#28241f;
  --bg:#26221d; --bg2:#191611; --bg3:#332e27;
  --pri:#5fa0f2; --pri-d:#4a8ae4; --pri-tint:#1c2a3a; --pri-ring:#2f496b;
  --acc:#ffc56a; --acc-tint:#3a2c12;
  --ok:#5cc985; --ok-tint:#173322; --ok-line:#285437;
  --sh-1:0 1px 2px rgba(0,0,0,.45);
  --sh-2:0 1px 2px rgba(0,0,0,.4), 0 8px 24px rgba(0,0,0,.45);
  background:var(--bg2);color:var(--ink);
  border-top:1px solid var(--line-2);border-bottom:1px solid var(--line-2);
  position:relative;overflow:hidden;
}

/* ---- 17. WIZARD (Opastettu — one question per screen) ------------------- */
.wiz-page{background:var(--bg2);min-height:100vh;display:flex;flex-direction:column}
.wiz-top{display:flex;align-items:center;justify-content:space-between;gap:var(--s4);padding:14px clamp(16px,4vw,32px)}
.wiz-progress{display:flex;align-items:center;gap:10px;min-width:min(300px,44vw)}
.wiz-bar{flex:1;height:6px;border-radius:var(--r-pill);background:var(--line);overflow:hidden}
.wiz-bar i{display:block;height:100%;background:var(--pri);border-radius:inherit;transition:width .35s ease}
.wiz{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:24px 16px 64px;width:100%}
.wiz-step{width:100%;max-width:520px;animation:wizIn .3s ease both}
.wiz-step--wide{max-width:720px}
@keyframes wizIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.wiz-q{font-family:var(--font-display);font-size:clamp(24px,4.6vw,32px);line-height:1.12;letter-spacing:-.025em;margin:0 0 8px;font-weight:800;color:var(--ink)}
.wiz-q--sub{font-size:clamp(18px,3.6vw,22px)}
.wiz-help{color:var(--mut);margin:0 0 22px;font-size:15px}
.wiz-options{display:grid;gap:10px}
.wiz-option{display:grid;gap:3px;text-align:left;width:100%;padding:16px 18px;min-height:56px;border:1.5px solid var(--line);border-radius:14px;background:var(--bg);cursor:pointer;font:inherit;color:var(--ink);transition:border-color .15s,box-shadow .15s,transform .15s;text-decoration:none}
.wiz-option:hover{border-color:var(--pri);box-shadow:var(--sh-2);transform:translateY(-1px);text-decoration:none;color:var(--ink)}
.wiz-option:active{transform:translateY(0)}
.wiz-option b{font-size:15px}
.wiz-option--eos{border-style:dashed;color:var(--mut);background:transparent}
.wiz-option.is-selected{border-color:var(--pri);box-shadow:0 0 0 3px var(--pri-ring);background:var(--pri-tint)}
.wiz-paths{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:10px}
.wiz-path--soon{opacity:.55;cursor:not-allowed}
.wiz-nav{display:flex;justify-content:space-between;align-items:center;margin-top:26px}
.wiz-back,.wiz-skip{background:none;border:0;color:var(--mut);font:inherit;font-size:14px;cursor:pointer;padding:10px 4px;text-decoration:none}
.wiz-back:hover,.wiz-skip:hover{color:var(--ink);text-decoration:none}
.wiz-cta{width:100%}
.wiz-findings{margin:14px 0 0;padding-left:20px;display:grid;gap:6px;color:var(--mut);font-size:14px}
.input--lg{min-height:52px;font-size:16px;padding:12px 16px}
@media(max-width:560px){.wiz{justify-content:flex-start;padding-top:8vh}.wiz-progress{min-width:38vw}}

/* ============================================================================
   JOBS-FIRST SYSTEM (CD-030) — every screen renders ONE next_action.
   §19 kind button + cost · §20 next-action hero · §21 journey stepper ·
   §22 receipt · §23 queue row · §24 run-sheet step · §25 care feed/all-clear ·
   §26 pre-flight gate · §27 talking-point · §28 honest progress.
   All kind color comes from var(--k*) set by a .k-<kind> class (action-kinds.css).
   ========================================================================== */

/* ---- 19. KIND BUTTON + COST-ON-BUTTON ----------------------------------- */
/* .btn--kind takes the colour of whatever .k-<kind> sits on it or an ancestor */
.btn--kind{background:var(--k);color:var(--k-on);border-color:transparent}
.btn--kind:hover{background:var(--k);color:var(--k-on);filter:brightness(.93)}
html[data-theme="operator"] .btn--kind:hover{filter:brightness(1.1)}
/* stacked button: action label over a quiet cost/credits line (money honesty) */
.btn--stack{flex-direction:column;gap:1px;min-height:52px;padding-top:7px;padding-bottom:7px;line-height:1.15}
.btn__cost{font-size:12px;font-weight:600;opacity:.82}
/* standalone cost note under an action */
.cost-note{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;color:var(--faint);font-weight:600}
.cost-note b{color:var(--mut);font-weight:700}

/* ---- 20. NEXT-ACTION HERO (the one dominant step on every screen) -------- */
.next-action{
  position:relative;border:1px solid var(--line);border-left:4px solid var(--k);
  border-radius:var(--r-lg);background:
    linear-gradient(90deg,color-mix(in srgb,var(--k-tint) 70%,var(--bg)),var(--bg) 62%);
  box-shadow:var(--sh-2);padding:var(--s5) var(--s5) var(--s5) calc(var(--s5) - 3px);
  display:flex;flex-direction:column;gap:var(--s3);
}
.next-action__kind{display:inline-flex;align-items:center;gap:7px;font-size:12px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--k-ink)}
.next-action__kind svg{width:16px;height:16px;flex:none}
.next-action__label{font-family:var(--font-display);font-size:clamp(20px,2.4vw,26px);font-weight:800;letter-spacing:-.02em;line-height:1.12;color:var(--ink);margin:0}
.next-action__why{font-size:14.5px;color:var(--mut);margin:0;line-height:1.5;max-width:60ch}
.next-action__cta{display:flex;gap:var(--s3);flex-wrap:wrap;align-items:center;margin-top:var(--s2)}
.next-action__cta .btn{min-width:min(280px,100%)}
.next-action--lg .next-action__label{font-size:clamp(24px,3.4vw,34px)}
.next-action--lg{padding:var(--s6) var(--s6) var(--s6) calc(var(--s6) - 3px)}
/* the kind eyebrow can carry a small round glyph badge */
.next-action__badge{width:34px;height:34px;border-radius:var(--r-sm);background:var(--k-tint);color:var(--k-ink);display:grid;place-items:center;flex:none}
.next-action__badge svg{width:19px;height:19px}
.next-action__row{display:flex;align-items:flex-start;gap:var(--s3)}

/* ---- 21. JOURNEY STEPPER (customer — 7 stages, receipts collapse) -------- */
.journey{display:flex;gap:0;list-style:none;margin:0 0 var(--s5);padding:0;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.journey::-webkit-scrollbar{display:none}
.journey__step{flex:1;min-width:96px;position:relative;display:flex;flex-direction:column;align-items:center;gap:7px;padding:0 4px;text-align:center;color:var(--faint)}
/* connector line runs behind the dots */
.journey__step::before{content:"";position:absolute;top:11px;left:-50%;width:100%;height:2px;background:var(--line);z-index:0}
.journey__step:first-child::before{display:none}
.journey__dot{position:relative;z-index:1;width:24px;height:24px;border-radius:50%;border:2px solid var(--line);background:var(--bg);display:grid;place-items:center;font-size:12px;font-weight:800;color:var(--faint)}
.journey__name{font-size:12px;font-weight:600;line-height:1.25;max-width:12ch}
.journey__step.is-done{color:var(--ok)}
.journey__step.is-done .journey__dot{background:var(--ok);border-color:var(--ok);color:#fff}
.journey__step.is-done::before{background:var(--ok)}
.journey__step.is-active{color:var(--k-ink)}
.journey__step.is-active .journey__dot{border-color:var(--k);color:var(--k-ink);box-shadow:0 0 0 4px var(--k-tint)}
.journey__step.is-active .journey__name{font-weight:800}
.journey__step.is-active::before{background:linear-gradient(90deg,var(--ok),var(--k))}
.journey__step.is-future .journey__dot{border-style:dashed}

/* ---- 22. RECEIPT (collapsed done-stage / done-step, one line) ------------ */
.receipt{display:flex;align-items:center;gap:var(--s3);padding:11px var(--s4);border:1px solid var(--line);border-radius:var(--r);background:var(--bg);color:var(--mut);font-size:13.5px;min-height:44px}
.receipt + .receipt{margin-top:var(--s2)}
.receipt__ico{width:20px;height:20px;border-radius:50%;background:var(--ok-tint);color:var(--ok);display:grid;place-items:center;flex:none}
.receipt__ico svg{width:12px;height:12px}
.receipt__txt{flex:1;min-width:0;color:var(--ink)}
.receipt__txt b{font-weight:700}
.receipt__meta{color:var(--faint);font-family:var(--mono);font-size:12px}
.receipt__link{flex:none;font-weight:700;font-size:13px;color:var(--pri)}
.receipt--muted{background:var(--bg2)}
.receipt--verdict .receipt__ico{background:var(--k-tint);color:var(--k-ink)}

/* ---- 23. QUEUE ROW (expert / sales — project + ONE next step + age) ------ */
.queue{display:flex;flex-direction:column;gap:var(--s2)}
.queue-row{display:flex;align-items:center;gap:var(--s4);padding:var(--s4);border:1px solid var(--line);border-radius:var(--r);background:var(--bg);color:inherit;transition:.14s ease}
.queue-row:hover{text-decoration:none;border-color:var(--pri-ring);box-shadow:var(--sh-2);transform:translateY(-1px)}
.queue-row__co{min-width:0;flex:1 1 40%}
.queue-row__co b{display:block;font-weight:700;font-size:15px;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.queue-row__url{font-size:12.5px;color:var(--faint);font-family:var(--mono)}
.queue-row__next{flex:1 1 40%;display:inline-flex;align-items:center;gap:8px;font-weight:700;font-size:14px;color:var(--k-ink);min-width:0}
.queue-row__next svg{width:16px;height:16px;flex:none}
.queue-row__next .lbl{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.queue-row__age{flex:none;font-size:12.5px;font-weight:700;font-family:var(--mono);color:var(--mut);background:var(--bg2);border:1px solid var(--line);border-radius:var(--r-pill);padding:3px 10px;white-space:nowrap}
.queue-row__chev{flex:none;width:18px;height:18px;color:var(--faint)}
/* the top row = "start here": lifted, kind-accented left edge */
.queue-row--top{border-left:4px solid var(--k);background:linear-gradient(90deg,color-mix(in srgb,var(--k-tint) 60%,var(--bg)),var(--bg) 50%);box-shadow:var(--sh-2)}
.queue-row--top .queue-row__co b{font-size:16px}
@media(max-width:640px){
  .queue-row{flex-wrap:wrap;gap:var(--s2) var(--s4)}
  .queue-row__co{flex:1 1 100%}
  .queue-row__next{flex:1 1 auto}
}

/* ---- 24. RUN-SHEET STEP (expert — one vertical operation sheet) ---------- */
.runsheet{list-style:none;margin:0;padding:0;position:relative}
.rs-step{display:flex;gap:var(--s4);padding:0 0 var(--s4)}
.rs-step:last-child{padding-bottom:0}
.rs-step__rail{display:flex;flex-direction:column;align-items:center;flex:none;width:26px}
.rs-step__dot{width:26px;height:26px;border-radius:50%;border:2px solid var(--line);background:var(--bg);display:grid;place-items:center;font-size:12px;font-weight:800;color:var(--faint);z-index:1}
.rs-step:not(:last-child) .rs-step__rail::after{content:"";flex:1;width:2px;background:var(--line);margin:3px 0}
.rs-step__body{flex:1;min-width:0;padding-bottom:2px}
.rs-step__head{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;min-height:26px}
.rs-step__head b{font-family:var(--font-display);font-size:15px;font-weight:700;color:var(--ink)}
.rs-step__meta{font-size:12px;color:var(--faint);font-family:var(--mono)}
/* done → compact receipt look */
.rs-step.is-done .rs-step__dot{background:var(--ok);border-color:var(--ok);color:#fff}
.rs-step.is-done:not(:last-child) .rs-step__rail::after{background:var(--ok)}
.rs-step.is-done .rs-step__head b{color:var(--mut);font-weight:700}
/* active → expanded panel with the kind accent + its controls */
.rs-step.is-active .rs-step__dot{border-color:var(--k);color:var(--k-ink);box-shadow:0 0 0 4px var(--k-tint)}
.rs-step.is-active .rs-step__dot::after{content:"";width:8px;height:8px;border-radius:50%;background:var(--k)}
.rs-step__panel{margin-top:var(--s3);border:1px solid var(--line);border-left:3px solid var(--k);border-radius:var(--r);background:var(--bg);box-shadow:var(--sh-1);padding:var(--s4) var(--s5)}
.rs-step__panel .rs-step__panel-t{font-size:13px;color:var(--mut);margin:0 0 var(--s3)}
/* future → inert */
.rs-step.is-future{opacity:.6}
.rs-step.is-future .rs-step__head b{color:var(--faint);font-weight:600}
/* verdict rows inside quality-check */
.verdicts{display:flex;flex-direction:column;gap:6px;margin:0 0 var(--s4)}
.verdict{display:flex;align-items:flex-start;gap:9px;font-size:13.5px}
.verdict__mark{width:18px;height:18px;border-radius:50%;display:grid;place-items:center;flex:none;margin-top:1px}
.verdict--ok .verdict__mark{background:var(--ok-tint);color:var(--ok)}
.verdict--bad .verdict__mark{background:var(--bad-tint);color:var(--bad)}
.verdict--ok{color:var(--ink)}
.verdict--bad b{color:var(--bad)}
.verdict__mark svg{width:11px;height:11px}

/* ---- 25. CARE FEED (post-publish home) + ALL-CLEAR ("kaikki kunnossa") --- */
.allclear{display:flex;align-items:center;gap:var(--s4);padding:var(--s5);border-radius:var(--r-lg);border:1px solid var(--k-golive);background:linear-gradient(180deg,var(--k-golive-tint),var(--bg));box-shadow:var(--sh-1)}
.allclear__ico{width:46px;height:46px;border-radius:50%;background:var(--k-golive);color:#fff;display:grid;place-items:center;flex:none;box-shadow:0 0 0 6px color-mix(in srgb,var(--k-golive) 16%,transparent)}
.allclear__ico svg{width:24px;height:24px}
.allclear__t{font-family:var(--font-display);font-size:19px;font-weight:800;letter-spacing:-.01em;color:var(--ink)}
.allclear__d{font-size:14px;color:var(--mut);margin-top:2px}
html[data-theme="operator"] .allclear__ico{color:var(--k-golive-on)}

.care-feed{display:flex;flex-direction:column;gap:var(--s3)}
.care-day{font-size:11px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--faint);margin:var(--s3) 0 2px}
.care-card{display:flex;gap:var(--s3);padding:var(--s4);border:1px solid var(--line);border-radius:var(--r);background:var(--bg)}
.care-card__ico{width:34px;height:34px;border-radius:var(--r-sm);display:grid;place-items:center;flex:none}
.care-card__ico svg{width:18px;height:18px}
.care-card__body{flex:1;min-width:0}
.care-card__t{font-weight:700;font-size:14.5px;color:var(--ink)}
.care-card__d{font-size:13.5px;color:var(--mut);margin:4px 0 0;line-height:1.5}
.care-card__act{display:flex;gap:var(--s2);flex-wrap:wrap;margin-top:var(--s3)}
.care-card__time{flex:none;font-size:12px;color:var(--faint);font-family:var(--mono);white-space:nowrap}
/* approval item — needs the customer; carries a kind accent */
.care-card--approve{border-left:3px solid var(--k);background:linear-gradient(90deg,color-mix(in srgb,var(--k-tint) 55%,var(--bg)),var(--bg) 46%)}
.care-card--approve .care-card__ico{background:var(--k-tint);color:var(--k-ink)}
/* receipt item — automatic work already done; quiet, no accent */
.care-card--receipt{background:var(--bg2)}
.care-card--receipt .care-card__ico{background:var(--ok-tint);color:var(--ok)}
.care-card--receipt .care-card__t{font-weight:600;color:var(--mut)}

/* ---- 26. PRE-FLIGHT GATE (replaces the dead-end lock; ALWAYS resolvable) - */
/* Two uses: blocked_by (entitlement/credits/sign-off) and go-live pre-flight. */
.preflight{border:1px solid var(--k);border-radius:var(--r-lg);background:var(--k-tint);padding:var(--s5);box-shadow:var(--sh-1)}
.preflight__head{display:flex;align-items:center;gap:10px;font-family:var(--font-display);font-weight:800;font-size:16px;color:var(--ink)}
.preflight__head svg{width:20px;height:20px;color:var(--k-ink);flex:none}
.preflight__why{font-size:14px;color:var(--mut);margin:var(--s2) 0 0;line-height:1.5}
.preflight__list{list-style:none;margin:var(--s3) 0 0;padding:0;display:flex;flex-direction:column;gap:9px}
.preflight__list li{display:flex;gap:10px;font-size:14px;color:var(--ink);line-height:1.45}
.preflight__list li svg{width:17px;height:17px;color:var(--k-ink);flex:none;margin-top:2px}
.preflight__list li b{font-weight:700}
.preflight__foot{margin-top:var(--s4);display:flex;gap:var(--s3);flex-wrap:wrap;align-items:center}
.preflight__foot .btn{flex:1 1 auto;min-width:min(260px,100%)}
.preflight--onbg{background:var(--bg);border-color:var(--line);border-top:3px solid var(--k)}

/* ---- 27. TALKING-POINT CARD (sales — seller language, not engineering) --- */
.talking-point{display:flex;gap:var(--s3);padding:var(--s4);border:1px solid var(--line);border-radius:var(--r);background:var(--bg);border-left:3px solid var(--mut)}
.talking-point__ico{width:30px;height:30px;border-radius:var(--r-sm);display:grid;place-items:center;flex:none;background:var(--bg3);color:var(--mut)}
.talking-point__ico svg{width:17px;height:17px}
.talking-point__t{font-weight:800;font-size:14.5px;color:var(--ink);line-height:1.25}
.talking-point__d{font-size:13.5px;color:var(--mut);margin:3px 0 0;line-height:1.5}
.talking-point--bad{border-left-color:var(--bad)}
.talking-point--bad .talking-point__ico{background:var(--bad-tint);color:var(--bad)}
.talking-point--warn{border-left-color:var(--acc)}
.talking-point--warn .talking-point__ico{background:var(--acc-tint);color:var(--acc-d)}
.talking-point--ok{border-left-color:var(--ok)}
.talking-point--ok .talking-point__ico{background:var(--ok-tint);color:var(--ok)}

/* ---- 28. HONEST PROGRESS (weighted %, stage bullets, sub-steps) ---------- */
.progress-honest__top{display:flex;align-items:center;gap:var(--s4);flex-wrap:wrap}
.progress-honest__pct{font-family:var(--font-display);font-size:30px;font-weight:800;letter-spacing:-.02em;color:var(--k-ink,var(--pri));line-height:1;flex:none;white-space:nowrap}
.progress-honest__bar{flex:1;min-width:160px;height:8px;border-radius:var(--r-pill);background:var(--bg3);overflow:hidden}
.progress-honest__bar > i{display:block;height:100%;border-radius:inherit;background:var(--k,var(--pri));transition:width .8s cubic-bezier(.22,.8,.3,1)}
.progress-honest__eta{flex:none;font-size:12.5px;color:var(--faint);font-family:var(--mono)}
.progress-honest .stages{margin-top:var(--s5)}
/* sub-steps nested under a stage */
.stage__sub{list-style:none;margin:8px 0 0;padding:0;display:flex;flex-direction:column;gap:5px}
.stage__sub li{display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--mut)}
.stage__sub .sub-mark{width:13px;height:13px;flex:none;color:var(--ok)}
.stage__sub li.is-pending{color:var(--faint)}
.stage__sub li.is-pending .sub-mark{color:var(--faint)}

/* ---- 18. REDUCED MOTION -------------------------------------------------- */
@media(prefers-reduced-motion:reduce){
  .wiz-step{animation:none}
  .meter > i,.wiz-bar i,.progress-honest__bar > i{transition:none}
  .card--link,.wiz-option,.btn,.queue-row{transition:none}
  .celebrate,.celebrate *{animation:none!important}
}

/* ---- 29. CELEBRATION (first publish only — brief, tasteful) -------------- */
.celebrate{position:relative;text-align:center;padding:var(--s7) var(--s5)}
.celebrate__mark{width:76px;height:76px;border-radius:50%;background:var(--k-golive);color:#fff;display:grid;place-items:center;margin:0 auto var(--s4);box-shadow:0 0 0 0 color-mix(in srgb,var(--k-golive) 40%,transparent);animation:celebRing 1.4s ease-out 1}
.celebrate__mark svg{width:38px;height:38px;animation:celebPop .5s cubic-bezier(.2,1.4,.4,1) 1 both}
@keyframes celebRing{0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--k-golive) 45%,transparent)}100%{box-shadow:0 0 0 34px color-mix(in srgb,var(--k-golive) 0%,transparent)}}
@keyframes celebPop{0%{transform:scale(.3);opacity:0}100%{transform:scale(1);opacity:1}}
.celebrate__t{font-family:var(--font-display);font-size:clamp(24px,3.4vw,32px);font-weight:800;letter-spacing:-.02em}
.celebrate__d{color:var(--mut);margin:var(--s2) auto 0;max-width:44ch}

/* ---- 30. JOURNEY PAGE SHELL (customer surface) + DRAWER (Lisäasetukset) --- */
.jp{min-height:100vh;background:var(--bg2);display:flex;flex-direction:column}
.jp-top{display:flex;align-items:center;gap:var(--s3);padding:11px clamp(16px,4vw,28px);background:var(--bg);border-bottom:1px solid var(--line);position:sticky;top:0;z-index:var(--z-sticky)}
.jp-top__right{margin-left:auto;display:flex;align-items:center;gap:var(--s2)}
.jp-switch{display:inline-flex;align-items:center;gap:9px;padding:6px 10px 6px 12px;border:1px solid var(--line);border-radius:var(--r-pill);font-weight:700;font-size:13px;background:var(--bg);color:var(--ink);cursor:pointer;max-width:230px}
.jp-switch:hover{background:var(--bg3)}
.jp-switch b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.jp-switch svg{width:15px;height:15px;color:var(--faint);flex:none}
.jp-stepper{background:var(--bg);border-bottom:1px solid var(--line);padding:var(--s4) clamp(16px,4vw,28px) var(--s3)}
.jp-stepper .journey{margin:0 auto;max-width:var(--content-max)}
.jp-main{flex:1;width:100%;max-width:860px;margin:0 auto;padding:var(--s6) clamp(16px,4vw,28px) var(--s8)}
.jp-past{display:flex;flex-direction:column;gap:var(--s2);margin-bottom:var(--s5)}
.jp-stagehead{margin:0 0 var(--s5)}
.jp-stagehead h1{font-family:var(--font-display);font-size:clamp(23px,3vw,31px);font-weight:800;letter-spacing:-.022em;margin:0;line-height:1.1}
.jp-stagehead p{color:var(--mut);font-size:15px;margin:8px 0 0;max-width:60ch;line-height:1.5}

/* drawer — a right-hand slide-in for advanced options; invisible on the path */
.drawer{position:fixed;inset:0;z-index:var(--z-modal);display:none}
.drawer.is-open{display:block}
.drawer__scrim{position:absolute;inset:0;background:rgba(10,12,24,.42)}
.drawer__panel{position:absolute;top:0;right:0;height:100%;width:min(440px,94vw);background:var(--bg);box-shadow:var(--sh-3);display:flex;flex-direction:column;animation:drawerIn .22s ease}
@keyframes drawerIn{from{transform:translateX(24px);opacity:.4}to{transform:none;opacity:1}}
.drawer__head{display:flex;align-items:center;gap:var(--s3);padding:var(--s4) var(--s5);border-bottom:1px solid var(--line)}
.drawer__head h3{font-family:var(--font-display);font-size:17px;font-weight:800}
.drawer__close{margin-left:auto;width:36px;height:36px;border-radius:var(--r-sm);border:1px solid var(--line);background:var(--bg);cursor:pointer;color:var(--ink);display:grid;place-items:center}
.drawer__close:hover{background:var(--bg3)}
.drawer__body{padding:var(--s5);overflow-y:auto;display:flex;flex-direction:column;gap:var(--s6)}
.drawer-sect__t{font-size:11px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--faint);margin:0 0 var(--s3)}
.drawer-row{display:flex;align-items:center;gap:var(--s3);padding:var(--s3) 0;border-top:1px solid var(--line-2)}
.drawer-row:first-of-type{border-top:0}
.drawer-row__txt{flex:1;min-width:0}
.drawer-row__txt b{font-size:14px;font-weight:700;display:block}
.drawer-row__txt span{font-size:12.5px;color:var(--mut)}
/* visible-lite credits quota line */
.quota{display:flex;align-items:center;gap:10px;font-size:13px;color:var(--mut);background:var(--bg2);border:1px solid var(--line);border-radius:var(--r-sm);padding:10px 12px}
.quota b{color:var(--ink);font-weight:700;font-family:var(--font-display)}
.quota__bar{flex:1;height:6px;border-radius:var(--r-pill);background:var(--bg3);overflow:hidden;min-width:60px}
.quota__bar > i{display:block;height:100%;background:var(--pri);border-radius:inherit}

@media(prefers-reduced-motion:reduce){.drawer__panel{animation:none}}

/* ============================ repo compat tail ============================ */

/* repo additions kept from the v2 file (used by wizard chain progress) */
.stage__subs{display:flex;flex-direction:column;gap:2px;margin-top:4px}
.wiz-runbar{height:8px;border-radius:var(--r-pill);background:var(--bg3);overflow:hidden;margin-top:var(--s3)}
.wiz-runbar i{display:block;height:100%;border-radius:inherit;background:linear-gradient(90deg,var(--pri),var(--acc));transition:width .9s cubic-bezier(.22,.8,.3,1)}
@media(prefers-reduced-motion:reduce){.wiz-runbar i{transition:none}}
/* .split / .mode-toggle: copied verbatim from the v1 sheet (HEAD).          */
.split{display:grid;grid-template-columns:1.05fr .95fr;gap:48px;align-items:center}
.split>*{min-width:0}
@media(max-width:860px){.split{grid-template-columns:1fr;gap:var(--s5)}}
.mode-toggle{background:none;border:1px solid var(--line);border-radius:999px;padding:5px 12px;font:inherit;font-size:12.5px;color:var(--mut);cursor:pointer}
.mode-toggle:hover{color:var(--ink);border-color:var(--pri)}
/* The four below are used by templates but had NO definition in v1 either   */
/* (pre-existing no-ops) — given minimal token-driven definitions here.      */
.pill--sm{font-size:11px;padding:2px 8px}
.card--flat{background:var(--bg2);border:1px solid var(--line-2);border-radius:var(--r);padding:var(--s3) var(--s4);box-shadow:none}
.panel--tint{background:var(--bg2)}
.mt0{margin-top:0!important}

/* ---- 20. PAGE-LOCAL (DS v2 reference one-offs) --------------------------- */
/* Ported from the <style> block of ui_kits/marketing/index.html: savo-hill   */
/* hero motif + self-playing demo transitions (tokens only). Used by home.html*/
.hero{position:relative;overflow:hidden}
.hero__hill{position:absolute;right:-220px;bottom:-280px;width:640px;height:640px;pointer-events:none}
.hero__grid{position:relative;display:grid;grid-template-columns:1.05fr .95fr;gap:48px;align-items:center}
@media(max-width:860px){.hero__grid{grid-template-columns:1fr}.hero__hill{display:none}}
.demo-fade{opacity:0;transform:translateY(6px);transition:opacity .45s ease,transform .45s ease}
.demo-fade.on{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){.demo-fade{transition:none;transform:none}}
.dark-hill{position:absolute;left:-120px;bottom:-200px;width:520px;height:520px;pointer-events:none;opacity:.5}

/* ---- 20b. APP-LOCAL: direction thumbnails (CD-024 V3a) ---- */
.dir-thumb{width:100%;aspect-ratio:16/10;object-fit:cover;object-position:top;border-radius:10px;border:1px solid var(--line);margin-bottom:8px;background:var(--bg2)}
.wiz-option--thumbed{padding:12px 12px 16px;position:relative}
.dir-thumb-tag{position:absolute;top:20px;left:20px;background:var(--ink);color:var(--bg);font-size:11px;font-weight:700;letter-spacing:.04em;padding:3px 8px;border-radius:999px}

/* ---- 21. APP-LOCAL: htmx pending feedback (D-035 — no dead clicks) ---- */
form.htmx-request .wiz-option,form.htmx-request .wiz-cta{opacity:.55;pointer-events:none}
form.htmx-request .wiz-option::after{content:"";width:14px;height:14px;border-radius:50%;border:2px solid var(--pri);border-top-color:transparent;animation:spin .7s linear infinite;justify-self:end;margin-top:-18px}
.prose-report h2,.prose-report h3{margin-top:var(--s5)}
.prose-report p,.prose-report li{font-size:14px;line-height:1.6}
.prose-report table{margin:var(--s3) 0}

/* sales-callflow screen locals (ui_kits/sales-callflow, D-074) */
.call-verdict{flex:none}
.outcomes{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--s2)}
.order-steps{display:flex;gap:8px;margin-bottom:24px}
.order-steps i{flex:1;height:5px;border-radius:var(--r-pill);background:var(--line)}
.order-steps i.on{background:var(--k-golive)}
.sumline{display:flex;justify-content:space-between;padding:11px 0;border-top:1px solid var(--line-2);font-size:14px}
.sumline:first-child{border-top:0}
.sumline b{font-family:var(--font-display)}

/* entry-editor module (D-076): list-of-records add/edit/delete before one save */
.ee__rows{display:flex;flex-direction:column;gap:var(--s3)}
.ee__row{display:flex;gap:var(--s3);align-items:flex-start;padding:var(--s4);border:1px solid var(--line);border-radius:var(--r);background:var(--bg2)}
.ee__fields{flex:1;min-width:0}
.ee__del{flex:none;margin-top:2px}


/* ---- onboarding review rows (CD-093 chunk 8c, D-1052 §2.1/§2.6) ----------
   ⛔ BEFORE SECTION 30 DELIBERATELY. Appending at end-of-file is the natural habit and
   it lands inside the public-marketing overlay, where `test_site_scope_isolation`
   requires every selector to be `.site`-scoped. These are app components, not marketing
   ones, so the fix is WHERE THEY LIVE — never unscoping a rule to satisfy the gate.
   ⚠ The stylesheet rendered identically either way; only the gate noticed. */
/* One block per question, its Muuta anchored to the block's HEAD. The previous
   markup put the control after the answer inside a wrapping flex line, so a long
   answer pushed it down until it rendered directly above the NEXT question. */
.ob-rev{list-style:none;margin:0 0 var(--s5);padding:0}
.ob-rev__row{padding:var(--s3) 0;border-top:1px solid var(--line)}
.ob-rev__row:last-child{border-bottom:1px solid var(--line)}
.ob-rev__head{display:flex;gap:var(--s3);align-items:baseline;justify-content:space-between}
.ob-rev__q{color:var(--mut);font-size:14px;line-height:1.4}
.ob-rev__edit{flex:none;min-height:32px;align-self:center}
/* white-space:pre-wrap — the review's job is "is this what you meant?", and it can
   only answer it by showing what is STORED. overflow-wrap so a pasted URL cannot
   push a phone's layout sideways.
   max-height — measured on the real answer: pasted from a source that emits one
   fragment per line, it renders ~60 lines and pushes every other question AND the
   confirm button off a phone screen. The row scrolls; nothing is hidden and nothing
   is reflowed into something the record does not contain. */
.ob-rev__a{margin:var(--s1) 0 0;color:var(--ink);white-space:pre-wrap;overflow-wrap:anywhere;
           max-height:15em;overflow:auto}
.ob-rev__a--none{color:var(--faint)}
.ob-rev__note{color:var(--faint);font-style:italic;white-space:normal}
.ob-rev__row--derived .ob-rev__q{color:var(--faint)}

/* ---- the business-type picker's description (CD-093 chunk 8d, D-1053) ----
   It used to live INSIDE the option text; measured at up to 262 characters, which
   made a seventeen-option native picker unreadable on a phone. */
.ob-pick__desc{margin:var(--s2) 0 0;color:var(--mut);font-size:14px;line-height:1.5;
               min-height:1.5em}

/* ============================================================================
   30. PUBLIC MARKETING SURFACE — SavonAI brand v1.0  (spec: ui-redesign.md §v4)
   ----------------------------------------------------------------------------
   APPEND-ONLY SECTION. Nothing above this line is edited.

   Scope: `.site`, the class on <body class="site"> in public_base.html and
   nowhere else (app_base / auth_base / journey use a bare <body>, wizard uses
   .wiz-page). Every declaration below is nested under `.site`, which is what
   makes "the app is untouched" provable rather than hoped for.

   Mechanism: RE-MAP, don't rename. Components already read --ink, --bg, --pri,
   --acc, --ok…; this section gives those names brand values inside the scope.
   The app keeps :root untouched.

   Three rulings live in here and are commented where they bite:
     §30.4  state semantics without hue      (brief §3.1)
     §30.9  [data-band="dark"] becomes a RULE, not a fill   (brief §3.2)
     §30.3  the Savo hill is deleted on this surface        (brief §3.3)
   ========================================================================== */


/* ---- 30.0 Archivo — self-hosted, no third-party font request -------------
   Vendor exactly as Sora is vendored: app/static/fonts/Archivo-Variable.ttf
   + Archivo-OFL.txt + UPSTREAM. Add the preload to public_base.html beside
   the Sora one. There is deliberately no Google Fonts <link>: this product
   publishes a DPIA, and a font fetch to a US CDN on the marketing pages
   contradicts it.                                                          */
@font-face{
  font-family:"Archivo";
  src:url("fonts/Archivo-Variable.ttf") format("truetype-variations");
  font-weight:100 900;
  font-style:normal;
  font-display:swap;
}


/* ---- 30.1 TOKEN RE-MAP ---------------------------------------------------
   Maximum black–white contrast. #0071e3 appears exactly once per page — as
   the full stop in the wordmark (§30.11). It is not a button, link, border,
   focus or state colour anywhere on this surface.                          */
.site{
  /* brand values, named for reference in the overrides below */
  --b-bg:#000000;
  --b-surface-dark:#101014;
  --b-surface-light:#ffffff;
  --b-ink:#111111;
  --b-ink-2:#48484d;
  --b-accent:#0071e3;          /* the full stop. Nothing else. */
  --b-border:rgba(244,246,250,.20);
  --b-border-strong:rgba(244,246,250,.45);
  --b-ghost:rgba(244,246,250,.12);
  --b-ghost-hi:rgba(244,246,250,.22);
  --b-hover-light:#d6d6db;
  --b-hover-dark:#48484d;

  /* heritage names, re-pointed */
  --ink:#ffffff;
  --ink-2:#e4e4e9;
  --mut:#e4e4e9;               /* body copy on black — AA at 15px+ */
  --faint:#b4b4ba;             /* captions, kickers, footer */
  --line:var(--b-border);
  --line-2:var(--b-ghost);
  --bg:#000000;                /* card surface == page ground; cards are borders */
  --bg2:#000000;
  --bg3:var(--b-ghost);

  --pri:#ffffff;  --pri-d:var(--b-hover-light);
  --pri-tint:var(--b-ghost);  --pri-ring:rgba(255,255,255,.55);
  --acc:#ffffff;  --acc-d:var(--b-hover-light);
  --acc-tint:var(--b-ghost);  --acc-ink:#111111;

  /* semantic families collapse onto the value ramp — see §30.4 */
  --ok:#c8c8ce;   --ok-tint:transparent;   --ok-line:var(--b-border);
  --warn:#ffffff; --warn-tint:transparent; --warn-line:var(--b-border);
  --bad:#ffffff;  --bad-tint:transparent;  --bad-line:var(--b-border-strong);
  --on-pri:#111111;
  --on-acc:#111111;

  /* type */
  --font:"Archivo",-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;
  --font-display:"Archivo",-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;

  /* shape — cards 28–32, everything interactive is a pill */
  --r-xs:12px; --r-sm:999px; --r:20px; --r-lg:28px; --r-xl:32px; --r-pill:999px;

  /* the brand forbids shadows */
  --sh-1:none; --sh-2:none; --sh-3:none;

  /* focus: white, double-ringed so it survives on black AND on the white
     surfaces (pricing feature card, alert--info, the legal pages) */
  --ring:0 0 0 2px #000000, 0 0 0 4px #ffffff;

  --content-max:1200px;

  background:var(--b-bg);
  color:var(--ink);
  font:400 17px/1.55 var(--font);
  letter-spacing:-.005em;
  -webkit-font-smoothing:antialiased;
}
.site ::selection{background:#ffffff;color:#111111}


/* ---- 30.2 TYPE SCALE ----------------------------------------------------- */
.site h1,.site h2,.site h3,.site h4{color:var(--ink);font-family:var(--font-display)}

/* Display. The brief specifies clamp(72px,12vw,170px); 72px is unreadable as
   a floor at 360px (the first line of "Löydy Googlessa ja tekoälyhauissa."
   breaks mid-word), so the floor is 44px and the vw term carries it up. Same
   ceiling, same character. */
.site .t-display{
  font-size:clamp(44px,11.5vw,170px);
  font-weight:900;letter-spacing:-.045em;line-height:.95;
  text-wrap:balance;
}
.site .t-h1{font-size:clamp(32px,4.4vw,64px);font-weight:900;letter-spacing:-.038em;line-height:1.02;text-wrap:balance}
.site .t-h2,.site h2{font-size:clamp(26px,2.6vw,34px);font-weight:900;letter-spacing:-.032em;line-height:1.08}
.site h1{font-size:clamp(32px,4.4vw,64px);font-weight:900;letter-spacing:-.038em;line-height:1.02}
.site .t-h3,.site h3{font-size:20px;font-weight:700;letter-spacing:-.02em;line-height:1.25}
.site .t-h4{font-size:17px;font-weight:700;letter-spacing:-.015em}
.site .t-lead,.site .lead{font-size:clamp(18px,1.7vw,24px);line-height:1.45;font-weight:400;color:var(--ink-2);letter-spacing:-.012em}
.site .t-body{font-size:17px;color:var(--ink)}
.site .t-sm{font-size:15px;line-height:1.5}
.site .t-xs{font-size:13px;line-height:1.45}
.site .mut{color:var(--mut)}
.site .faint{color:var(--faint)}
.site p{text-wrap:pretty}
.site .mono,.site .stage__time{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;letter-spacing:0}

/* kicker — an eyebrow, not a chip. No fill, no border, no colour. */
.site .kicker{
  display:block;background:none!important;border:0;padding:0;border-radius:0;
  font-size:13px;font-weight:700;letter-spacing:.3em;text-transform:uppercase;
  color:var(--faint)!important;
}

/* links: no accent hue — underline carries them */
.site a{color:var(--ink);text-decoration:none}
.site a:not(.btn):not(.brand):not(.card):not(.lang-link):not(.pill):hover{text-decoration:underline;text-underline-offset:.22em;text-decoration-thickness:1px}
.site .mut a,.site a.mut{color:var(--faint)}
.site :focus-visible{outline:none;box-shadow:var(--ring);border-radius:inherit}


/* ---- 30.3 LAYOUT + THE SAVO HILL ----------------------------------------
   RULING (brief §3.3): the hill is REMOVED from the public surface. The new
   system forbids SVG illustration and has no amber to draw it in; the hero
   carries itself on type. The two inline <svg> blocks in home.html can be
   deleted by the developer — until they are, this hides them, so nothing
   references the dead --acc-tint.  The hill and the amber SURVIVE INSIDE THE
   APP (wizard.html:23 keeps its copy) — this is a per-surface removal.     */
.site .hero__hill,.site .dark-hill{display:none!important}

.site .section{padding:clamp(72px,9vw,140px) 0}
/* pricing.html / legal.html / webpresence.html carry inline `padding:… 0 …` on
   their sections, which zeroes the horizontal gutter and pins copy to the
   viewport edge on a phone. Longhand + !important is the only way to fix that
   from an overlay without editing markup; the inline VERTICAL padding is left
   intact. See structural ask S-4 for removing the inline styles properly. */
.site .wrap{padding-left:clamp(20px,4vw,48px)!important;padding-right:clamp(20px,4vw,48px)!important}
.site .wrap{max-width:var(--content-max)}
.site .wrap--narrow{max-width:820px}
.site .grid{gap:12px}
/* `.grid--3` is in the template class contract but has NO definition anywhere in
   savonai.css, so /webpresence's three pilot cards render as one column today.
   Giving it the obvious definition is part of "every class must still resolve to
   something sensible". */
.site .grid--3{grid-template-columns:repeat(3,1fr)}
.site .row{gap:10px}

/* section--tint: there is no tint on black. It becomes the one other surface
   the brand allows — #101014 — bounded by hairlines. Max two surfaces/view. */
.site .section--tint{
  background:var(--b-surface-dark);
  border-top:1px solid var(--b-border);
  border-bottom:1px solid var(--b-border);
}

/* HERO: full-bleed type screen, then the score card on its own screen below,
   separated by a hairline. CSS only — .hero__grid keeps its markup and its
   source order; it simply stops being two columns. */
.site .hero{padding-top:clamp(56px,9vw,120px)!important;padding-bottom:0!important}
.site .hero__grid{
  display:grid;grid-template-columns:1fr;gap:0;align-items:start;
}
.site .hero__grid > div:first-child{
  min-height:min(74vh,760px);display:flex;flex-direction:column;justify-content:center;
  padding-bottom:clamp(48px,7vw,96px);
}
.site .hero__grid > div:first-child > .t-display{max-width:none!important;margin-top:clamp(20px,3vw,40px)}
.site .hero__grid > div:first-child > .t-lead{max-width:34ch!important;margin-top:clamp(20px,2.6vw,36px)}
.site .hero__grid > .card{
  border-top:1px solid var(--b-border);border-left:0;border-right:0;border-bottom:0;
  border-radius:0;padding:clamp(40px,6vw,80px) 0 clamp(56px,7vw,96px);
  max-width:640px;
}


/* ---- 30.4 STATE WITHOUT HUE  ⚠ THE RULING (brief §3.1) ------------------
   Two mechanisms, always both, never colour alone:

   (a) A VALUE RAMP. Brightness = how much this wants you. White = act on
       this. #c8c8ce = noted. #b4b4ba = quiet. A 1px border = at rest.
   (b) FILL vs OUTLINE, plus weight. Filled = attention. Outlined = at rest.
       Severity also changes SHAPE and SIZE, so the ramp is never the only cue.

   Contrast on #000: #ffffff 21:1 · #e4e4e9 15.9:1 · #c8c8ce 11.9:1 ·
   #b4b4ba 9.3:1. Every state token is AA at 13px and above.

   ⚠ ASYMMETRY, accepted deliberately: .meter--warn is white here and amber
   inside the app. Both are correct in their own scope. Written down because a
   future contributor will find it surprising.                              */

/* meter: attention = solid white fill; at-rest = a quiet grey. The value is
   always printed next to it (58/100), so the bar never carries meaning alone. */
.site .meter{height:4px;background:var(--b-ghost);border-radius:999px;margin-top:14px}
.site .meter > i{background:#ffffff}
.site .meter--warn > i{background:#ffffff}                       /* act on this */
.site .meter--ok > i{background:#c8c8ce}                          /* noted */
.site .meter--bad > i{background:#ffffff}
.site .meter--ok{background:rgba(244,246,250,.08)}

/* issue severity: high = filled white SQUARE, med = filled grey CIRCLE,
   low = hollow CIRCLE. Shape + fill + value, three cues. */
.site .issue{border-top:1px solid var(--b-ghost);padding:18px 0}
.site .issue__sev{width:10px;height:10px;border-radius:0;background:#ffffff;margin-top:8px}
.site .issue__sev--high{width:11px;height:11px;border-radius:0;background:#ffffff}
.site .issue__sev--med{width:10px;height:10px;border-radius:50%;background:#c8c8ce}
.site .issue__sev--low{width:10px;height:10px;border-radius:50%;background:transparent;box-shadow:inset 0 0 0 1.5px var(--b-border-strong)}
.site .issue__t{font-size:17px;font-weight:600;letter-spacing:-.015em}
.site .issue__d,.site .issue__why{color:var(--mut);font-size:15px}
.site .issue__more{font-size:14px;font-weight:600;color:var(--faint);text-decoration:underline;text-underline-offset:.22em;margin-top:8px}
.site .issue__more:hover{color:#ffffff}

/* pill: at rest = outline. .pill--ok keeps the dot, hollowed.
   Borders that carry state use border-on-dark at .45 (4.2:1), not .2 (1.6:1):
   a boundary a user has to READ is a UI component and owes 3:1. Purely
   decorative card edges stay at .2. */
.site .pill{
  background:none;border:1px solid var(--b-border-strong);color:var(--faint);
  font-size:13px;font-weight:600;letter-spacing:.02em;padding:7px 14px;border-radius:999px;
}
.site .pill--ok{background:none;border-color:var(--b-border-strong);color:#c8c8ce}
.site .pill--ok .dot{background:none;box-shadow:inset 0 0 0 1.5px currentColor;width:8px;height:8px}
.site .pill--pri,.site .pill--amber{background:#ffffff;border-color:#ffffff;color:#111111}
.site .pill--warn,.site .pill--bad{background:none;border-color:#ffffff;color:#ffffff}

/* badge: --ai is an outline (a fact, not a claim); --premium is filled
   (it marks the recommended plan — that IS attention). */
.site .badge{font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;padding:5px 11px;border-radius:999px}
.site .badge--ai{background:none;border:1px solid var(--b-border-strong);color:var(--faint)}
.site .badge--premium{background:#ffffff;border:1px solid #ffffff;color:#111111}
.site .badge--verified,.site .badge--tier{background:none;border:1px solid var(--b-border);color:var(--faint)}

/* stages: done = filled, active = ring + pulse, pending = hairline + muted */
.site .stages li{padding-bottom:22px}
.site .stage__bullet{width:20px;height:20px;border:1px solid var(--b-border-strong);background:transparent}
.site .stages li:not(:last-child) .stage__rail::after{background:var(--b-border);width:1px}
.site .stage--done .stage__bullet{background:#ffffff;border-color:#ffffff;color:#111111}
.site .stage--done .stage__bullet svg{stroke:#111111}
.site .stage--done .stage__rail::after{background:var(--b-border-strong)}
.site .stage--active .stage__bullet{border-color:#ffffff;box-shadow:0 0 0 4px rgba(244,246,250,.14)}
.site .stage--active .stage__bullet::after{background:#ffffff;width:8px;height:8px}
.site .stage--pending .stage__bullet{border-style:dashed}
.site .stage--pending .stage__t{color:var(--faint)}
.site .stage__t{font-size:16px;font-weight:600;letter-spacing:-.01em}
.site .stage__time{font-size:13px;color:var(--faint)}

/* alert: --ok is an outline note. --info carries the signup CTA, so it is the
   one component that inverts to the light surface and shouts. */
.site .alert{border-radius:var(--r);padding:24px 28px;font-size:16px;line-height:1.5;gap:14px;border:1px solid var(--b-border-strong);background:none;color:var(--ink)}
.site .alert__title{font-weight:700}
.site .alert--ok{background:none;border-color:var(--b-border-strong);color:var(--ink)}
.site .alert--warn,.site .alert--bad{background:none;border-color:#ffffff;color:#ffffff}
.site .alert--info{background:var(--b-surface-light);border-color:var(--b-surface-light);color:var(--b-ink)}
.site .alert--info .t-sm{color:var(--b-ink);font-size:17px;font-weight:500}
.site .alert--info .btn,.site .alert--info .btn--amber{background:var(--b-ink);color:#ffffff;border-color:var(--b-ink)}
.site .alert--info .btn:hover,.site .alert--info .btn--amber:hover{background:var(--b-hover-dark);color:#ffffff}


/* ---- 30.5 BUTTONS ------------------------------------------------------- */
.site .btn{
  border-radius:999px;min-height:48px;padding:0 26px;
  font-family:var(--font);font-size:16px;font-weight:600;letter-spacing:-.01em;
  background:#ffffff;color:var(--b-ink);border:1px solid #ffffff;
  transition:background .14s ease,color .14s ease,border-color .14s ease;
  white-space:normal;text-align:center;
}
.site .btn:hover{background:var(--b-hover-light);color:var(--b-ink);border-color:var(--b-hover-light)}
.site .btn:active{transform:translateY(1px)}
/* .btn--amber keeps its NAME and loses its colour. It is the primary CTA
   class across the marketing templates; renaming it means touching markup. */
.site .btn--amber{background:#ffffff;color:var(--b-ink);border-color:#ffffff;font-weight:700}
.site .btn--amber:hover{background:var(--b-hover-light);color:var(--b-ink)}
.site .btn--ghost{background:var(--b-ghost);color:#ffffff;border-color:transparent}
.site .btn--ghost:hover{background:var(--b-ghost-hi);color:#ffffff;border-color:transparent}
.site .btn--sec{background:none;color:#ffffff;border-color:var(--b-border-strong)}
.site .btn--sec:hover{background:var(--b-ghost);color:#ffffff;border-color:#ffffff}
.site .btn--quiet,.site .btn--link{background:none;border-color:transparent;color:var(--faint)}
.site .btn--quiet:hover,.site .btn--link:hover{background:none;color:#ffffff;text-decoration:underline}
.site .btn--lg{min-height:60px;padding:0 34px;font-size:18px;border-radius:999px}
.site .btn--sm{min-height:40px;padding:0 18px;font-size:14px}
.site .btn--block{width:100%}
.site .btn[disabled],.site .btn[aria-disabled="true"]{opacity:1;background:none;color:var(--faint);border-color:var(--b-border);cursor:not-allowed}
.site .btn.is-loading::after{color:var(--b-ink);border-color:currentColor;border-top-color:transparent}
.site .btn--ghost.is-loading::after,.site .btn--sec.is-loading::after{color:#ffffff}


/* ---- 30.6 CARDS + SURFACES ---------------------------------------------- */
.site .card{
  background:none;border:1px solid var(--b-border);border-radius:var(--r-lg);box-shadow:none;
}
.site .card--pad{padding:clamp(28px,3.4vw,44px)}
.site .card--link:hover,.site a.card:hover{border-color:#ffffff;transform:none;box-shadow:none;text-decoration:none}
.site .card > h3,.site .card > b{letter-spacing:-.02em}

/* The featured pricing card inverts to the light surface. Selected via :has()
   on the badge that already marks it — no markup change, no new class. */
.site .card:has(> .row > .badge--premium),
.site .card:has(> .row--between > .badge--premium){
  background:var(--b-surface-light);border-color:var(--b-surface-light);color:var(--b-ink);
}
.site .card:has(.badge--premium) h3,
.site .card:has(.badge--premium) .price,
.site .card:has(.badge--premium) b{color:var(--b-ink)}
.site .card:has(.badge--premium) .price small,
.site .card:has(.badge--premium) .mut,
.site .card:has(.badge--premium) .t-xs,
.site .card:has(.badge--premium) p{color:var(--b-ink-2)}
.site .card:has(.badge--premium) .badge--premium{background:var(--b-ink);border-color:var(--b-ink);color:#ffffff}
.site .card:has(.badge--premium) .btn{background:var(--b-ink);border-color:var(--b-ink);color:#ffffff}
.site .card:has(.badge--premium) .btn:hover{background:var(--b-hover-dark);color:#ffffff}

/* price — the brand book's spec: 900, big, unit in the muted grey */
.site .price{font-family:var(--font-display);font-size:clamp(56px,6.2vw,84px);font-weight:900;letter-spacing:-.045em;line-height:.95;color:var(--ink)}
.site .price small{font-size:20px;font-weight:400;letter-spacing:-.01em;color:var(--faint)}
/* /hinnoittelu prices its plans with an inline `font-size:28px` on the <p>
   instead of .price. Same treatment, reached through the inline hook. */
.site .card [style*="font-size:28px"]{margin:18px 0 20px!important}
.site .card [style*="font-size:28px"] > b{font-family:var(--font-display);font-size:clamp(40px,4vw,56px);font-weight:900;letter-spacing:-.045em;line-height:1}
.site .card [style*="font-size:28px"] > small{font-size:18px;font-weight:400;color:var(--faint);margin-left:8px}
.site .card ul{margin:0 0 20px 1.1em;padding:0;font-size:15px;line-height:1.5}
.site .card ul li{margin:.4em 0}
.site .card ul li::marker{color:var(--faint)}

/* KPI / scorecard — the hero number */
.site .scorecard{gap:12px}
.site .kpi{background:var(--b-ghost);border:0;border-radius:var(--r);padding:24px}
.site .kpi__val{font-family:var(--font-display);font-size:44px;font-weight:900;letter-spacing:-.04em;color:var(--ink)}
.site .kpi__val small{font-size:18px;font-weight:400;color:var(--faint)}
.site .kpi__label{font-size:13px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--faint);margin-top:12px}
.site .kpi--feature{background:none;border:1px solid #ffffff;border-radius:var(--r)}
.site .kpi--feature .kpi__val{color:#ffffff;font-size:clamp(56px,7vw,92px);line-height:.9}


/* ---- 30.7 FORMS --------------------------------------------------------- */
.site .input,.site .select,.site .textarea{
  background:none;border:1px solid var(--b-border-strong);border-radius:999px;
  color:#ffffff;font:400 17px/1.4 var(--font);min-height:56px;padding:0 22px;
}
.site .textarea{border-radius:var(--r);padding:16px 22px}
.site .input::placeholder{color:var(--faint)}
.site .input:focus,.site .select:focus,.site .textarea:focus{border-color:#ffffff;box-shadow:var(--ring)}
.site .field-inline{gap:10px}
.site .field-prefix{border:1px solid var(--b-border-strong);border-radius:999px;background:none;min-height:56px}
.site .field-prefix:focus-within{border-color:#ffffff;box-shadow:var(--ring)}
.site .field-prefix .px{color:var(--faint);font-size:17px;padding:0 2px 0 22px}
.site .field-prefix .input{border:0;padding-left:2px;min-height:54px}
.site .field-label{color:var(--faint);font-size:13px;font-weight:700;letter-spacing:.14em;text-transform:uppercase}
.site .help{color:var(--faint);font-size:14px}

/* the "AI picks your colours" chips (home.html "how it works", card 2).
   The template hardcodes the RETIRED palette (#0b5cad #ffb020 #12152e #f5f7fc)
   as content. Until the markup stops doing that, the marketing scope renders
   them as a four-step value ramp: same idea — "a look gets chosen for you" —
   without shipping the old brand as an illustration. See structural ask S-2. */
.site .swatches{gap:8px;margin-top:14px}
.site .swatch{width:44px;height:28px;border-radius:8px;border:1px solid var(--b-border)}
.site .swatch:nth-child(1){background:#ffffff!important;border-color:#ffffff}
.site .swatch:nth-child(2){background:#c8c8ce!important;border-color:#c8c8ce}
.site .swatch:nth-child(3){background:#48484d!important;border-color:#48484d}
.site .swatch:nth-child(4){background:#000000!important;border-color:var(--b-border-strong)}


/* ---- 30.8 SHELL : nav, footer ------------------------------------------- */
.site .topnav{
  position:sticky;top:0;background:rgba(0,0,0,.72);backdrop-filter:saturate(1.2) blur(14px);
  border-bottom:0;
}
.site .topnav__in{height:96px;gap:24px;max-width:var(--content-max);padding:0 clamp(20px,4vw,48px)}
.site .brand{font-family:var(--font-display);font-size:26px;font-weight:900;letter-spacing:-.02em;color:#ffffff;gap:0}
.site .brand svg{display:none}                 /* the mark is the wordmark now */
/* the wordmark is "SavonAI." — one word, one blue full stop, no highlighted AI */
.site .brand .ai{color:#ffffff}
.site .brand .ai::after{content:".";color:var(--b-accent)}

/* the floating pill row — four destinations, the language toggle, the CTA */
.site .topnav__links{
  gap:8px;padding:7px 7px 7px 10px;border-radius:999px;
  background:rgba(244,246,250,.07);border:1px solid var(--b-border-strong);
}
.site .topnav__links a:not(.btn){
  color:var(--ink-2);font-size:15px;font-weight:500;letter-spacing:-.005em;white-space:nowrap;
  padding:11px 16px;border-radius:999px;min-height:44px;display:inline-flex;align-items:center;
}
.site .topnav__links a:not(.btn):hover{color:#ffffff;background:var(--b-ghost);text-decoration:none}
.site .topnav__links .btn{min-height:44px;padding:0 22px;font-size:15px}
.site .lang{border:0;background:none;font-size:13px;font-weight:700;letter-spacing:.08em;gap:2px}
.site .lang a,.site .lang span{padding:9px 11px;border-radius:999px;color:var(--faint);min-height:38px;display:inline-flex;align-items:center}
.site .lang .on{background:none;color:#ffffff;box-shadow:inset 0 0 0 1px var(--b-border)}
.site .lang a:hover{background:var(--b-ghost);color:#ffffff}

.site .site-foot{
  background:none;border-top:1px solid var(--b-border);
  color:var(--faint);font-size:15px;padding:clamp(48px,6vw,80px) 0 clamp(32px,4vw,48px);
}
.site .site-foot__in{max-width:var(--content-max);padding:0 clamp(20px,4vw,48px);gap:20px}
.site .site-foot b{font-family:var(--font-display);font-size:20px;font-weight:900;letter-spacing:-.02em;color:#ffffff}
/* The accent appears exactly ONCE per page, and it is the nav wordmark's stop.
   The footer lockup is the monochrome one: same full stop, white. The template's
   inline `color:var(--pri)` on the AI span already resolves to white in this
   scope, so the wordmark stays whole and unsplit. */
.site .site-foot b span{color:#ffffff!important}
.site .site-foot b::after{content:".";color:#ffffff}
.site .site-foot a{color:var(--faint)}
.site .site-foot a:hover{color:#ffffff}


/* ---- 30.9 THE INVERTED BAND  ⚠ RULING (brief §3.2) ---------------------
   `[data-band="dark"]` is a DARK band on a light page. This page is already
   black, so the name is now wrong — and it is kept anyway, because renaming
   it means editing markup in home.html and aivot.html.

   ⚠⚠ READ THIS BEFORE YOU "FIX" THE NAME: on the marketing surface
   [data-band="dark"] produces a BLACK section bounded by two 1px white rules.
   The interlude is made by the rules and the spacing, not by a fill. The
   ruled band was chosen over a white inversion so the page stays one
   unbroken black field top to bottom.

   The v3 section that re-declares the palette inside this attribute still
   applies at :root level; everything below re-points it inside .site.     */
.site [data-band="dark"]{
  --ink:#ffffff; --ink-2:#e4e4e9; --mut:#e4e4e9; --faint:#b4b4ba;
  --line:var(--b-border); --line-2:var(--b-ghost);
  --bg:#000000; --bg2:#000000; --bg3:var(--b-ghost);
  --pri:#ffffff; --pri-d:var(--b-hover-light); --pri-tint:var(--b-ghost); --pri-ring:rgba(255,255,255,.55);
  --acc:#ffffff; --acc-tint:var(--b-ghost);
  --ok:#c8c8ce; --ok-tint:transparent; --ok-line:var(--b-border);
  --sh-1:none; --sh-2:none; --sh-3:none;
  background:#000000;color:#ffffff;
  border-top:1px solid rgba(255,255,255,.9);
  border-bottom:1px solid rgba(255,255,255,.9);
}
/* aivot.html also uses data-band="tint" — same treatment as .section--tint */
.site [data-band="tint"]{
  background:var(--b-surface-dark);
  border-top:1px solid var(--b-border);border-bottom:1px solid var(--b-border);
}


/* ---- 30.10 LONG-FORM : /legal/{slug} + /rekisteriseloste ----------------
   RULING: these invert to a white ground. Minutes of reading, GDPR prose,
   tables — white paper is the right surface and the brand allows it as the
   emphasis surface. Scoped with :has(.legal-doc) so it cannot leak onto the
   other five pages. /rekisteriseloste needs the existing .legal-doc class on
   its wrap to qualify — structural ask S-1, no new class name.            */
.site:has(.legal-doc){background:var(--b-surface-light);color:var(--b-ink)}
.site:has(.legal-doc) .topnav{background:rgba(255,255,255,.82);border-bottom:1px solid rgba(17,17,17,.1)}
.site:has(.legal-doc) .brand,
.site:has(.legal-doc) .brand .ai,
.site:has(.legal-doc) h1,.site:has(.legal-doc) h2,.site:has(.legal-doc) h3{color:var(--b-ink)}
.site:has(.legal-doc) .topnav__links{background:rgba(17,17,17,.04);border-color:rgba(17,17,17,.14)}
.site:has(.legal-doc) .topnav__links a:not(.btn){color:var(--b-ink-2)}
.site:has(.legal-doc) .topnav__links a:not(.btn):hover{color:var(--b-ink);background:rgba(17,17,17,.06)}
.site:has(.legal-doc) .lang .on{color:var(--b-ink);box-shadow:inset 0 0 0 1px rgba(17,17,17,.18)}
.site:has(.legal-doc) .lang a{color:var(--b-ink-2)}
.site:has(.legal-doc) .btn{background:var(--b-ink);border-color:var(--b-ink);color:#ffffff}
.site:has(.legal-doc) .btn:hover{background:var(--b-hover-dark)}
.site:has(.legal-doc) .mut,.site:has(.legal-doc) .faint,.site:has(.legal-doc) .t-sm.mut{color:var(--b-ink-2)}
.site:has(.legal-doc) a:not(.btn):not(.brand):not(.topnav__links a):not(.lang-link):not(.site-foot a){color:var(--b-ink);text-decoration:underline;text-underline-offset:.22em}
.site:has(.legal-doc) .topnav__links a,.site:has(.legal-doc) .site-foot a{text-decoration:none}
.site:has(.legal-doc) .topnav__links a:hover,.site:has(.legal-doc) .site-foot a:hover{text-decoration:underline}
.site:has(.legal-doc) .site-foot{border-top:1px solid rgba(17,17,17,.14);color:var(--b-ink-2)}
.site:has(.legal-doc) .site-foot b{color:var(--b-ink)}
.site:has(.legal-doc) .site-foot a{color:var(--b-ink-2)}
.site:has(.legal-doc) p,.site:has(.legal-doc) li{color:var(--b-ink)}

/* the document itself: one measure, a heading rhythm, ruled tables */
.site .legal-doc{max-width:68ch;font-size:19px;line-height:1.62;color:var(--b-ink)}
.site .legal-doc h2{font-size:clamp(28px,3vw,40px);font-weight:900;letter-spacing:-.035em;line-height:1.05;margin:0 0 .5em}
.site .legal-doc h3{font-size:22px;font-weight:700;letter-spacing:-.02em;margin:2.2em 0 .5em;padding-top:1.1em;border-top:1px solid rgba(17,17,17,.14)}
.site .legal-doc h4{font-size:18px;font-weight:700;margin:1.6em 0 .4em}
.site .legal-doc p{margin:.85em 0;max-width:68ch}
.site .legal-doc ul,.site .legal-doc ol{margin:1em 0 1.4em 1.1em;padding:0}
.site .legal-doc li{margin:.45em 0;line-height:1.55;padding-left:.3em}
.site .legal-doc li::marker{color:var(--b-ink-2)}
.site .legal-doc table{width:100%;border-collapse:collapse;margin:1.6em 0;font-size:16px}
.site .legal-doc td,.site .legal-doc th{border:0;border-bottom:1px solid rgba(17,17,17,.14);padding:14px 16px 14px 0;vertical-align:top;text-align:left}
.site .legal-doc tr:first-child td{border-bottom:1px solid var(--b-ink);font-weight:700}
.site .legal-doc hr{border:0;border-top:1px solid rgba(17,17,17,.14);margin:2.4em 0}
/* /rekisteriseloste renders its prose as bare h1/h2/p inside the wrap */
.site:has(.legal-doc) .wrap > h2{font-size:clamp(24px,2.4vw,30px);margin:2.2em 0 .5em;padding-top:1.1em;border-top:1px solid rgba(17,17,17,.14);max-width:68ch}
.site:has(.legal-doc) .wrap > p{max-width:68ch;font-size:19px;line-height:1.62;margin:.85em 0}


/* ---- 30.11 LOGO --------------------------------------------------------- */
/* Wordmark: "SavonAI" in Archivo 900 at -.02em + a #0071e3 full stop. White on
   black, black on white. Clear space = the dot's diameter on every side. The
   inline 32×32 SVG (blue square + amber triangle) is hidden here and should be
   deleted from public_base.html; favicon.svg gets the new mark. Ship OUTLINED
   PATHS for any exported logo file — the brand folder's <text> versions render
   in a fallback face wherever Archivo is absent. */


/* ---- 30.12 LOADING / MOTION -------------------------------------------- */
.site .spinner{border-color:var(--b-border);border-top-color:#ffffff;width:18px;height:18px}
.site .skel{background:var(--b-ghost);border-radius:var(--r)}
.site .skel::after{background:linear-gradient(90deg,transparent,rgba(244,246,250,.10),transparent)}
.site .run-head{gap:14px;color:var(--faint)}
.site .demo-fade{transition:opacity .5s ease,transform .5s ease}
@media(prefers-reduced-motion:reduce){
  .site .meter > i{transition:none}
  .site .demo-fade{transition:none;transform:none}
  .site .spinner{animation:none}
}


/* ---- 30.13 RESPONSIVE (mobile-first audience — most arrive on a phone) -- */
@media(max-width:1040px){
  .site .topnav__links{gap:2px}
  .site .topnav__links a:not(.btn){padding:11px 11px;font-size:14px}
}
@media(max-width:860px){
  .site .topnav__in{height:76px;gap:12px;padding:0 16px}
  /* savonai.css hides the nav's text links below 860px; the .site rule above
     re-shows them by being later in the cascade, so hide them again here or the
     header overflows the viewport by ~220px. */
  .site .topnav__links a:not(.btn):not(.lang-link){display:none}
  /* home.html's dark band is a two-column grid declared INLINE, so it needs
     !important to collapse on a phone. Ask S-4 covers removing it. */
  .site [data-band="dark"] .wrap{grid-template-columns:1fr!important;gap:32px!important}
  .site .brand{font-size:22px}
  .site .topnav__links{padding:5px 5px 5px 6px;gap:4px}
  .site .topnav__links .btn{min-height:44px;padding:0 16px;font-size:14px}
  .site .hero__grid > div:first-child{min-height:auto;padding-bottom:56px}
  .site .hero__grid > .card{padding-top:36px;padding-bottom:56px}
  .site .grid.g2,.site .grid.g3,.site .grid.grid--3{grid-template-columns:1fr}
  .site .section{padding:64px 0}
  .site .price{font-size:56px}
}
@media(max-width:560px){
  .site .scorecard{grid-template-columns:1fr}
  .site .kpi--feature .kpi__val{font-size:64px}
  .site .btn,.site .btn--lg{width:100%}
  .site .row .btn{flex:1 1 auto}
  .site .legal-doc{font-size:18px}
}
/* ======================== end section 30 ================================= */


/* ============================================================================
   31. PUBLIC MARKETING SURFACE — Brain-first components
       (spec: content-brief-v4.md · design-brief-v4.md §10)
   ----------------------------------------------------------------------------
   Section 30 re-skins what exists. This section adds the components the
   Brain-first content refocus needs and that have no equivalent in savonai.css.
   Still entirely inside `.site` — the app scope invariant is untouched.

   These ARE new class names, which §0 of the design brief forbids and §10.1
   narrowly permits: only on `/`, the new `/verkkosivut`, and `/aivot`'s
   capability grid. Every one is listed as a structural ask so the developer adds
   the markup deliberately. Nothing in the §6 class contract is renamed, merged
   or dropped.
   ========================================================================== */


/* ---- 31.1 THE WHITE SHEET -----------------------------------------------
   The brand's emphasis surface, used for the Brain block, the analysis-CTA
   card, the featured pricing card and the closing CTA. One class flips the
   whole subtree to the light palette, so a white surface never needs its text
   colours restated element by element.                                     */
.site .sheet{
  background:var(--b-surface-light);color:var(--b-ink);
  border-radius:32px;padding:clamp(32px,5vw,72px);
}
.site .sheet--flush{border-radius:0;padding-left:0;padding-right:0}
.site .sheet h1,.site .sheet h2,.site .sheet h3,.site .sheet h4,
.site .sheet .t-display,.site .sheet .t-h1,.site .sheet .t-h2,.site .sheet .t-h3,
.site .sheet .price,.site .sheet b,.site .sheet .kpi__val{color:var(--b-ink)}
.site .sheet p,.site .sheet li,.site .sheet .t-lead,.site .sheet .t-body{color:var(--b-ink)}
.site .sheet .mut,.site .sheet .faint,.site .sheet .kicker,
.site .sheet .t-sm.mut,.site .sheet .t-xs,.site .sheet .price small,
.site .sheet .kpi__label{color:var(--b-ink-2)!important}
.site .sheet .btn{background:var(--b-ink);border-color:var(--b-ink);color:#ffffff}
.site .sheet .btn:hover{background:var(--b-hover-dark);border-color:var(--b-hover-dark);color:#ffffff}
.site .sheet .btn--ghost,.site .sheet .btn--sec{background:none;border-color:rgba(17,17,17,.28);color:var(--b-ink)}
.site .sheet .btn--ghost:hover,.site .sheet .btn--sec:hover{background:rgba(17,17,17,.06);border-color:var(--b-ink);color:var(--b-ink)}
.site .sheet a:not(.btn){color:var(--b-ink)}
.site .sheet .card{border-color:rgba(17,17,17,.16)}
.site .sheet :focus-visible{box-shadow:0 0 0 2px #ffffff,0 0 0 4px var(--b-ink)}
/* the input group inside the embedded-CTA variant */
.site .sheet .input,.site .sheet .field-prefix{border-color:rgba(17,17,17,.3);color:var(--b-ink)}
.site .sheet .input{color:var(--b-ink)}
.site .sheet .input::placeholder{color:var(--b-ink-2)}
.site .sheet .field-prefix .px{color:var(--b-ink-2)}
.site .sheet .field-prefix:focus-within{border-color:var(--b-ink);box-shadow:0 0 0 2px #ffffff,0 0 0 4px var(--b-ink)}


/* ---- 31.2 STATUS CHIP  (content brief §3) -------------------------------
   Three values only: Käytössä / Pilotissa / Tulossa.

   ⚠ Legible without colour, like everything else in this system. Three cues
   per value, none of them hue:
     live   filled white pill, black ink, 700        — the loudest
     pilot  outlined pill, white ink, + a filled dot — mid
     soon   DASHED outlined pill, muted ink          — quietest
   And the word itself is always present, so the chip is self-describing even
   in a monochrome print-out or at 200% zoom.                                */
.site .chip{
  display:inline-flex;align-items:center;gap:7px;flex:none;
  font:700 12px/1 var(--font);letter-spacing:.1em;text-transform:uppercase;
  padding:7px 12px;border-radius:999px;border:1px solid transparent;white-space:nowrap;
}
.site .chip--live{background:#ffffff;border-color:#ffffff;color:var(--b-ink)}
.site .chip--pilot{background:none;border-color:var(--b-border-strong);color:#ffffff}
.site .chip--pilot::before{content:"";width:7px;height:7px;border-radius:50%;background:#ffffff;flex:none}
.site .chip--soon{background:none;border-style:dashed;border-color:var(--b-border-strong);color:var(--faint)}
/* the accent full stop, as live type. `.brand` gets one via ::after (§30.8); this
   is the class for the one in the homepage H1 — see the deviation note about the
   accent appearing twice on `/`. */
.site .stop{color:var(--b-accent)}
/* on a white surface the same three cues invert. `.acc__row` is white too, so it
   takes the identical treatment — without this, chip--pilot is white ink on a
   white row and vanishes entirely. */
.site .sheet .chip--live,.site .acc__row .chip--live{background:var(--b-ink);border-color:var(--b-ink);color:#ffffff}
.site .sheet .chip--pilot,.site .acc__row .chip--pilot{border-color:rgba(17,17,17,.4);color:var(--b-ink)}
.site .sheet .chip--pilot::before,.site .acc__row .chip--pilot::before{background:var(--b-ink)}
.site .sheet .chip--soon,.site .acc__row .chip--soon{border-color:rgba(17,17,17,.32);color:var(--b-ink-2)}


/* ---- 31.3 ACCORDION ROW  (content brief §4.5) ---------------------------
   White rows, r28. Head = title + ordinal + chip; one body open at a time,
   the first open on load. Built on <details>/<summary> so it works with no JS
   at all and is keyboard-operable and screen-reader-correct for free; the
   page's small vanilla script only enforces the one-at-a-time behaviour.    */
.site .acc{display:flex;flex-direction:column;gap:12px}
.site .acc__row{
  background:var(--b-surface-light);color:var(--b-ink);border-radius:28px;overflow:hidden;
}
.site .acc__head{
  display:flex;align-items:center;gap:clamp(16px,3vw,32px);
  padding:clamp(22px,2.6vw,32px) clamp(24px,3vw,40px);
  cursor:pointer;list-style:none;
}
.site .acc__head::-webkit-details-marker{display:none}
.site .acc__n{
  font:900 15px/1 var(--font);letter-spacing:-.01em;color:var(--b-ink-2);
  flex:none;width:2.2em;font-variant-numeric:tabular-nums;
}
.site .acc__t{
  flex:1 1 auto;font:900 clamp(19px,2vw,26px)/1.2 var(--font-display);
  letter-spacing:-.028em;color:var(--b-ink);text-wrap:balance;
}
.site .acc__body{
  padding:0 clamp(24px,3vw,40px) clamp(24px,2.6vw,34px);
  max-width:74ch;font-size:17px;line-height:1.55;color:var(--b-ink-2);
}
/* Explicit collapse. A closed <details> already suppresses its body in every
   current UA, so this looks redundant — it is not. It makes the collapsed state
   depend on a CSS rule we own rather than on UA box suppression surviving the
   row's `overflow:hidden`, a nested transform, or a framework that drops the
   bare `open` attribute on render. Without it a dropped `open` means every
   description paints at once, outside its own row. */
.site .acc__row:not([open]) .acc__body{display:none}
.site .acc__row:hover{background:#f2f2f4}
.site .acc__row[open]{background:var(--b-surface-light)}
.site .acc__row[open] .acc__head{padding-bottom:clamp(14px,1.6vw,20px)}
.site .acc__head:focus-visible{outline:none;box-shadow:inset 0 0 0 3px var(--b-ink)}
/* the marker: a plus that becomes a minus. Rotation, not a glyph swap. */
.site .acc__mark{position:relative;width:18px;height:18px;flex:none}
.site .acc__mark::before,.site .acc__mark::after{
  content:"";position:absolute;inset:50% 0 auto;height:1.5px;background:var(--b-ink);
  transition:transform .14s ease;
}
.site .acc__mark::after{transform:rotate(90deg)}
.site .acc__row[open] .acc__mark::after{transform:rotate(0deg)}


/* ---- 31.4 STAT CARD  (content brief §4.3, §4.7) -------------------------
   Dark card, 1px border, r28, big number + caption + a footnote-marker slot.
   ⚠ Every figure on the site needs a source. `.statcard__fn` is that slot —
   a superscript marker that links to the note under the band. It is part of
   the component, not an afterthought, so an unsourced stat looks unfinished.  */
.site .statband{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.site .statcard{
  border:1px solid var(--b-border);border-radius:28px;
  padding:clamp(28px,3.2vw,44px);display:flex;flex-direction:column;gap:14px;
}
.site .statcard__n{
  font:900 clamp(48px,6vw,86px)/.92 var(--font-display);letter-spacing:-.045em;color:#ffffff;
}
.site .statcard__c{font-size:16px;line-height:1.45;color:var(--mut);max-width:26ch;text-wrap:pretty}
.site .statcard__fn{
  font:700 11px/1 var(--font);vertical-align:super;margin-left:.35em;
  color:var(--faint);text-decoration:none;
}
.site .statcard__fn:hover{color:#ffffff}
.site .statnote{
  margin-top:20px;font-size:13px;line-height:1.5;color:var(--faint);max-width:80ch;
}
.site .statnote b{color:var(--mut);font-weight:700}


/* ---- 31.5 CAPABILITY GRID  (content brief §5.3) -------------------------
   8–16 cards, each title + one line + chip, with a filter over the chip
   values. Designed so a mixed set of chips still reads as one grid: the chip
   sits on its own baseline at the card foot, never inline with the title.   */
.site .capgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.site .capcard{
  border:1px solid var(--b-border);border-radius:28px;padding:clamp(24px,2.6vw,34px);
  display:flex;flex-direction:column;gap:12px;
}
.site .capcard__t{font:700 19px/1.25 var(--font-display);letter-spacing:-.022em;color:#ffffff}
.site .capcard__d{font-size:15px;line-height:1.5;color:var(--mut);flex:1 1 auto}
.site .capcard__foot{display:flex;align-items:center;justify-content:flex-start;padding-top:4px}
.site .capcard--open{border-style:dashed}
/* the filter: a pill row, the active one filled. Counts are printed so the
   pilot's "what works now" question is answered before a click. */
.site .capfilter{display:flex;flex-wrap:wrap;gap:8px}
.site .capfilter__btn{
  font:600 14px/1 var(--font);letter-spacing:-.005em;
  min-height:44px;padding:0 18px;border-radius:999px;
  background:none;border:1px solid var(--b-border-strong);color:var(--ink-2);cursor:pointer;
  display:inline-flex;align-items:center;gap:8px;transition:background .14s ease,color .14s ease;
}
.site .capfilter__btn:hover{background:var(--b-ghost);color:#ffffff}
.site .capfilter__btn[aria-pressed="true"]{background:#ffffff;border-color:#ffffff;color:var(--b-ink)}
.site .capfilter__n{font-variant-numeric:tabular-nums;opacity:.62;font-weight:700}
.site .capcard[hidden]{display:none}


/* ---- 31.6 CENTRED HERO + SPLIT BLOCK  (content brief §4.2, §4.4) --------
   The homepage hero is type only, centred, at full display size — the one
   place the 170px ceiling is reached. No card, no motif (§3.3 ruling).      */
.site .hero--center{padding:clamp(72px,11vw,150px) 0 clamp(56px,7vw,110px)!important;text-align:center}
.site .hero--center .t-display{margin:clamp(18px,2.4vw,32px) 0 0;text-wrap:balance}
.site .hero--center .t-lead{
  max-width:44ch;margin-left:auto;margin-right:auto;margin-top:clamp(20px,2.6vw,34px);
}
.site .hero--center .row{justify-content:center;margin-top:clamp(28px,3.4vw,44px)}

/* headline left, body + CTA right, baseline-aligned */
.site .split{display:grid;grid-template-columns:1fr 1fr;gap:clamp(28px,5vw,72px);align-items:baseline}
.site .split > div:last-child{display:flex;flex-direction:column;align-items:flex-start;gap:24px}

/* the "you always decide" line and other single muted statements under a block */
.site .undernote{margin-top:22px;font-size:16px;color:var(--faint);max-width:70ch}
.site .center .undernote,.site .undernote--center{margin-left:auto;margin-right:auto;text-align:center}


/* ---- 31.7 RESPONSIVE ---------------------------------------------------- */
@media(max-width:860px){
  .site .statband,.site .capgrid{grid-template-columns:1fr}
  .site .split{grid-template-columns:1fr;gap:24px;align-items:start}
  .site .sheet{border-radius:24px;padding:28px 22px}
  .site .acc__row{border-radius:22px}
  .site .acc__t{font-size:19px}
  .site .acc__head{gap:14px;padding:20px 22px}
  .site .acc__body{padding:0 22px 22px}
  .site .acc__n{width:1.9em;font-size:14px}
  .site .hero--center{padding-top:56px!important}
  .site .capfilter__btn{font-size:13px;padding:0 14px}
}
@media(max-width:560px){
  /* the chip drops below the title rather than squeezing it */
  .site .acc__head{flex-wrap:wrap}
  .site .acc__t{flex:1 1 100%;order:2;width:100%}
  .site .acc__n{order:1}
  .site .acc__mark{order:1;margin-left:auto}
  .site .acc__head .chip{order:3}
  .site .statcard__n{font-size:56px}
}
@media(prefers-reduced-motion:reduce){
  .site .acc__mark::before,.site .acc__mark::after{transition:none}
  .site .capfilter__btn{transition:none}
}
/* ======================== end section 31 ================================= */


/* ============================================================================
   32. PUBLIC MARKETING SURFACE — as-built addenda  (spec: ui-redesign.md §v4.10)
   ----------------------------------------------------------------------------
   APPENDED AFTER the delivered sections 30 + 31, deliberately, so those stay
   byte-identical to docs/design/design_handoff_public_surface/savonai-site-v4.css
   and their diff remains checkable against the deliverable. Everything here was
   found by measuring the built pages, not by redesigning them.

   ⛔ Same invariant: every selector below begins with `.site`.
   ========================================================================== */

/* ---- 32.1 long-form tables must not push the PAGE sideways ---------------
   MEASURED, D-848: /legal/{slug} reaches 644px inside a 375px viewport — and
   642px under the PRE-REBRAND stylesheet too, so this is a live defect the
   rebrand inherited rather than caused (same family as S-4). §30.10 sets
   `width:100%`, which cannot cap a table's INTRINSIC minimum: long unbreakable
   cell text still forces the box wider than the screen and takes the document
   with it.

   The table scrolls inside its own box below the breakpoint instead. Desktop is
   untouched — this is a phone-only containment, not a restyle — and it is what
   makes §v4.8 test 10 (no horizontal overflow at 320/375/414) true rather than
   aspirational. A privacy policy is the last page that should need sideways
   dragging to read.                                                        */
@media(max-width:760px){
  .site .legal-doc table{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}
  .site .legal-doc td,.site .legal-doc th{min-width:11ch}
}

/* ---- 32.2 Finnish compounds must be allowed to break in long-form headings -
   MEASURED, D-848: /rekisteriseloste reaches 329px inside a 320px viewport. The
   whole overflow is ONE word — "prospektirekisterin" in the h1 — which cannot
   fit on a 280px line at the long-form heading size and, having nowhere to
   break, pushes the document instead.

   This is the Finnish length problem the design return flagged (FI runs 20–35%
   longer than EN, and the display floor was already dropped from 72px to 44px
   for it). Hyphenation, not a smaller size: `lang="fi"` is on <html>, so
   `hyphens:auto` breaks at real syllable boundaries, and `overflow-wrap` is the
   backstop for a browser that will not hyphenate. Scoped to the long-form
   surface, where the measurement was taken — the display type on the other
   pages already balances and clamps, and measured clean at 320px.         */
.site:has(.legal-doc) h1,
.site:has(.legal-doc) h2,
.site:has(.legal-doc) h3,
.site .legal-doc h1,
.site .legal-doc h2,
.site .legal-doc h3{overflow-wrap:break-word;hyphens:auto}

/* ---- 32.3 the language toggle must not shrink below its own labels -------
   MEASURED, D-913: on a 375px phone `.lang` was 45px wide holding 79px of
   content and CLIPPING the active label — the second chip rendered as a sliver
   next to the CTA, which reads as a broken button rather than a cut-off toggle.

   Cause: `.lang` carries `overflow:hidden` from the app's design system (§3),
   where it clips the active chip's fill to a bordered pill. §30.8 takes that
   border away and draws the active state with an inset shadow instead, so the
   clipping has nothing left to do — but it was never reset, and
   `overflow:hidden` makes a flex item's automatic minimum size resolve to ZERO.
   So the toggle was free to shrink under the CTA and then hide the evidence.

   Two fixes, because either alone leaves half the bug: stop it clipping, and
   stop it shrinking. The labels are the one thing in the nav that must never
   compress — FI/EN is how a Finnish visitor reaches Finnish.                */
.site .lang{overflow:visible;flex:0 0 auto}

@media(max-width:860px){
  /* The nav is already down to the toggle + the CTA here. Tighten the chips so
     both survive a 320px screen without the CTA having to shrink its label. */
  .site .lang a,.site .lang span{padding:9px 8px}
  .site .topnav__links .btn{flex:0 1 auto;min-width:0}
}

/* ---- 32.4 the URL field must shrink, not clip, on a small phone ----------
   MEASURED, D-913 addendum: on a 320px screen the homepage analysis CTA's
   `.field-prefix` was 234px wide around 276px of content — 42px of the input
   unreachable. Found by the clipping check §32.3 introduced, which is the
   whole point of having written it.

   SAME SHAPE as the nav toggle, DIFFERENT FIX. `.field-prefix` also carries
   `overflow:hidden` from §9 — but here the clipping is LOAD-BEARING: it rounds
   the square-cornered <input> to the pill's 999px border. Removing it would
   put a square corner inside a pill. So this removes the CAUSE of the overflow
   instead: `.field-inline .input{min-width:200px}` and
   `.field-prefix{min-width:220px}` (both §9) are desktop ergonomics — they stop
   the field getting uselessly narrow on a wide screen — and on a 320px phone
   they force 276px of content into a 234px box.

   Below the stacking breakpoint the field is already full width and the button
   already sits under it, so the minimums have nothing left to protect.

   ⚠ Do NOT "simplify" this by dropping `overflow:hidden` the way §32.3 does.
   The two rules look identical and are not: one clips for a border that no
   longer exists, this one clips for a border that does.                    */
@media(max-width:560px){
  .site .field-prefix{min-width:0}
  .site .field-inline .input{min-width:0}
}

/* ---- 32.5 the nav must fit on the narrowest phones without wrapping ------
   Consequence of §32.3, measured and then fixed rather than left. Once the
   language toggle stopped shrinking, the squeeze moved to the CTA and its
   label wrapped to two lines inside a 44px pill — FI at ≤360px, EN at 320px.
   That is a far better failure than a clipped toggle (nothing is unreachable),
   but it is still not what the design says.

   §30.13 already steps the nav down twice — padding and font at 1040, again at
   860. This is the same move one step further, for the phones below the design
   return's 375px reference width. Measured after: FI one line at 360 (was two),
   EN one line at 320 (was two), nothing clipped, nothing past the viewport.

   ⚠ FI at 320px still wraps. "Aloita ilmaiseksi" beside a wordmark and a
   language toggle does not fit 320 CSS pixels at a legible size, and the
   remaining choices are all worse: shrink the label below 13px, drop the
   toggle (it is how a Finnish visitor reaches Finnish), or cut the CTA (it is
   the conversion). Two readable lines is the right answer there.           */
@media(max-width:374px){
  .site .topnav__links{padding:4px 4px 4px 5px;gap:2px}
  .site .topnav__links .btn{padding:0 12px;font-size:13px}
  .site .lang a,.site .lang span{padding:9px 6px}
  .site .brand{font-size:20px}
}

/* ---- 32.6 an anchor jump must not park the heading under the sticky nav --
   MEASURED, D-1215 addendum: at 375px, jumping to `#miten`, `#pricing` or `#tyot` left the
   heading's top 11–12px BEHIND the sticky header. `.site .topnav` is 96px tall (76px below
   860px) and `.site .section` has 64px of top padding on a phone, so the padding nearly — but
   not quite — clears the nav.

   Pre-existing: `/#miten` has been the nav's "Miten toimii" since D-848 and has always landed
   this way. It surfaced now because the nav gained two more in-page jumps, which turned one
   slightly-clipped heading into three.

   `scroll-margin-top` is the property for exactly this: it offsets the SCROLL destination
   without moving the element, so nothing about the layout changes — only where a jump stops.
   Sized to the nav rather than guessed, and stepped at the same 860px breakpoint the nav is. */
.site .section[id],
.site .card[id]{scroll-margin-top:96px}

@media(max-width:860px){
  .site .section[id],
  .site .card[id]{scroll-margin-top:76px}
}

/* ---- 32.7 v6 — THE INDUSTRY TABS (CD-119, public-site-v6.md §4.1, §10) ---
   The nav carries the industry tabs (three since D-2299) AND the section links AND the
   meeting button.
   Measured against the content width: FI labels need ~1390px on one row and the
   row is 1200px, so the tabs ALWAYS take their own row under the wordmark — the
   same place at every width, rather than a layout that changes at a breakpoint
   nobody tests. On a phone the row scrolls sideways inside itself (never the
   page), so all four stay one thumb away.
   The current tab is the white pill with dark text — the same "selected" the
   language toggle's inverse uses. No accent: #0071e3 is the wordmark's stop only. */
/* ⚠ A GRID, not flex-wrap — measured at 320px: with wrap, the wordmark and the
   link pill no longer fit one row and the pill dropped to a row of its own (three
   header rows). A grid never wraps, so the pill SHRINKS instead (its button label
   may take two lines, §32.5's accepted failure) and the header stays two rows. */
.site .topnav__in{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;column-gap:24px;row-gap:0;height:auto}
.site .topnav__in > .brand{grid-column:1;grid-row:1;min-height:96px}
.site .topnav__in > .topnav__links{grid-column:2;grid-row:1;justify-self:end;margin-left:0;min-width:0}
/* ⚠ `.tabs` is also the APP's tab strip (§1–§29: a bottom rule and 24px under it). Both are
   reset here: measured on the v6 header, they drew a second hairline 25px above the header's
   own and made it 176px tall (D-2299). */
.site .tabs{
  grid-column:1 / -1;grid-row:2;min-width:0;display:flex;gap:6px;margin:0;padding:0 0 14px;border:0;
  overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch;
}
.site .tabs::-webkit-scrollbar{display:none}
.site .tabs a{
  flex:none;white-space:nowrap;min-height:40px;padding:0 18px;border-radius:999px;
  display:inline-flex;align-items:center;font-size:14px;font-weight:600;letter-spacing:-.005em;
  color:#ffffff;background:var(--b-ghost);border:1px solid var(--b-border);
}
.site .tabs a:hover{color:#ffffff;border-color:#ffffff;text-decoration:none}
.site .tabs a[aria-current="page"]{background:#ffffff;color:var(--b-ink);border-color:#ffffff}
.site:has(.legal-doc) .tabs a{color:var(--b-ink-2);background:none;border-color:rgba(17,17,17,.18)}
.site:has(.legal-doc) .tabs a:hover{color:var(--b-ink);border-color:var(--b-ink)}
/* the header is two rows now: the anchor offset follows it (§32.6 sized it for one) */
.site .section[id],.site .card[id]{scroll-margin-top:160px}
@media(max-width:860px){
  .site .topnav__in{column-gap:12px}
  .site .topnav__in > .brand{min-height:76px}
  .site .tabs{padding-bottom:10px}
  .site .tabs a{min-height:38px;padding:0 14px;font-size:14px}
}

/* ---- 32.8 v7 — THE INDUSTRY PAGE (D-2299, public-site-v7.md §4, §10) ------
   The 2026-10-11 handoff, which replaces v6's centred axis (owner, 2026-10-11): heads are
   left-aligned, every grid is auto-fit, cards are dark on black with at most one white card
   beside them, and the Brain is drawn on three canvases by landing.js.
   Every class here is `lp-…` and only landing.html uses it. Existing tokens only. No shadow,
   no gradient, and no accent: the Brain's one blue node is painted by the script from
   --b-accent, so the stylesheet still names the accent once (the wordmark's stop).
   A card carries its own palette in five custom properties (--h heading, --b body, --m muted,
   --rule hairline, --inv the text on a filled pill), so the white card restates no element. */

/* the header: opaque (v6 R9, measured: text showed through the 72 % header), and it scrolls
   away on a phone, where two rows would take a fifth of the screen */
.site .topnav{background:#000000;backdrop-filter:none;-webkit-backdrop-filter:none;border-bottom:1px solid var(--b-border)}
.site:has(.legal-doc) .topnav{background:#ffffff}
@media(max-width:860px){
  .site .topnav{position:relative}
  .site .section[id],.site .card[id]{scroll-margin-top:16px}
}
/* screen-reader-only text (the forecast's numbers) */
.site .vh{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}

/* 1 · hero */
.site .lp-hero{padding:clamp(40px,6vw,80px) 0 clamp(56px,8vw,100px)}
.site .lp-hero__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,340px),1fr));gap:32px 40px;align-items:center}
.site .lp-h1{margin:22px 0 0;font-size:clamp(38px,6vw,84px);font-weight:900;line-height:.98;letter-spacing:-.04em;text-wrap:balance}
.site .lp-lead{margin:28px 0 0;max-width:620px;font-size:clamp(18px,2vw,22px);line-height:1.5;color:var(--ink-2)}
.site .lp-actions{margin-top:36px;display:flex;flex-wrap:wrap;gap:12px}
.site .landing .btn--lg{min-height:52px;padding:0 30px;font-size:16px;font-weight:700}
.site .lp-brain{position:relative;aspect-ratio:1/1;width:100%;max-width:580px;justify-self:center}
.site .lp-brain canvas,.site .lp-stage__view canvas,.site .lp-cta__brain canvas{position:absolute;inset:0;width:100%;height:100%;display:block;touch-action:pan-y;cursor:grab}
.site .lp-brain__hint{position:absolute;left:0;bottom:0;font-size:12px;letter-spacing:.2em;text-transform:uppercase;color:var(--faint);pointer-events:none}
/* no script, no Brain: an empty square is worse than none */
.site .landing:not(.js) .lp-brain,.site .landing:not(.js) .lp-cta__brain,
.site .landing:not(.js) .lp-stage__view,.site .landing:not(.js) .lp-stage__dots{display:none}
.site .lp-gains{list-style:none;margin:clamp(40px,6vw,72px) 0 0;padding:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:32px}
.site .lp-gains li{margin:0;border-top:2px solid #ffffff;padding-top:18px}
.site .lp-gains b{display:block;font-size:22px;font-weight:900;letter-spacing:-.02em;color:#ffffff}
.site .lp-gains span{display:block;margin-top:6px;font-size:16px;line-height:1.5;color:var(--faint)}

/* 1b · #asiakkaat — the reference strip (D-2826). White logos drift left to right across the full
   width; a pointer or keyboard focus on the strip stops them. The list is drawn four times and the
   track starts half its width to the left and slides home, so the loop has no seam. The keyframes
   name only `to` (the start is the track's own transform). Reduced motion: one still row. */
.site .lp-sec.lp-refs{padding:clamp(40px,6vw,64px) 0;overflow:hidden}
.site .lp-refs__h{margin:0}
.site .lp-refs__view{margin:28px auto 0;max-width:2200px;overflow:hidden}
.site .lp-refs__track{list-style:none;margin:0;padding:0;display:flex;align-items:center;width:max-content;
  transform:translate3d(-50%,0,0);animation:lp-refs 70s linear infinite}
.site .lp-refs__view:hover .lp-refs__track,.site .lp-refs__view:focus-within .lp-refs__track{animation-play-state:paused}
.site .lp-refs__track li{flex:none;margin:0 clamp(36px,4.5vw,64px) 0 0}
.site .lp-refs__track a{display:block;opacity:.72;transition:opacity .2s}
.site .lp-refs__track a:hover,.site .lp-refs__track a:focus-visible{opacity:1;text-decoration:none}
.site .lp-refs__track img{display:block;height:var(--h);width:auto;max-width:none}
@keyframes lp-refs{to{transform:translate3d(0,0,0)}}
@media(max-width:640px){
  .site .lp-refs__track img{height:calc(var(--h) * .75)}
}
@media(prefers-reduced-motion:reduce){
  .site .lp-refs__view{padding:0 20px}
  .site .lp-refs__track{animation:none;transform:none;width:auto;flex-wrap:wrap;justify-content:center;gap:28px 48px}
  .site .lp-refs__track li{margin:0}
  .site .lp-refs__track li[aria-hidden]{display:none}
}

/* 2 · sections: a hairline above, a left-aligned head, 44 px to the content */
.site .lp-sec{border-top:1px solid var(--b-border);padding:clamp(72px,10vw,120px) 0}
.site .lp-sec,.site .lp-close{scroll-margin-top:160px}
.site .lp-head{max-width:900px}
.site .lp-head--wide{max-width:960px}
.site .lp-head .t-h1,.site .lp-cta .t-h1{margin:16px 0 0;font-size:clamp(34px,5vw,64px);line-height:1;letter-spacing:-.04em}
.site .lp-sub{margin:20px 0 0;max-width:780px;font-size:19px;line-height:1.55;color:var(--ink-2)}
.site .lp-head + *{margin-top:44px}

/* 3 · the card and what goes in it */
.site .lp-card{
  --h:#ffffff;--b:var(--ink-2);--m:var(--faint);--rule:var(--b-border);--inv:var(--b-ink);
  min-width:0;margin:0;padding:26px 24px;border:0;border-radius:var(--r-lg);
  background:var(--b-surface-dark);color:var(--b);font:inherit;text-align:left;
}
.site .lp-card--light{--h:var(--b-ink);--b:var(--b-ink-2);--m:var(--b-ink-2);--rule:rgba(17,17,17,.2);--inv:#ffffff;background:var(--b-surface-light)}
.site .lp-card--line{background:none;border:1px solid var(--b-border-strong)}
.site .lp-card--roomy{padding:28px 26px}
.site .lp-card--tall{display:flex;flex-direction:column;padding:32px 28px}
.site :where(.lp-card) p{margin:10px 0 0;font-size:16.5px;line-height:1.55;color:var(--b)}
.site .lp-card__t{display:block;margin:14px 0 0;font-size:24px;font-weight:900;line-height:1.12;letter-spacing:-.03em;color:var(--h)}
.site .lp-card > .lp-card__t:first-child,.site .lp-faq__q{margin-top:0}
.site .lp-card__t--lg{margin-top:22px;font-size:26px;line-height:1.1;text-wrap:balance}
.site .lp-card__t--drop{margin-top:40px}
.site .lp-card .lp-card__s{display:block;margin:4px 0 0;font-size:15px;line-height:1.4;color:var(--m)}
.site .lp-tag{display:block;margin:0;font-size:13px;font-weight:600;line-height:1.4;letter-spacing:.3em;text-transform:uppercase;color:var(--m,var(--faint))}
.site .lp-tag--sm{font-size:12px;font-weight:700;letter-spacing:.25em}
.site .lp-num{display:block;font-size:15px;font-weight:700;letter-spacing:.1em;color:var(--m,var(--faint))}
.site .lp-rows{list-style:none;margin:18px 0 0;padding:0}
.site .lp-rows li{margin:0;padding:10px 0;border-top:1px solid var(--rule);font-size:15.5px;line-height:1.4;color:var(--b)}
.site .lp-rows b{color:var(--h)}
.site .lp-rows + .lp-tag{margin-top:12px}
.site .lp-rows--mut{margin-top:6px}
.site .lp-rows--mut li{padding:8px 0;font-size:15px;color:var(--m)}
.site .lp-grid{list-style:none;margin:0;padding:0;display:grid;gap:16px}
/* D-2826: a grid right under a head keeps the 44 px of `.lp-head + *` (the rule above zeroed it) */
.site .lp-head + .lp-grid{margin-top:44px}
.site .lp-grid--260{grid-template-columns:repeat(auto-fit,minmax(min(100%,260px),1fr))}
.site .lp-grid--280{grid-template-columns:repeat(auto-fit,minmax(min(100%,280px),1fr))}
.site .lp-grid--290{grid-template-columns:repeat(auto-fit,minmax(min(100%,290px),1fr))}
.site .lp-grid--300{grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr))}
.site .lp-gap-sm{margin-top:16px}
.site .lp-strip{display:flex;flex-wrap:wrap;align-items:center;gap:16px;margin:16px 0 0;padding:20px 28px;border:1px dashed var(--b-border-strong);border-radius:var(--r-lg);font-size:16px;line-height:1.5;color:var(--ink-2)}
.site .lp-strip svg{flex:none;width:28px;height:28px;fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.site .lp-strip span{flex:1;min-width:min(100%,240px)}
.site .lp-strip b{font-size:18px;color:#ffffff}

/* 4 · #mika */
.site .lp-what{display:flex;flex-wrap:wrap;gap:24px 48px;align-items:flex-end;justify-content:space-between}
.site .lp-what .lp-head{flex:1;min-width:min(100%,320px);max-width:860px}
.site .lp-247{margin:0;font-size:clamp(64px,10vw,128px);font-weight:900;line-height:.9;letter-spacing:-.05em;color:#ffffff}
.site .lp-areas{list-style:none;margin:36px 0 0;padding:0;display:flex;flex-wrap:wrap;gap:8px}
.site .lp-areas li{display:inline-flex;align-items:center;gap:10px;margin:0;padding:9px 18px;border:1px solid var(--b-border-strong);border-radius:999px;font-size:15px;font-weight:600;color:#ffffff}
.site .lp-areas li::before{content:"";width:7px;height:7px;border-radius:50%;background:#ffffff}
.site .lp-areas + .lp-grid{margin-top:24px}
.site .lp-pair{display:flex;flex-wrap:wrap;gap:16px 40px;align-items:center;margin-top:16px;padding:clamp(24px,4vw,40px)}
.site .lp-pair__t{flex:1;min-width:min(100%,260px);margin:0;font-size:clamp(24px,3vw,36px);font-weight:900;line-height:1.08;letter-spacing:-.03em;color:var(--h);text-wrap:balance}
.site .lp-pair__d{flex:1.4;min-width:min(100%,280px);margin:0;font-size:17px;line-height:1.55}

/* 5 · #toimii — the stage card. With the script ONE caption shows, but all five keep their
   place in one grid cell: the bar is as tall as the longest, so the auto-advance moves nothing
   below it, and a screen reader still reads the five as a list. */
.site .lp-stage{overflow:hidden;border:1px solid var(--b-border);border-radius:var(--r-lg);background:var(--b-bg)}
.site .lp-stage__view{position:relative;height:clamp(300px,42vw,460px);border-bottom:1px solid var(--b-border)}
.site .lp-stage__label{position:absolute;left:24px;top:20px;right:24px;font-size:12px;letter-spacing:.25em;text-transform:uppercase;color:var(--faint);pointer-events:none}
.site .lp-stage__bar{display:flex;flex-wrap:wrap;gap:16px 32px;align-items:center;justify-content:space-between;padding:20px 24px}
.site .lp-stage__caps{list-style:none;flex:1;min-width:min(100%,260px);margin:0;padding:0;display:grid;gap:14px}
.site .lp-stage__caps li{margin:0}
.site .lp-stage__cap{display:block;margin-top:6px;font-size:19px;font-weight:600;line-height:1.4;color:#ffffff;text-wrap:pretty}
.site .landing.js .lp-stage__caps{gap:0}
.site .landing.js .lp-stage__caps li{grid-area:1/1;opacity:0;transition:opacity .25s ease}
.site .landing.js .lp-stage__caps li.is-on{opacity:1}
.site .lp-stage__dots{display:flex;flex-wrap:wrap;gap:6px}
.site .lp-stage__dots button{min-height:36px;padding:0 14px;border:1px solid var(--b-border-strong);border-radius:999px;background:none;color:var(--ink-2);font:inherit;font-size:13px;font-weight:700;cursor:pointer}
.site .lp-stage__dots button[aria-pressed="true"]{background:#ffffff;border-color:#ffffff;color:var(--b-ink)}
/* 200, not the handoff's 210: our gutter is 48px, and five cards must still share one row at 1200 */
.site .lp-loop{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,200px),1fr));gap:16px;margin-top:16px}
.site .lp-loop .lp-card{outline:2px solid transparent;outline-offset:-2px}
.site .landing.js .lp-loop .lp-card{cursor:pointer}
.site .landing.js .lp-loop .lp-card.is-on{outline-color:#ffffff}
.site .landing.js .lp-loop .lp-card--light.is-on{outline-offset:3px}
.site .lp-decide{display:flex;flex-direction:column}
.site .lp-chips{list-style:none;margin:auto 0 0;padding:22px 0 0;display:flex;flex-wrap:wrap;gap:6px}
.site .lp-chips li{margin:0;padding:6px 12px;border:1px solid var(--h);border-radius:999px;font-size:13px;font-weight:700;color:var(--h)}
.site .lp-ex{margin-top:72px}
.site .lp-ex__t{margin:14px 0 0;font-size:clamp(26px,3.4vw,40px);font-weight:900;line-height:1.05;letter-spacing:-.03em}
.site .lp-ex__steps{list-style:none;margin:32px 0 0;padding:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,200px),1fr));gap:28px 20px}
.site .lp-ex__steps li{margin:0;padding-top:16px;border-top:2px solid var(--b-border-strong)}
.site .lp-ex__n{display:block;font-size:13px;font-weight:700;letter-spacing:.2em;text-transform:uppercase;color:var(--faint)}
.site .lp-ex__steps li.is-key{border-top-color:#ffffff}
.site .lp-ex__steps li.is-key .lp-ex__n{color:#ffffff}
.site .lp-ex__steps p{margin:10px 0 0;font-size:16px;line-height:1.5;color:var(--ink-2)}

/* 6 · #ketju — a level is a real button; without the script all three details are stacked */
.site .lp-chain{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,360px),1fr));gap:16px;align-items:stretch}
.site .lp-chain__levels{display:flex;flex-direction:column}
/* a <button> centres its content; the last level stretches, so its text is pinned to the top */
.site .lp-chain__level{display:flex;flex-direction:column;align-items:stretch;justify-content:flex-start;width:100%;padding:22px 24px;outline:2px solid transparent;outline-offset:-2px}
.site .lp-chain__level:last-child{flex:1}
.site .lp-chain__level .lp-card__t{margin-top:10px}
.site .landing.js .lp-chain__level{cursor:pointer}
.site .landing.js .lp-chain__level.is-on{outline-color:#ffffff}
.site .lp-chain__flow{display:flex;justify-content:space-between;gap:12px;margin:0 44px;padding:14px 12px;border-left:1px dashed var(--b-border-strong);border-right:1px dashed var(--b-border-strong);font-size:13px;font-weight:600;line-height:1.4;color:var(--faint)}
.site .lp-chain__flow span:last-child{text-align:right}
.site .lp-chain__chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:16px}
.site .lp-chain__chips span{padding:6px 14px;border:1px solid var(--b-border-strong);border-radius:999px;font-size:14px;font-weight:600;color:var(--ink-2)}
.site .lp-chain__chips--tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(110px,1fr));gap:8px}
.site .lp-chain__chips--tiles span{padding:12px;border-radius:14px;text-align:center}
.site .lp-chain__details{display:grid;gap:16px}
.site .lp-chain__detail{display:flex;flex-direction:column;padding:clamp(24px,3vw,36px)}
.site .landing.js .lp-chain__detail:not(.is-on){display:none}
.site .lp-chain__h{margin:12px 0 0;font-size:clamp(24px,2.6vw,32px);font-weight:900;line-height:1.1;letter-spacing:-.03em;color:var(--h);text-wrap:balance}
.site .lp-chain__detail .lp-rows{margin-bottom:20px}
.site .lp-chain__detail .lp-rows li{padding:11px 0;color:var(--h)}
.site .lp-box{margin-top:auto;padding:16px 18px;border:1px solid var(--h);border-radius:20px}
.site .lp-box p{margin:8px 0 0;font-size:15.5px;line-height:1.5;color:var(--h)}

/* 7 · #hallinta */
.site .lp-two{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,340px),1fr));gap:16px}
.site .lp-bb,.site .lp-queue{padding:clamp(24px,3vw,36px)}
.site .lp-bb{display:flex;flex-direction:column}
.site .lp-bb__t{margin:16px 0 0;font-size:clamp(26px,3vw,34px);font-weight:900;line-height:1.08;letter-spacing:-.03em;color:var(--h);text-wrap:balance}
.site .lp-bb p{margin-top:14px;font-size:17px}
.site .lp-bb .lp-bb__note{margin-top:auto;padding-top:22px;font-size:15.5px;line-height:1.5;font-weight:700;color:var(--h)}
.site .lp-queue .lp-queue__top{display:flex;flex-wrap:wrap;justify-content:space-between;gap:12px;margin:0;font-size:13px;color:var(--faint)}
.site .lp-queue ul{list-style:none;margin:14px 0 0;padding:0}
.site .lp-queue li{display:flex;flex-wrap:wrap;align-items:center;gap:14px;margin:0;padding:14px 0;border-top:1px solid var(--b-border)}
.site .lp-queue__k{flex:none;width:112px;font-size:12px;font-weight:700;line-height:1.4;letter-spacing:.25em;text-transform:uppercase;color:var(--faint)}
.site .lp-queue__v{flex:1;min-width:min(100%,180px);font-size:15.5px;line-height:1.4;color:var(--ink-2)}
.site .lp-queue__ok{flex:none;padding:6px 14px;border:1px solid #ffffff;border-radius:999px;font-size:13px;font-weight:700;color:#ffffff}
.site .lp-queue .lp-queue__note{margin:6px 0 0;padding-top:16px;border-top:1px solid var(--b-border);font-size:15.5px;line-height:1.5;font-weight:700;color:#ffffff}

/* 8 · the process rows */
.site .lp-proc{list-style:none;margin:44px 0 0;padding:0}
.site .lp-proc li{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,200px),1fr));gap:8px 24px;align-items:baseline;margin:0;padding:26px 0;border-top:1px solid var(--b-border)}
.site .lp-proc h3{margin:0;font-size:24px;font-weight:900;line-height:1.2;letter-spacing:-.03em}
.site .lp-proc .lp-num{display:inline;margin-right:18px}
.site .lp-proc p{margin:0;font-size:17px;line-height:1.5;color:var(--ink-2)}

/* 9 · #saat — the forecast: two bars a month (filled = forecast, outline = last year) */
.site .lp-fc{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr));gap:36px;align-items:end;margin-top:16px;padding:clamp(24px,4vw,44px)}
.site .lp-fc__t{margin:14px 0 0;font-size:clamp(26px,3.2vw,38px);font-weight:900;line-height:1.05;letter-spacing:-.03em}
.site .lp-fc p{margin-top:16px}
.site .lp-fc__bars{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:6px}
.site .lp-fc__bars li{position:relative;display:flex;flex-direction:column;min-width:0;margin:0}
.site .lp-fc__pair{display:flex;gap:2px;align-items:flex-end;height:190px}
.site .lp-fc__pair i{flex:1;border-radius:3px 3px 0 0}
.site .lp-fc__pair i:first-child{height:calc(var(--f) * 1.8px);background:#ffffff}
.site .lp-fc__pair i:last-child{height:calc(var(--l) * 1.8px);border:1.5px solid var(--faint);border-bottom:0}
.site .lp-fc__m{margin-top:8px;font-size:12px;line-height:1.3;text-align:center;color:var(--faint)}
.site .lp-fc__dot{height:12px;font-size:9px;line-height:12px;text-align:center;color:#ffffff}
.site .lp-fc .lp-fc__legend{margin:14px 0 0;font-size:13px;line-height:1.5;color:var(--faint)}
@media(max-width:520px){
  .site .lp-fc__bars{gap:3px}
  .site .lp-fc__pair{gap:1px}
  .site .lp-fc__m{font-size:9.5px;letter-spacing:-.03em}
}

/* 10 · #hinnat — Pro is featured by SURFACE (the white card), never by a badge or a word */
/* D-2826: the owner's mock-up: name, who it is for, price, then the lines; the "everything in …"
   line is muted, and the VAT note sits under the cards */
.site .lp-tier .lp-tier__top{margin:0}
.site .lp-tier__name{font-size:26px;font-weight:900;letter-spacing:-.03em;color:var(--h)}
.site .lp-tier .lp-tier__who{margin:8px 0 0;font-size:17px;line-height:1.45;color:var(--b)}
.site .lp-tier .lp-tier__price{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px;margin:26px 0 0;color:var(--h)}
.site .lp-tier__price b{font-size:52px;font-weight:900;line-height:1;letter-spacing:-.04em;color:var(--h)}
.site .lp-tier__price small{font-size:16px;color:var(--m)}
.site .lp-tier__list{margin-top:28px}
.site .lp-tier__list li{padding:11px 0}
.site .lp-tier__list li:last-child{border-bottom:1px solid var(--rule)}
.site .lp-tier__list .lp-tier__plus{color:var(--m)}
.site .lp-undernote{margin:22px 0 0;font-size:16px;color:var(--faint)}

/* 11 · #ukk and the closing call */
.site .lp-faq__q{font-size:21px;font-weight:900;line-height:1.25;letter-spacing:-.02em;color:var(--h)}
.site .lp-close{padding:0 0 clamp(72px,10vw,120px)}
.site .lp-cta{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr));gap:32px;align-items:center;overflow:hidden;padding:clamp(32px,6vw,72px);border:1px solid var(--b-border);border-radius:var(--r-xl);background:var(--b-surface-dark)}
.site .lp-cta .t-h1{margin:0}
.site .lp-cta .lp-sub{max-width:560px}
.site .lp-cta .btn{margin-top:32px}
.site .lp-cta__brain{position:relative;min-height:280px;height:100%}

@media(max-width:860px){
  .site .lp-sec,.site .lp-close{scroll-margin-top:16px}
  .site .lp-strip{padding:18px 20px}
  .site .lp-chain__flow{margin:0 24px}
}
@media(prefers-reduced-motion:reduce){
  .site .landing.js .lp-stage__caps li{transition:none}
}

/* ============================================================================
   33. EDITOR SURFACES — the customer's AI editor + the menu editor (CD-104, D-1431)
   ----------------------------------------------------------------------------
   APPEND-ONLY OVERLAY for app/static/savonai.css. Nothing above §33 is edited.
   Every hue below is drawn from the existing tokens (ink/mut/faint, pri, acc,
   ok/warn/bad, the six kinds). New names exist only where a component needs a
   stable semantic hook: notices (four severities), the diff pair, the drag
   affordance, the marks widget, the translation gap, the preview frame.
   Contrast evidence for every new text/ground pair: see Komponentit.dc.html §D.
   ========================================================================== */

/* ---- 33.0 TOKENS --------------------------------------------------------- */
:root{
  /* notice family — four severities, each = ink + wash + line */
  --n-fail-ink:#8c241c; --n-fail-bg:#fcebea; --n-fail-line:#f3c8c4;   /* build failed · blocked      */
  --n-warn-ink:#7a4d09; --n-warn-bg:#fdf3e2; --n-warn-line:#f1ddb4;   /* value not found · unreached */
  --n-info-ink:#0b4f95; --n-info-bg:#eaf2fb; --n-info-line:#cfe2f7;   /* residual · fyi              */
  --n-note-ink:#3b4160; --n-note-bg:#eef2f8; --n-note-line:#e4e8f1;   /* queued · neutral            */
  /* diff pair (old → new) */
  --diff-old-ink:#8c241c; --diff-old-bg:#fcebea;
  --diff-new-ink:#15623f; --diff-new-bg:#e7f6ee;
  /* drag affordance */
  --drag-ink:#8c92a8; --drag-ink-hover:#5b6178; --drop-line:#0b5cad; --drop-tint:#eaf2fb;
  /* marks widget — three states + raw */
  --mark-on-bg:#12152e;  --mark-on-ink:#ffffff;
  --mark-maybe-ink:#12152e; --mark-maybe-line:#5b6178;
  --mark-off-ink:#5b6178;   --mark-off-line:#e4e8f1;
  --mark-raw-ink:#5a3d00;   --mark-raw-bg:#fff6e6; --mark-raw-line:#ffb020;
  /* armed row (Vahvista) — the review kind */
  --armed:#ffb020; --armed-ink:#8a5a0c; --armed-bg:#fff6e6;
  /* translation gap */
  --gap-ink:#5b6178; --gap-line:#8c92a8;
  /* preview frame chrome */
  --frame-bg:#e9ecf3; --frame-line:#d6dbe7; --frame-ink:#5b6178;
  /* deleted strip */
  --del-ink:#5b6178; --del-bg:#f5f7fc;
  --le-rail:400px;
}
html[data-theme="operator"]{
  --n-fail-ink:#f0837a; --n-fail-bg:#3a1d1a; --n-fail-line:#5a302b;
  --n-warn-ink:#f0b659; --n-warn-bg:#372813; --n-warn-line:#574020;
  --n-info-ink:#8fbaf4; --n-info-bg:#1c2a3a; --n-info-line:#2f496b;
  --n-note-ink:#c6bfb2; --n-note-bg:#332e27; --n-note-line:#39342d;
  --diff-old-ink:#f0837a; --diff-old-bg:#3a1d1a;
  --diff-new-ink:#5cc985; --diff-new-bg:#173322;
  --drag-ink:#a39a8c; --drag-ink-hover:#c6bfb2; --drop-line:#5fa0f2; --drop-tint:#1c2a3a;
  --mark-on-bg:#f7f3ec; --mark-on-ink:#12152e;
  --mark-maybe-ink:#f7f3ec; --mark-maybe-line:#c6bfb2;
  --mark-off-ink:#c6bfb2;   --mark-off-line:#39342d;
  --mark-raw-ink:#ffc56a;   --mark-raw-bg:#3a2c12; --mark-raw-line:#ffc56a;
  --armed:#ffc56a; --armed-ink:#ffc56a; --armed-bg:#3a2c12;
  --gap-ink:#c6bfb2; --gap-line:#a39a8c;
  --frame-bg:#191611; --frame-line:#39342d; --frame-ink:#c6bfb2;
  --del-ink:#c6bfb2; --del-bg:#191611;
}

/* hidden attribute must win over component display values */
.tsp[hidden],.busy[hidden],.actbar__todo[hidden],.pv__gap[hidden],.st[hidden],.tsp__note[hidden],.notice[hidden],.rec[hidden],.clarify[hidden]{display:none!important}

/* ---- 33.1 STATUS CHIP (record + list states) ------------------------------ */
.st{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;letter-spacing:.02em;border-radius:var(--r-pill);padding:4px 10px;line-height:1.2;white-space:nowrap}
.st svg{width:12px;height:12px;flex:none}
.st--planned{background:var(--k-review-tint);color:var(--k-review-ink)}
.st--pending{background:var(--k-build-tint);color:var(--k-build-ink)}
.st--staged{background:var(--k-golive-tint);color:var(--k-golive-ink)}
.st--queued{background:var(--n-note-bg);color:var(--n-note-ink)}
.st--failed{background:var(--n-fail-bg);color:var(--n-fail-ink)}
.st--conflict{background:var(--n-warn-bg);color:var(--n-warn-ink)}
.st--done{background:var(--ok-tint);color:#15623f}
.st--managed{background:var(--ok-tint);color:#15623f;border:1px solid var(--ok-line)}
.st--text{background:var(--bg3);color:var(--mut);border:1px solid var(--line)}
html[data-theme="operator"] .st--done,html[data-theme="operator"] .st--managed{color:var(--ok)}

/* ---- 33.2 NOTICE FAMILY — four severities, one shape ---------------------- */
.notice{display:flex;gap:10px;align-items:flex-start;padding:10px 12px;border-radius:var(--r-sm);border:1px solid;font-size:13.5px;line-height:1.45}
.notice svg{width:16px;height:16px;flex:none;margin-top:2px}
.notice b{font-weight:700}
.notice__act{margin-left:auto;flex:none;align-self:flex-start;white-space:nowrap}
.notice--fail{background:var(--n-fail-bg);border-color:var(--n-fail-line);color:var(--n-fail-ink)}
.notice--warn{background:var(--n-warn-bg);border-color:var(--n-warn-line);color:var(--n-warn-ink)}
.notice--info{background:var(--n-info-bg);border-color:var(--n-info-line);color:var(--n-info-ink)}
.notice--note{background:var(--n-note-bg);border-color:var(--n-note-line);color:var(--n-note-ink)}
/* grouped notices collapse behind a count; the worst severity leads */
.notices{display:flex;flex-direction:column;gap:6px}
.notices__sum{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:700;color:var(--mut);cursor:pointer;list-style:none;padding:6px 0}
.notices__sum::-webkit-details-marker{display:none}
.notices__sum .st{font-weight:700}
.notices__sum svg{width:14px;height:14px;transition:transform .14s}
details[open] .notices__sum svg{transform:rotate(90deg)}

/* ---- 33.3 DIFF PAIR ------------------------------------------------------- */
.diff{display:flex;flex-direction:column;gap:6px;font-size:14px}
.diff__row{display:grid;grid-template-columns:minmax(0,1fr);gap:4px;padding:8px 0;border-top:1px solid var(--line-2)}
.diff__row:first-child{border-top:0;padding-top:0}
.diff__where{font-size:12px;font-weight:700;color:var(--faint);text-transform:uppercase;letter-spacing:.04em}
.diff__pair{display:flex;flex-wrap:wrap;gap:6px 10px;align-items:baseline}
.diff-old{background:var(--diff-old-bg);color:var(--diff-old-ink);text-decoration:line-through;text-decoration-thickness:1.5px;padding:1px 6px;border-radius:4px}
.diff-new{background:var(--diff-new-bg);color:var(--diff-new-ink);font-weight:600;padding:1px 6px;border-radius:4px}
.diff__arrow{color:var(--faint);font-size:13px}

/* ---- 33.4 RECORD CARD (the door — one change = one card) ----------------- */
.rec{position:relative;border:1px solid var(--line);border-left:4px solid var(--k,var(--line));border-radius:var(--r-lg);background:var(--bg);box-shadow:var(--sh-1);padding:var(--s4) var(--s5) var(--s4) calc(var(--s5) - 3px);display:flex;flex-direction:column;gap:var(--s3)}
.rec--planned{--k:var(--k-review)}
.rec--pending{--k:var(--k-build)}
.rec--staged{--k:var(--k-golive);box-shadow:var(--sh-2)}
.rec--queued{--k:var(--faint);background:var(--bg2)}
.rec--failed{--k:var(--bad)}
.rec--conflict{--k:var(--warn)}
.rec__head{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
.rec__title{font-family:var(--font-display);font-size:16px;font-weight:700;color:var(--ink);letter-spacing:-.01em;min-width:0}
.rec__title small{font-family:var(--font);font-weight:600;color:var(--mut);font-size:13px;margin-left:6px}
.rec__meta{margin-left:auto;font-size:12px;color:var(--faint);font-family:var(--mono);white-space:nowrap}
.rec__lines{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:5px;font-size:14px;color:var(--ink)}
.rec__lines li{display:flex;gap:8px;align-items:flex-start}
.rec__lines li::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--k,var(--mut));flex:none;margin-top:8px}
.rec__cost{display:flex;gap:var(--s3);flex-wrap:wrap;align-items:center;font-size:13px;color:var(--mut)}
.rec__cost b{color:var(--ink);font-family:var(--font-display);font-weight:700}
.rec__gate{font-size:13px;color:var(--mut)}
.rec__pages{font-size:13px;color:var(--mut)}
.rec__pages b{color:var(--ink);font-weight:600}
.rec__actions{display:flex;gap:var(--s2);flex-wrap:wrap;align-items:center;margin-top:var(--s1)}
.rec__actions .spread{margin-left:auto}
.rec__body{display:flex;flex-direction:column;gap:var(--s3)}
/* queued / conflict: the card is muted, the sentence is the content */
.rec--queued .rec__title{color:var(--mut)}
.rec--queued .rec__actions .btn{opacity:.6;pointer-events:none}

/* ---- 33.5 CLARIFY CARD — one question, once ------------------------------ */
.clarify{border:1px solid var(--line);border-left:4px solid var(--k-analyse);border-radius:var(--r-lg);background:linear-gradient(90deg,color-mix(in srgb,var(--k-analyse-tint) 70%,var(--bg)),var(--bg) 60%);box-shadow:var(--sh-2);padding:var(--s5) var(--s5) var(--s5) calc(var(--s5) - 3px);display:flex;flex-direction:column;gap:var(--s3)}
.clarify__kind{display:inline-flex;align-items:center;gap:7px;font-size:12px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--k-analyse-ink)}
.clarify__kind svg{width:16px;height:16px;flex:none}
.clarify__q{font-family:var(--font-display);font-size:19px;font-weight:700;letter-spacing:-.015em;line-height:1.25;color:var(--ink)}
.clarify__opts{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}
.clarify__opt{display:block;text-align:left;padding:12px 14px;min-height:48px;border:1.5px solid var(--line);border-radius:var(--r);background:var(--bg);font:inherit;font-weight:600;color:var(--ink);cursor:pointer;transition:.14s}
.clarify__opt:hover{border-color:var(--pri);box-shadow:var(--sh-2);transform:translateY(-1px)}
.clarify__opt.is-selected{border-color:var(--pri);background:var(--pri-tint);box-shadow:0 0 0 3px var(--pri-ring)}
.clarify__free{display:flex;gap:var(--s2);flex-wrap:wrap;align-items:center}
.clarify__free .input{flex:1;min-width:200px}

/* ---- 33.6 BUSY LINE (the honest minute) ---------------------------------- */
.busy{display:flex;flex-direction:column;gap:8px;padding:12px 14px;border:1px solid var(--k-build-tint);background:var(--k-build-tint);border-radius:var(--r-sm);color:var(--k-build-ink);font-size:14px}
.busy__row{display:flex;align-items:center;gap:10px}
.busy__row .spinner{border-color:var(--k-build);border-top-color:transparent}
.busy__row b{font-weight:700}
.busy__t{margin-left:auto;font-family:var(--mono);font-size:12px;color:var(--k-build-ink);opacity:.85}
.busy__bar{height:5px;border-radius:var(--r-pill);background:color-mix(in srgb,var(--k-build) 18%,transparent);overflow:hidden}
.busy__bar i{display:block;height:100%;width:38%;border-radius:inherit;background:var(--k-build);animation:busySlide 1.6s ease-in-out infinite}
@keyframes busySlide{0%{transform:translateX(-100%)}100%{transform:translateX(280%)}}
@media(prefers-reduced-motion:reduce){.busy__bar i{animation:none;width:100%;opacity:.5}}

/* ---- 33.7 LIST ROW (the door's menu list) --------------------------------- */
.listrows{display:flex;flex-direction:column}
.listrow{display:flex;align-items:center;gap:var(--s3);padding:10px 0;border-top:1px solid var(--line-2);min-height:48px}
.listrow:first-child{border-top:0;padding-top:0}
.listrow__txt{flex:1;min-width:0}
.listrow__txt b{display:block;font-size:14.5px;font-weight:700;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.listrow__txt span{font-size:12.5px;color:var(--mut)}
.listrow__act{flex:none;display:flex;gap:6px;align-items:center}

/* ---- 33.8 THE MENU EDITOR SHELL ------------------------------------------ */
.le{container-type:inline-size;container-name:le;display:flex;flex-direction:column;min-height:100%}
.le-head{position:sticky;top:0;z-index:var(--z-sticky);background:var(--bg);border-bottom:1px solid var(--line);padding:10px clamp(16px,3vw,28px);display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;min-height:56px}
.le-head__t{font-family:var(--font-display);font-size:18px;font-weight:800;letter-spacing:-.018em;display:flex;align-items:center;gap:10px;min-width:0}
.le-head__t .st{font-family:var(--font)}
.le-head__right{margin-left:auto;display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap}
.le-body{display:grid;grid-template-columns:minmax(0,1fr) var(--le-rail);gap:var(--s5);align-items:start;padding:var(--s5) clamp(16px,3vw,28px) 120px;max-width:1240px;margin:0 auto;width:100%}
.le-main{display:flex;flex-direction:column;gap:var(--s4);min-width:0}
.le-rail{position:sticky;top:72px;min-width:0}
@container le (max-width: 980px){
  .le-body{grid-template-columns:minmax(0,1fr)}
  .le-rail{position:static}
}

/* the list's own settings: type + intro/price-note per language */
.le-meta{border:1px solid var(--line);border-radius:var(--r-lg);background:var(--bg);box-shadow:var(--sh-1);padding:var(--s4) var(--s5);display:grid;gap:var(--s3);grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}
.le-meta__type{display:flex;flex-direction:column;gap:6px}
.le-meta__type .row{gap:6px}
.type-chip{white-space:nowrap;display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:600;padding:6px 10px;border-radius:var(--r-pill);border:1px solid var(--line);background:var(--bg);color:var(--mut);cursor:pointer;min-height:36px}
.type-chip:hover{border-color:var(--pri-ring);color:var(--ink)}
.type-chip.is-on{background:var(--pri-tint);border-color:transparent;color:var(--pri)}
.type-chip small{font-weight:600;opacity:.8}

/* language header — how many gaps, filter */
.langbar{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;font-size:13px;color:var(--mut)}
.langbar b{color:var(--ink)}
.gap-count{white-space:nowrap;display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;color:var(--gap-ink);border:1px dashed var(--gap-line);border-radius:var(--r-pill);padding:3px 9px;background:var(--bg)}
.gap-count.is-zero{border-style:solid;border-color:var(--ok-line);color:#15623f;background:var(--ok-tint)}

/* ---- 33.9 SECTION + GROUP CONTAINERS ------------------------------------- */
.sec{border:1px solid var(--line);border-radius:var(--r-lg);background:var(--bg);box-shadow:var(--sh-1);overflow:clip}
.sec.is-new{border-style:dashed;border-color:var(--pri-ring);box-shadow:none}
.sec__head{display:flex;align-items:center;gap:8px;padding:10px 12px 10px 8px;background:var(--bg2);border-bottom:1px solid var(--line-2)}
.sec__head .field-h{flex:1 1 180px;min-width:0}
.sec__n{font-size:11px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--faint);padding:0 4px;white-space:nowrap}
.sec__body{padding:6px 12px 12px}
.sec__foot{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;padding:8px 12px 12px;border-top:1px solid var(--line-2)}
.grp{border-left:2px solid var(--line);margin:8px 0 0 4px;padding:0 0 0 8px;border-radius:2px}
.grp.is-new{border-left-style:dashed;border-left-color:var(--pri-ring)}
.grp + .grp{margin-top:10px}
.grp__head{display:flex;align-items:center;gap:8px;padding:4px 0 6px}
.grp__pre{flex:1;min-width:0;display:flex;align-items:center;gap:8px}
.grp__pre .input{font-weight:600}
.grp__pre .lbl{font-size:12px;color:var(--faint);white-space:nowrap}
.grp__rows{display:flex;flex-direction:column}
.grp__add{display:flex;gap:6px;flex-wrap:wrap;padding:6px 0 2px}
.rule-hint{display:flex;align-items:center;gap:8px;color:var(--faint);font-size:11.5px;margin:6px 0 0}
.rule-hint::before,.rule-hint::after{content:"";flex:1;border-top:1px dashed var(--line)}

/* inline heading field: looks like text until focused */
.field-h{display:flex;align-items:center;gap:8px;min-width:0}
.field-h .input{border-color:transparent;background:transparent;font-family:var(--font-display);font-weight:700;font-size:15px;padding:6px 8px;min-height:36px}
.field-h .input:hover{border-color:var(--line);background:var(--bg)}
.field-h .input:focus{border-color:var(--pri);background:var(--bg)}
.field-h .input--en{font-family:var(--font);font-weight:500;color:var(--mut)}

/* ---- 33.10 ROW (line + priced) ------------------------------------------- */
.mrow{display:grid;grid-template-columns:28px minmax(0,1fr) minmax(0,1fr) 88px auto 36px;gap:6px 8px;align-items:start;padding:8px 4px 8px 0;border-top:1px solid var(--line-2);position:relative;border-radius:var(--r-sm)}
.grp__rows .mrow:first-child{border-top:0}
.mrow__cell{display:flex;flex-direction:column;gap:4px;min-width:0}
.mrow__cell .input{padding:8px 10px;min-height:40px;font-size:14.5px}
.mrow__cell .input--desc{font-size:13.5px;color:var(--mut);min-height:36px;padding:6px 10px}
.mrow__price{position:relative}
.mrow__price .input{text-align:right;padding-right:24px;padding-left:8px;font-variant-numeric:tabular-nums;font-weight:600;font-size:14px}
.mrow__price::after{content:"€";position:absolute;right:10px;top:11px;font-size:13px;color:var(--faint);pointer-events:none}
.mrow__lang{display:none;font-size:11px;font-weight:700;color:var(--faint);text-transform:uppercase;letter-spacing:.05em}
.mrow__more{width:36px;min-height:40px;border-radius:var(--r-sm);border:1px solid transparent;background:transparent;color:var(--mut);display:grid;place-items:center;cursor:pointer}
.mrow__more:hover{background:var(--bg3);border-color:var(--line);color:var(--ink)}
.mrow__more svg{width:16px;height:16px}
.mrow--line .input--desc{display:none}
.mrow--line .mrow__price{visibility:hidden}
.mrow__shape{font-size:11px;color:var(--faint);font-weight:600}
/* armed: text changed → marks must be confirmed */
.mrow.is-armed{background:linear-gradient(90deg,var(--armed-bg),transparent 55%);border-top-color:transparent;box-shadow:inset 3px 0 0 var(--armed)}
.mrow.is-armed .marks{box-shadow:0 0 0 2px var(--armed);border-radius:var(--r-sm)}
.mrow__confirm{grid-column:2 / -1;display:flex;align-items:center;gap:10px;flex-wrap:wrap;font-size:13px;color:var(--armed-ink);padding:2px 0 2px}
.mrow__confirm svg{width:15px;height:15px;flex:none}
.mrow__confirm .btn{min-height:36px}
.mrow:not(.is-armed) .mrow__confirm{display:none}
/* dragging */
.mrow.is-dragging{opacity:.35}
.drag-ghost{position:fixed;pointer-events:none;z-index:var(--z-toast);background:var(--bg);border:1px solid var(--pri-ring);border-radius:var(--r-sm);box-shadow:var(--sh-3);padding:8px 12px;font-weight:600;font-size:14px;display:flex;gap:8px;align-items:center;max-width:320px}
.drag-ghost .marks-mini{display:inline-flex;gap:3px}
.drop-line{height:0;border-top:2px solid var(--drop-line);position:relative;margin:-1px 0}
.drop-line::before{content:"";position:absolute;left:-4px;top:-5px;width:8px;height:8px;border-radius:50%;background:var(--drop-line)}
.grp__rows.is-target,.sec.is-target .grp__rows:empty{background:var(--drop-tint);border-radius:var(--r-sm);outline:1.5px dashed var(--drop-line);min-height:44px}
.grp__rows:empty{min-height:44px;display:grid;place-items:center;border:1.5px dashed var(--line);border-radius:var(--r-sm);color:var(--faint);font-size:13px}
.grp__rows:empty::before{content:"Tyhjä ryhmä — vedä rivi tähän tai lisää rivi"}
/* keyboard pick-up */
.mrow.is-picked{box-shadow:0 0 0 2px var(--drop-line),var(--sh-2);background:var(--drop-tint);z-index:2}
/* deleted → a 44px strip with undo */
.mrow-del{display:flex;align-items:center;gap:10px;min-height:44px;padding:0 12px;border-top:1px solid var(--line-2);background:var(--del-bg);color:var(--del-ink);font-size:13.5px;border-radius:var(--r-sm)}
.mrow-del s{opacity:.8}
.mrow-del .btn{margin-left:auto;min-height:32px}

/* drag handle — 44px hit target, 28px visual */
.handle{width:28px;min-height:40px;display:grid;place-items:center;color:var(--drag-ink);cursor:grab;border-radius:var(--r-xs);touch-action:none;border:0;background:transparent;padding:0}
.handle:hover{color:var(--drag-ink-hover);background:var(--bg3)}
.handle:active{cursor:grabbing}
.handle svg{width:14px;height:14px}
.handle--sec{width:32px;min-height:36px}

/* ---- 33.11 TRANSLATION GAP ------------------------------------------------ */
.input.is-gap{border-style:dashed;border-color:var(--gap-line);background:transparent}
.input.is-gap::placeholder{color:var(--gap-ink);font-style:italic}
.le.show-gaps-only .mrow:not(.has-gap){display:none}
.le.show-gaps-only .grp:not(:has(.has-gap)){display:none}
.le.show-gaps-only .sec:not(:has(.has-gap)){display:none}

/* ---- 33.12 MARKS WIDGET — L / G / M three-state + raw --------------------- */
.marks{display:inline-flex;align-items:center;gap:4px;padding:2px}
.mark{display:inline-flex;flex-direction:column;align-items:center;justify-content:center;gap:0;width:44px;height:40px;border-radius:var(--r-xs);border:1.5px solid var(--mark-off-line);background:var(--bg);color:var(--mark-off-ink);font:inherit;cursor:pointer;padding:0;transition:.14s;line-height:1}
.mark__l{font-family:var(--font-display);font-weight:800;font-size:15px}
.mark__s{font-size:9.5px;font-weight:700;letter-spacing:.02em;margin-top:2px;text-transform:lowercase}
.mark[data-state="off"] .mark__s{opacity:0}
.mark[data-state="off"] .mark__l{text-decoration:line-through;text-decoration-thickness:1.5px;opacity:.7}
.mark[data-state="on"]{background:var(--mark-on-bg);border-color:var(--mark-on-bg);color:var(--mark-on-ink)}
.mark[data-state="maybe"]{border-style:dashed;border-color:var(--mark-maybe-line);color:var(--mark-maybe-ink)}
.mark:hover{border-color:var(--mark-maybe-line)}
.mark:focus-visible{box-shadow:var(--ring);outline:none}
.marks__raw{display:inline-flex;align-items:center;gap:6px;height:40px;padding:0 10px;border-radius:var(--r-xs);background:var(--mark-raw-bg);border:1.5px solid var(--mark-raw-line);color:var(--mark-raw-ink);font-size:13px;font-weight:600;max-width:190px;cursor:pointer}
.marks__raw svg{width:13px;height:13px;flex:none}
.marks__raw span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.marks--raw .mark{display:none}
.marks:not(.marks--raw) .marks__raw{display:none}
.marks-mini b{display:inline-grid;place-items:center;width:18px;height:18px;border-radius:4px;background:var(--mark-on-bg);color:var(--mark-on-ink);font-size:11px;font-weight:800}
.marks-mini i{display:inline-grid;place-items:center;height:18px;padding:0 4px;border-radius:4px;border:1px dashed var(--mark-maybe-line);color:var(--mark-maybe-ink);font-size:10px;font-weight:700;font-style:normal}
/* the legend lives where the marks live: one per section foot */
.legend{font-size:12.5px;color:var(--mut);display:flex;gap:4px 12px;flex-wrap:wrap}
.legend span{white-space:nowrap}
.legend b{color:var(--ink);font-weight:800;font-family:var(--font-display)}

/* ---- 33.13 ACTION BAR (sticky, the save flow) ----------------------------- */
.actbar{position:sticky;bottom:0;z-index:var(--z-sticky);background:color-mix(in srgb,var(--bg) 92%,transparent);backdrop-filter:blur(8px);border-top:1px solid var(--line);padding:10px clamp(16px,3vw,28px);display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
.actbar__sum{display:flex;align-items:center;gap:10px;font-size:13.5px;color:var(--mut);min-width:0;flex:1}
.actbar__sum b{color:var(--ink);font-weight:700}
.actbar__dot{width:8px;height:8px;border-radius:50%;background:var(--faint);flex:none}
.actbar.is-dirty .actbar__dot{background:var(--acc)}
.actbar__draft{font-size:12px;color:var(--faint);font-family:var(--mono)}
.actbar__btns{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap;margin-left:auto}
.actbar .btn--primary{min-height:44px}
.actbar__todo{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;font-weight:700;color:var(--armed-ink);background:var(--armed-bg);border-radius:var(--r-pill);padding:4px 10px;cursor:pointer;border:0;font-family:inherit}
.actbar__todo svg{width:12px;height:12px}
.seg{display:inline-flex;border:1px solid var(--line);border-radius:var(--r-pill);overflow:hidden;background:var(--bg)}
.seg button{border:0;background:transparent;font:inherit;font-size:13px;font-weight:700;color:var(--mut);padding:0 14px;min-height:40px;cursor:pointer}
.seg button.is-on{background:var(--pri-tint);color:var(--pri)}
.seg--sm button{min-height:30px;padding:0 10px;font-size:12px}

/* ---- 33.14 PREVIEW FRAME (the site's own look, untouched) ----------------- */
.pv{border:1px solid var(--frame-line);border-radius:var(--r-lg);background:var(--frame-bg);box-shadow:var(--sh-1);display:flex;flex-direction:column;overflow:hidden;max-height:calc(100vh - 96px)}
.pv__bar{display:flex;align-items:center;gap:8px;padding:8px 10px 8px 12px;border-bottom:1px solid var(--frame-line);color:var(--frame-ink);font-size:12.5px;font-weight:700}
.pv__bar .dots{display:inline-flex;gap:4px}
.pv__bar .dots i{width:8px;height:8px;border-radius:50%;background:var(--frame-line)}
.pv__url{flex:1;min-width:0;background:var(--bg);border:1px solid var(--frame-line);border-radius:var(--r-pill);padding:4px 10px;font-family:var(--mono);font-weight:500;font-size:11.5px;color:var(--frame-ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pv__status{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;font-weight:700;color:var(--frame-ink);white-space:nowrap}
.pv__status i{width:7px;height:7px;border-radius:50%;background:var(--ok)}
.pv.is-updating .pv__status i{background:var(--acc);animation:pvPulse .9s ease-in-out infinite}
@keyframes pvPulse{50%{opacity:.35}}
@media(prefers-reduced-motion:reduce){.pv.is-updating .pv__status i{animation:none}}
.pv__body{flex:1;overflow:auto;background:var(--frame-bg);padding:14px;display:flex;justify-content:center}
.pv__site{background:#fff;width:100%;box-shadow:0 1px 2px rgba(18,21,46,.08);border-radius:6px;overflow:hidden;transition:width .2s}
.pv.is-phone .pv__site{width:390px;max-width:100%}
.pv__foot{display:flex;align-items:center;gap:8px;padding:8px 12px;border-top:1px solid var(--frame-line);background:var(--bg);font-size:13px;color:var(--mut);flex-wrap:wrap}
.pv__foot b{color:var(--ink);font-weight:700}
.pv__style{white-space:nowrap;display:inline-flex;align-items:center;gap:6px;font-family:var(--mono);font-size:12px;color:var(--ink);background:var(--bg2);border:1px solid var(--line);border-radius:var(--r-xs);padding:3px 8px}
.pv__gap{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--gap-ink);border:1px dashed var(--gap-line);border-radius:var(--r-pill);padding:2px 8px}
/* phone: the preview is a bottom sheet */
.pv-sheet{position:fixed;left:0;right:0;bottom:0;z-index:var(--z-modal);background:var(--bg);border-radius:var(--r-xl) var(--r-xl) 0 0;box-shadow:var(--sh-3);max-height:82vh;display:flex;flex-direction:column;transform:translateY(100%);transition:transform .22s ease}
.pv-sheet.is-open{transform:none}
.pv-sheet__grab{width:40px;height:4px;border-radius:2px;background:var(--line);margin:8px auto 0}
@media(prefers-reduced-motion:reduce){.pv-sheet{transition:none}}

/* type-style picker — a site-wide decision, previewed like anything else */
.tsp{border:1px solid var(--line);border-radius:var(--r-lg);background:var(--bg);box-shadow:var(--sh-3);padding:var(--s4);display:flex;flex-direction:column;gap:var(--s3);width:min(420px,100%)}
.tsp__t{font-family:var(--font-display);font-weight:700;font-size:15px}
.tsp__t small{display:block;font-family:var(--font);font-weight:500;color:var(--mut);font-size:13px;margin-top:2px}
.tsp__lbl{font-size:11px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--faint)}
.tsp__grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
.tsp__grid--3{grid-template-columns:repeat(3,1fr)}
.tsp__opt{display:flex;flex-direction:column;gap:6px;align-items:stretch;padding:8px;border:1.5px solid var(--line);border-radius:var(--r-sm);background:var(--bg);cursor:pointer;font:inherit;color:var(--mut);font-size:12px;font-weight:700;text-align:center;min-height:44px}
.tsp__opt:hover{border-color:var(--pri-ring)}
.tsp__opt.is-on{border-color:var(--pri);background:var(--pri-tint);color:var(--pri);box-shadow:0 0 0 3px var(--pri-ring)}
.tsp__opt.is-cur::after{content:"nyt käytössä";font-size:10px;font-weight:700;color:var(--faint)}
.tsp__wire{height:34px;border-radius:4px;background:var(--bg2);border:1px solid var(--line);position:relative;overflow:hidden}
.tsp__wire i{position:absolute;height:2px;background:var(--mut);border-radius:1px;opacity:.7}
.tsp__note{font-size:13px;color:var(--mut);line-height:1.45}
.tsp__note b{color:var(--ink)}
.tsp__acts{display:flex;gap:8px;flex-wrap:wrap;align-items:center}

/* ---- 33.15 UNDO STRIP + TOAST ------------------------------------------- */
.toast{position:fixed;left:50%;bottom:88px;transform:translateX(-50%);z-index:var(--z-toast);display:flex;align-items:center;gap:12px;padding:10px 12px 10px 16px;background:var(--ink);color:var(--bg);border-radius:var(--r);box-shadow:var(--sh-3);font-size:14px;font-weight:600;max-width:min(480px,92vw)}
.toast .btn{min-height:32px;background:transparent;color:#ffc56a;border-color:transparent;padding:0 8px}
.toast .btn:hover{background:rgba(255,255,255,.1)}
html[data-theme="operator"] .toast{background:var(--bg3);color:var(--ink)}
.toast--ok{background:#15623f;color:#fff}

/* ---- 33.16 OFFER (tee hallittu lista) ------------------------------------- */
.offer-sec{border:1px solid var(--line);border-radius:var(--r-lg);background:var(--bg);box-shadow:var(--sh-1);overflow:hidden}
.offer-sec__head{display:flex;align-items:center;gap:10px;padding:12px 16px;border-bottom:1px solid var(--line-2);background:var(--bg2)}
.offer-sec__head .check{font-weight:700;font-size:15px}
.offer-sec__head .n{margin-left:auto;font-size:12.5px;color:var(--mut)}
.offer-sec.is-off .offer-row{opacity:.45}
.offer-row{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:10px;padding:10px 16px;border-top:1px solid var(--line-2);font-size:14px;align-items:center}
.offer-row:first-of-type{border-top:0}
.offer-row__fi{color:var(--ink)}
.offer-row__en{display:flex;align-items:center;gap:8px;min-width:0}
.offer-row__en .txt{flex:1;min-width:0;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.offer-row__en.is-off .txt{text-decoration:line-through;color:var(--faint)}
.offer-row__en .gaptxt{font-style:italic;color:var(--gap-ink);font-size:13px}
.offer-cols{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:10px;padding:6px 16px;font-size:11px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--faint)}
.offer-cols span:last-child{display:flex;align-items:center;gap:8px}
.reason{font-size:13px;color:var(--mut);display:inline-flex;gap:6px;align-items:flex-start;max-width:52ch;line-height:1.45}
.reason svg{width:15px;height:15px;flex:none;margin-top:2px;color:var(--warn)}

/* ---- 33.17 DOCUMENT EDITOR ---------------------------------------------- */
.doc-ta{width:100%;min-height:60vh;font:14.5px/1.7 var(--mono);padding:var(--s5);border:1px solid var(--line);border-radius:var(--r-lg);background:var(--bg);color:var(--ink);resize:vertical;tab-size:2;max-width:78ch}
.doc-ta:focus{outline:none;border-color:var(--pri);box-shadow:var(--ring)}

/* ---- 33.18 PHONE (container query) — the row, the marks, the action bar --- */
@container le (max-width: 640px){
  .le-head{padding:8px 12px;min-height:52px}
  .le-head__t{font-size:16px}
  .le-body{padding:var(--s4) 12px 140px}
  .le-meta{grid-template-columns:1fr;padding:var(--s4)}
  .sec__head{flex-wrap:wrap;padding:8px 10px 8px 6px}
  .sec__head .field-h{flex:1 1 100%}
  .sec__head .field-h--en{order:5}
  .sec__body{padding:4px 8px 10px}
  .mrow{grid-template-columns:28px minmax(0,1fr) 36px;gap:6px;padding:10px 0 10px}
  .mrow__cell--fi{grid-column:2}
  .mrow__cell--en{grid-column:2}
  .mrow__lang{display:block;margin:2px 0 -2px 10px}
  .mrow__price{grid-column:2;width:110px}
  .mrow__marks{grid-column:2;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
  .mrow__more{grid-row:1;grid-column:3}
  .mrow--line .mrow__price{display:none}
  .mrow__confirm{grid-column:2 / -1}
  .mrow.is-armed{background:var(--armed-bg)}
  .actbar{padding:8px 12px;gap:8px}
  .actbar__sum{flex:1 1 100%;font-size:13px}
  .actbar__btns{margin-left:0;width:100%}
  .actbar__btns .btn--primary{flex:1;min-width:0;white-space:normal;line-height:1.2;text-align:center;padding:8px 12px}
  .actbar__draft{display:none}
  .langbar{font-size:12.5px}
}

/* =========================================================================
   34. OFFER SURFACE — the responsive rule §33 does not contain
   `ui-redesign.md` §v5.3 · `menu-entity.md` §5.5.5 · P-C (D-1438)

   ⛔ THIS SECTION IS OURS, and that is why it is not inside §33. §33 is a VERBATIM copy of the
   Claude Design hand-back (`docs/design/editor-handoff/savonai-editor.css`) and a test compares
   it byte for byte; a rule added inside it would unfalsify that comparison AND attribute our
   rule to the designer. A gap in someone else's bytes is recorded as ours, never patched into
   theirs.

   MEASURED 2026-09-11: the hand-back declares every `offer-*` class the page needs and contains
   NO `@media` and NO `@container` block mentioning `offer`. Its C1 phone artboard nevertheless
   shows the languages stacked — with per-element inline `style="grid-template-columns:1fr"`,
   which is artboard scaffolding that nothing carries into production. So the overlay as shipped
   renders two 50%-width columns on a 390px screen, with a checkbox beside a truncated dish name.

   ⛔⛔ A MEDIA QUERY, and NOT `container-type`. §33.18 queries `@container le` because `.le` is a
   real container — the editor sits beside a rail that appears and disappears, so its width is
   not the window's. The offer IS the page column. Declaring `container-type` on a wrapper that
   exists only to be queried is precisely how D-1437's worst defect was built: `.door-work`
   declared one and then queried `@container` for its OWN selector, which never matches, so the
   phone's main column computed to 0px and the cards rendered 50px wide. An element is never its
   own container-query target. Nothing below declares `container-type`, and a test asserts that.

   Every class named here is one §33 already declares — this section adjusts the layout of
   existing components and introduces none of its own.
   ========================================================================= */

/* ---- 34.1 the columns generalise past one harvest language --------------- */
.offer-sec{--ocols:1}
.offer-row,.offer-cols{grid-template-columns:minmax(0,1fr) repeat(var(--ocols,1),minmax(0,1fr))}

/* ---- 34.2 `hidden` must win here too ------------------------------------
   ⛔ §33 rule 6's trap, one section further on. The offer renders BOTH Finnish sentences for a
   row and a section — «käytetään»/«jää aukoksi», the count/«ei mukaan» — and the script toggles
   `hidden` between them, so that every word stays server-side (§5.4.5). But `.st` and `.gaptxt`
   set `display:inline-flex`/`inline`, which OVERRIDES the UA stylesheet's `[hidden]` rule: both
   sentences would render at once, and no Python test can see it. §33's own rule names only the
   classes it knew about. */
.offer-sec [hidden],.offer-row [hidden]{display:none!important}

/* ---- 34.3 the phone: one column, and a real touch target ---------------- */
@media (max-width: 640px){
  .offer-row,.offer-cols{grid-template-columns:minmax(0,1fr)}
  .offer-cols span:not(:first-child){display:none}
  .offer-row__en.check{min-height:44px}
  .offer-sec__head{flex-wrap:wrap}
  .offer-sec__head .n{margin-left:0;flex-basis:100%}
}

/* ---- 34.4 the two bulk controls (P-E, D-1443) -----------------------------
   `menu-editor.md` §13.2 / §13.3. Both sit in a section's foot, both edit the form the customer
   then submits themselves. ⛔ In §34 (ours) and not in §33, whose value is that it is verbatim.
   ⛔ No `container-type`: an element is never its own query target (D-1437). */
.pricebump,.markbulk{display:flex;flex-wrap:wrap;gap:8px;align-items:center;flex-basis:100%;
  margin-top:8px;padding:10px 12px;border:1px solid var(--line);border-radius:var(--r-md);
  background:var(--bg2);font-size:13px}
.pricebump .input,.markbulk select{font:inherit;padding:4px 8px;border:1px solid var(--line);
  border-radius:var(--r-sm);background:var(--bg);color:var(--ink)}
.markbulk__l{display:inline-flex;align-items:center;gap:5px}
.markbulk__l b{display:inline-grid;place-items:center;width:20px;height:20px;border-radius:4px;
  background:var(--mark-on-bg);color:var(--mark-on-ink);font-size:11px;font-weight:800}

/* the row picker appears only while a section is picking, so the row keeps its shape otherwise */
.mrow__pick{display:none;align-items:center;padding-right:2px}
.sec.is-picking .mrow__pick{display:inline-flex}
.sec.is-picking .mrow{outline:1px dashed var(--line-2);outline-offset:2px}
.mrow__pick input{width:18px;height:18px;accent-color:var(--pri);margin:0}

@media (max-width: 640px){
  .pricebump,.markbulk{gap:6px}
  .pricebump .btn,.markbulk .btn{min-height:44px}
  .mrow__pick input{width:22px;height:22px}
}

/* ---- 34.5 the STALE record card (D-1475) ----------------------------------
   ⛔ It belongs HERE, not in §33.4 beside the other `.rec--*` rules, and the overlay tests are
   what said so: §33 is appended VERBATIM from the hand-back and must stand contiguous, so a
   rule of OURS inserted into it breaks the one property that makes the hand-back re-appliable.
   §34 is ours; this is the only honest home for it.

   A stale candidate is staged, but the knowledge base moved under it: warn-keyed like a
   conflict (both mean "this needs you before anything can publish") and muted like the queue,
   because the preview it shows is no longer what would ship. */
.rec--stale{--k:var(--warn);background:var(--bg2)}

/* ---- 34.6 the STAGING record card (D-1621) --------------------------------
   The machine is on it: build-keyed like `pending` (it IS the preview being built) and muted like
   the queue, because there is nothing on it to press. Same home as 34.5, for the same reason. */
.rec--staging{--k:var(--k-build);background:var(--bg2)}
.rec--held{--k:var(--warn)}
.st--held{background:var(--n-warn-bg);color:var(--n-warn-ink)}
.rec--deciding{--k:var(--k-build);background:var(--bg2)}
.rec--deciding .rec__title{color:var(--mut)}
.st--deciding{background:var(--k-build-tint);color:var(--k-build-ink)}
.rec--staging .rec__title{color:var(--mut)}
.st--staging{background:var(--k-build-tint);color:var(--k-build-ink)}

/* ---- 34.7 the AI's menu proposal (D-1724, `menu-proposals.md` §6) ---------
   The editor opened ON a proposal: the panel above the form, and a row the proposal added,
   changed or moved carries the analyse hue on its edge and a word beside its language label.
   An ARMED row keeps the armed edge — the marks question outranks "the AI touched this". */
.mrow--ai{box-shadow:inset 3px 0 0 var(--k-analyse)}
.mrow--ai.is-armed{box-shadow:inset 3px 0 0 var(--armed)}
.ai-badge{display:inline-block;margin-left:6px;font-size:11px;font-weight:700;letter-spacing:.02em;color:var(--k-analyse-ink);background:var(--k-analyse-tint);border-radius:var(--r-pill);padding:1px 8px;text-transform:none}
/* D-1747 — a value the translator made: dashed until a person saves their own */
.input[data-mt="1"]{border-style:dashed}
.le-prop{border:1px solid var(--line);border-left:4px solid var(--k-analyse);border-radius:var(--r-sm);padding:14px 16px;margin:0 0 16px;display:grid;gap:8px;background:var(--k-analyse-tint)}
.le-prop ul{margin:0;padding-left:18px;display:grid;gap:2px}
.le-prop details summary{cursor:pointer;font-weight:700}

/* ---- 34.8 the offer's action bar on a phone (D-1828 addendum) -------------
   ⛔ §33.18 gives `.actbar` its phone layout inside `@container le` — and the offer is the one
   `.actbar` that is NOT inside `.le` (`paivita_lista.html` renders it in the `.jp` shell, the
   editor in `.le`). So the designer's phone rules never reached it: MEASURED 2026-09-27 at 320px
   the summary was a 32px column whose words ran over «Peruuta»; at 375 a 7-line, 87px column.
   These are §33.18's four `.actbar` declarations, verbatim, keyed on the shell instead of the
   container — a test holds them equal, so a change to the designer's rule is a change here. */
@media (max-width: 640px){
  .jp .actbar{padding:8px 12px;gap:8px}
  .jp .actbar__sum{flex:1 1 100%;font-size:13px}
  .jp .actbar__btns{margin-left:0;width:100%}
  .jp .actbar__btns .btn--primary{flex:1;min-width:0;white-space:normal;line-height:1.2;text-align:center;padding:8px 12px}
}

/* ---- CD-126 D-1994/D-1995 — «Hinnasto ja tuotteet» (`price-list-editor.md` §4.10, §6.3) -----------
   The price-list editor's row cards, and the doc editor in PRODUCT words: a products doc with no
   marked row has no marks cell, no «Vahvista merkinnät» and no legend — rows the script adds too.
   At the END of the sheet, deliberately: the phone rules below must win (a media query adds no
   specificity). */
.le[data-products="1"] .mrow__marks,.le[data-products="1"] .mrow__confirm,
.le[data-products="1"] .sec__foot .legend{display:none}
.pe-rows{display:grid;gap:14px;margin:14px 0}
.pe-row{display:grid;grid-template-columns:96px minmax(0,1fr);gap:14px;border:1px solid var(--line);
 border-radius:12px;padding:14px;background:var(--surface,#fff)}
.pe-row.is-del{opacity:.45}
.pe-row.is-sug{outline:2px solid var(--accent,#2f6fed);outline-offset:2px}
.pe-thumb{width:96px;height:96px;border:1px solid var(--line-2,#e5e7eb);border-radius:8px;display:flex;
 align-items:center;justify-content:center;background:#fafafa;overflow:hidden}
.pe-thumb img{max-width:100%;max-height:100%;object-fit:contain}
.pe-thumb small{font-size:11px;color:var(--mut,#6b7280);text-align:center;padding:4px}
.pe-fields{display:grid;gap:8px;min-width:0}
.pe-line{display:grid;grid-template-columns:minmax(0,1fr) 8em 7em;gap:8px}
.pe-line input,.pe-fields textarea,.pe-fields select{width:100%}
.pe-meta{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.pe-chip{font-size:12px;padding:2px 8px;border-radius:999px;background:var(--bg2,#f3f4f6)}
.pe-tools{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.pe-pic-label{font-size:12px;color:var(--mut,#6b7280)}
.pe-grid{display:grid;grid-template-columns:repeat(auto-fill,72px);gap:8px;max-height:60vh;overflow:auto}
.pe-grid button{border:1px solid var(--line);border-radius:6px;padding:0;background:#fff;cursor:pointer}
.pe-grid img{width:70px;height:54px;object-fit:contain;display:block}
.pe-grid span{display:block;font-size:10px;max-width:70px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
dialog.pe-dialog{max-width:min(720px,94vw);border:1px solid var(--line);border-radius:12px;padding:16px}
@media(max-width:560px){.pe-row{grid-template-columns:72px minmax(0,1fr);padding:10px}
 .pe-thumb{width:72px;height:72px}.pe-line{grid-template-columns:1fr 1fr}
 .pe-line .pe-name{grid-column:1/-1}.pe-grid{grid-template-columns:repeat(3,1fr)}}

/* =========================================================================
   35. APP SHELL AT PHONE WIDTH — the rules the journey shell does not contain
   `ui-redesign.md` §v5.5 · `site-update-door.md` §1.1 · D-1828

   ⛔ THIS SECTION IS OURS, for the same reason §34 is. `.jp-top` / `.jp-switch` / `.jp-top__right`
   live in the base sheet's "30. JOURNEY PAGE SHELL" block, which is a VERBATIM copy of the design
   system's `components.css` (docs/design/editor-handoff/_ds/…/css/components.css) and sits above
   two append-only overlays whose rule is "nothing above this line is edited". So the fix is
   appended here and names the classes it adjusts; it introduces no component of its own.

   MEASURED 2026-09-27, headless Chromium at 375px, the real templates through the app: the bar's
   right edge was 451px on the door, the history and the list offer, 599px on the journey and
   686px on a journey whose report link is showing — the whole page scrolled sideways on a phone.
   Two causes, and both need fixing:
     1. `.jp-switch` is a flex item with the default `min-width:auto`, and its name is `nowrap`, so
        it can never be narrower than the name (capped at 230px). Nothing else in the bar shrinks.
     2. Even at ZERO width for the name the journey does not fit: brand 126 + «Lisäasetukset» 140
        + «Ulos» 55 + gaps is already 354px of a 343px row, and «Raportit» adds 92 more. So the
        phone bar has to carry less, not only squeeze harder.

   ⛔ A MEDIA query, and no `container-type` — the bar is the page's own width (§34's reasoning,
   D-1437). 640px is §34's phone breakpoint; at 641px the fullest bar still leaves the name 144px.
   ========================================================================= */

/* ---- 35.1 the project name gives way — at every width ------------------
   The name already declares its ellipsis (`.jp-switch b`); only its box could not shrink. Between
   640px and the ~732px the fullest bar needs, this is the rule doing the work. */
.jp-switch{min-width:0}

/* ---- 35.2 the phone: the mark and the icons carry the bar --------------
   The wordmark collapses to the mark and a top-bar button that HAS an icon collapses to the icon.
   Both keep their accessible name — `.brand` carries `aria-label="SavonAI"`, and the button's label
   is still its text content, only set at zero size (never `display:none`, which would remove it).
   `gap:0` because a zero-size text run is still a flex item and would keep the gap beside it.
   «Raportit» and «Ulos» have no icon and keep their words. */
@media (max-width: 640px){
  .jp-top .brand{gap:0;font-size:0}
  .jp-top__right .btn:has(> .ico){gap:0;font-size:0;padding:0;width:32px}
}

/* ---- 35.3 a receipt on a shell page wraps rather than pushing ----------
   The door's «Sivusto julkaistu» receipt prints the site's whole URL as its link, and
   `.receipt__link{flex:none}` could not shrink: 391px at 375 with a 45-character address, with the
   top bar already fixed. The journey's «Julkinen osoite» receipt prints `live_url` in a `<code>`
   inside the text: 324px at 320. Every other receipt link is one word («näytä», «avaa ↗»), so this
   changes nothing else — a row wraps, and a URL breaks, only where it would otherwise overflow. */
@media (max-width: 640px){
  .jp .receipt{flex-wrap:wrap}
  .jp .receipt__txt{overflow-wrap:anywhere}
  .jp .receipt__link{flex-shrink:1;min-width:0;overflow-wrap:anywhere}
}

/* ---- 35.4 a stage heading breaks a token rather than pushing (D-1828 addendum)
   The offer's intro prints the list's entity path in a `<code>` — `entities/menu/<slug>.md`, one
   unbreakable token, because a browser does not break at `/`. MEASURED 2026-09-27: 328px at 320
   with the real slug; with a longer slug 490px even at 414; and one long compound in the `<h1>`
   («Isänpäivänjuhlabrunssivarauslista») 409px at 375. `break-word` (not `anywhere`) because it
   changes no min-content size: it acts only on a token that would otherwise overflow its line,
   which is why it can apply at every width and leave every page that fits pixel-identical. */
.jp-stagehead h1,.jp-stagehead p{overflow-wrap:break-word}

/* =========================================================================
   36. «VERKKOSIVU»'S EDITORS INSIDE THE APP SHELL (CD-127 S1, D-2004 — customer-dashboard.md §4.1, §6.1)
   The list editor and the price-list editor (`.le`) used to be whole pages of their own, with
   their head sticky at `top:0`. Inside `.jp` the shell's top bar is sticky at `top:0` too, and two
   bars stuck to one line hide each other. MEASURED 2026-10-01 at 1440: the bar is 57.1 px — its
   height is whatever its tallest child makes it — so on these pages it gets an exact one, and the
   editor's head (and the preview rail, 16 px under the head as before) stick below it.
   ≤ 760 px the top bar scrolls away instead: the head already carries «← Verkkosivu», the
   dashboard's bottom bar is the way home, and a phone cannot spare two sticky bars over a form.
   ========================================================================= */
.jp:has(> .le) > .jp-top{height:58px}
.jp > .le .le-head{top:58px}
.jp > .le .le-rail{top:130px}
@media (max-width: 760px){
  .jp:has(> .le) > .jp-top{position:relative}
  .jp > .le .le-head{top:0}
}

/* =========================================================================
   37. «SISÄLTÖ» ON «VERKKOSIVUT» (CD-127 S4, D-2036 — site-update-door.md §1.16)
   One card per content kind the client has, right under the AI box, each with its next items and two
   buttons written as words. OURS, for §34's reason. The pending pill reuses §33.2's `.notice` and the
   chips §33.1's `.st`; these rules arrange them and add nothing else. ≤ 760 px the lead paragraph of the
   stage head gives way (`.door-lead`), so that on a 375 px phone the page name, the pill, the AI box and
   the first two cards with both buttons sit above the fold (measured in Chromium).
   ========================================================================= */
.door-pill{align-items:center}
.ck{display:flex;flex-direction:column;gap:10px}
.ck-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:12px}
.ck-card{background:var(--bg);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--sh-1);
  padding:12px 14px;display:flex;flex-direction:column;gap:8px;min-width:0}
.ck-card__head{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
.ck-card__head h3{font-size:15px;font-weight:700;margin:0}
.ck-card__sub{font-size:12.5px;color:var(--mut);white-space:nowrap}
.ck-rows{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px}
.ck-row{display:flex;align-items:center;gap:8px;min-width:0;font-size:13.5px;min-height:30px}
.ck-row__name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ck-row__verb{flex:none;min-height:28px;padding:0 8px}
.ck-note{font-size:12.5px;color:var(--mut);margin:0}
.ck-acts{display:flex;gap:8px;margin-top:auto}
.ck-acts .btn{flex:1 1 0;min-width:0}
/* ≤ 760 px — the fold (owner-UX review M4, measured at 375 × 812 with the 56 px bottom bar): the page
   name and «Muokkaa sivua suoraan» share one row, the AI box keeps every control but drops its kind chip
   and takes a one-line label, and each card shows its first row and its two buttons (the review's phone
   sketch: «Ruokalistat · …» + two words). The rest of a card is one tap away («Kaikki … ›»). */
@media (max-width: 760px){
  .ck-grid{grid-template-columns:minmax(0,1fr);gap:10px}
  .ck-card{padding:8px 12px;gap:4px}
  .ck-rows .ck-row:nth-child(n+2){display:none}
  .jp-stagehead .door-lead{display:none}
  .jp-main:has(.door-head){padding-top:var(--s4)}
  .jp-stagehead:has(.door-head){gap:8px!important;margin-bottom:var(--s3)}   /* its inline 24 px gap */
  .jp-stagehead .door-head{display:flex;align-items:center;justify-content:space-between;gap:8px 12px;
    flex-wrap:wrap}
  .jp-stagehead .door-head > p{margin:0!important}
  .door-work .next-action{padding:var(--s4) var(--s4) var(--s4) calc(var(--s4) - 3px);gap:var(--s2)}
  .door-work .next-action .next-action__kind{display:none}
  .door-work .next-action .next-action__label{font-size:18px}
  .door-work .next-action .cost-note{display:none}   /* the preview promise: the record card makes it */
  .door-work > .stack{gap:12px!important}      /* the column's inline 20 px: the one property overridden */
  .door-pill{padding:6px 10px}
  .door-pill > span{flex:1 1 auto;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .door-pill .btn{min-height:30px}
  .door-work .next-action label.select{width:auto;flex:1 1 150px;min-width:0}
  .ck .t-h2{font-size:19px}
  .ck-note{display:none}                        /* the event form says it too (`F.no_hub`) */
  /* the «Sivusto julkaistu» receipt on ONE line: the tick, the words, the site's address cut to fit
     (§35.3 lets receipts wrap, which on the door cost four lines above the AI box) */
  .jp-stagehead .receipt{flex-wrap:nowrap;padding:6px 10px;min-height:0;width:100%}
  .jp-stagehead .receipt__txt{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:0 1 auto}
  .jp-stagehead .receipt__txt b{display:none}
  .jp-stagehead .receipt__link{flex:1 1 auto;min-width:0;white-space:nowrap;overflow:hidden;
    text-overflow:ellipsis;overflow-wrap:normal;text-align:right}
}

/* =========================================================================
   38. «USEIN KYSYTYT» — THE OWNER'S FAQ EDITOR (CD-127 S6b, D-2043 — content-items.md §8)
   §33.8's editor shell (`.le`), §33.13's save bar and §37's rows; these rules lay out a question row
   (phone first: one column, the counters beside their labels), the «⋯» row menu, the translation
   disclosure and the preview frame (desktop width, or a 390 px phone). Nothing here scrolls sideways.
   ========================================================================= */
.fq-rows{display:flex;flex-direction:column;gap:12px}
.fq-row{border:1px solid var(--line);border-radius:var(--r);background:var(--bg);padding:10px 12px 12px;
  display:flex;flex-direction:column;gap:8px;min-width:0;position:relative;margin:0}
.fq-row--new{border-style:dashed}
.fq-row__head{font-size:13.5px;padding:0 4px;display:flex;align-items:center;gap:8px}
.fq-field{display:flex;flex-direction:column;gap:4px;min-width:0}
.fq-field__l{display:flex;justify-content:space-between;gap:8px;font-size:12.5px;color:var(--mut)}
.fq-field .input{width:100%;box-sizing:border-box}
.fq-count{font-variant-numeric:tabular-nums;white-space:nowrap}
.fq-tr summary{cursor:pointer;color:var(--mut)}
.fq-tr .input{width:100%;box-sizing:border-box;margin-top:6px}
.fq-miss{color:var(--n-warn-ink);font-weight:600}
/* «⋯» sits ON the row's top border, opposite the legend — never over the counters (measured at 390) */
.fq-menu{position:absolute;top:-16px;right:10px}
.fq-menu > summary{list-style:none;cursor:pointer;font-weight:800;padding:2px 10px;border-radius:var(--r-pill);
  min-height:30px;display:flex;align-items:center;background:var(--bg);border:1px solid var(--line)}
.fq-menu > summary::-webkit-details-marker{display:none}
.fq-menu__list{position:absolute;right:0;z-index:2;background:var(--bg);border:1px solid var(--line);
  border-radius:var(--r-sm);box-shadow:var(--sh-1);padding:6px;display:flex;flex-direction:column;gap:4px}
.fq-line{margin:0}
.fq-ack{gap:6px;margin-top:6px}
.fq-preview{display:flex;flex-direction:column;gap:8px}
.fq-frame{width:100%;height:480px;border:1px solid var(--line);border-radius:var(--r-sm);background:#fff}
.fq-frame--phone{width:390px;max-width:100%;margin:0 auto;display:block}
.fq-list{padding:var(--s5) clamp(16px,3vw,28px) 120px;max-width:820px;width:100%;margin:0 auto;
  display:flex;flex-direction:column;gap:12px;box-sizing:border-box}
.fq-list__rows{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:4px}
.fq-list__row{flex-wrap:wrap}
.fq-where ul{margin:6px 0 0;padding-left:18px}
/* ⇥ CD-127 S7 (§6.7.2): «Uusi kysymysosio sivulle:» — wrapped page links, each a ≥44 px tap target */
.fq-create{display:flex;flex-direction:column;gap:6px}
.fq-create p{margin:0}
.fq-create__pages{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:8px}
.fq-create__pages .btn{min-height:44px;display:inline-flex;align-items:center}
.fq-create-head{display:flex;flex-direction:column;gap:10px;align-items:flex-start}
.fq-create-head .fq-field{width:100%}
/* ⇥ CD-127 S7 F2 (§6.7.3): the bind mode — the default language read-only above the face's fields */
.fq-bind-src{border-left:3px solid var(--line);padding:2px 0 2px 10px;margin:0 0 8px}
.fq-bind-src p{margin:0}
.fq-bind-src__q{font-weight:600}
.fq-bind-now ol{margin:4px 0 0;padding-left:20px}
.fq-bind-offer{margin:0}
.fq-bind-offer .btn{min-height:44px;display:inline-flex;align-items:center}
.fq-receipt{padding:var(--s5) clamp(16px,3vw,28px);max-width:820px;width:100%;margin:0 auto;
  display:flex;flex-direction:column;gap:12px;box-sizing:border-box}
.fq-receipt__acts{gap:8px;flex-wrap:wrap}

/* =========================================================================
   39. «AJASTETUT MUUTOKSET» AT PHONE WIDTH (CD-127 S8b, D-2070 — timed-content.md §17.7, §17.13)
   A scheduled change's verbs wrap UNDER its text on a phone — found by the 390 px drive: a scheduled new item's three
   verbs («Julkaise nyt» · «Muuta» · «Peru ajastus») left its title and its moment a 70 px column.
   ========================================================================= */
@media (max-width: 760px){
  .listrow--sched{flex-wrap:wrap}
  .listrow--sched > .row{width:100%;justify-content:flex-start!important}
}
/* ⇥ CD-127 S9a P3 (`content-items.md` §17.11): the stale mentions under a list preview — a sentence, not a pill */
.pv__gap[data-li-stale]{display:block;flex:1 1 100%;border-radius:var(--r-sm);padding:8px 10px;font-size:13px;line-height:1.45}
.pv__gap[data-li-stale] p{margin:0 0 4px}
/* ⇥ D-2093: staff's documents under the stale lines — a <details> of paths, never in the sentence */
.li-docs{margin:0 0 4px}
.li-docs ul{margin:4px 0 0;padding-left:18px;overflow-wrap:anywhere}

/* =========================================================================
   40. THE ITEM RECEIPT'S OUTPUT LINES AND THE DOOR'S EVENTS LIST (CD-127 S12 P3, D-2188 — content-planner.md
   §S12.11, §S12.14). One row per output: its sentence, and its one button beside it — under it on a phone, where a
   long sentence («Juliste valmistuu tavallista hitaammin — …») would otherwise leave the button a sliver. The events
   list is the same shape: the day and the name, the chip, then the verbs.
   ========================================================================= */
.pi-outs{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}
.pi-out{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px 12px;
  padding:10px 14px;border:1px solid var(--line);border-radius:var(--r);background:var(--bg);min-width:0}
.pi-out__line{flex:1 1 240px;min-width:0;overflow-wrap:anywhere;line-height:1.45}
.pi-out form{margin:0}
.pi-out .btn{flex:none}
.ev-acts{margin:0 0 4px;max-width:420px}
.ev-h{font-size:16px;font-weight:700;margin:22px 0 4px}
.ev-rows{list-style:none;margin:0;padding:0;display:flex;flex-direction:column}
.ev-row{display:flex;align-items:center;flex-wrap:wrap;gap:6px 10px;padding:10px 0;border-bottom:1px solid var(--line);
  min-width:0}
.ev-row__what{flex:1 1 260px;min-width:0;overflow-wrap:anywhere;line-height:1.4}
.ev-row__when{color:var(--mut);font-size:13px;margin-right:4px;white-space:nowrap}
.ev-row__name{font-weight:600}
.ev-row__acts{display:flex;gap:6px;flex:none;margin-left:auto;flex-wrap:wrap;justify-content:flex-end;max-width:100%}
/* ⇥ D-2482 (`ai-ui-parity.md` §1.4): «Poista sivustolta» beside a list row's chip — the opened confirm takes the row */
.rm-row>summary{list-style:none;cursor:pointer}
.rm-row>summary::-webkit-details-marker{display:none}
.rm-row[open]{flex-basis:100%;width:100%}
.rm-row form{margin:6px 0 0;display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px}
.rm-row form p{margin:0;flex:1 1 240px;min-width:0;overflow-wrap:anywhere}
.ck-row .rm-row[open]{flex:1 1 100%}
/* the news / blog door list (§10.4) on a PHONE only (wider, the list is exactly as it was): EVERY row shows — §37's
   «first row only» is the door CARD's rule — and a row's verbs wrap under its title once «Kopioi uudeksi» sits beside
   «Muokkaa» */
@media (max-width: 760px){
  .ck-rows.pl-rows .ck-row:nth-child(n+2){display:flex}
  .pl-rows .ck-row{flex-wrap:wrap;row-gap:2px;padding:6px 0;border-bottom:1px solid var(--line)}
  .pl-rows .ck-row__name{flex:1 1 200px;white-space:normal;overflow-wrap:anywhere}
}

/* ⇥ CD-142 block 2 (dashboard-i18n.md §10.1) — the language switcher at the foot of the invitation card */
.auth__card .lang-switch{display:flex;gap:2px;margin-top:20px}
.auth__card .lang-switch__b{font:inherit;font-size:12px;font-weight:600;letter-spacing:.04em;min-width:34px;min-height:32px;padding:4px 8px;border:1px solid transparent;border-radius:6px;background:none;color:var(--muted,#5b6472);cursor:pointer}
.auth__card .lang-switch__b[aria-pressed="true"]{color:var(--ink,#16202c);border-color:var(--line,#d8dde5);background:var(--bg-soft,#f3f5f8)}

/* ⇥ D-2563 (site-agent.md §17.2) — the site assistant plan values keep their lines: a list is one line per item */
.sa-arvot p{white-space:pre-line}

/* ============================================================================
   41. A CHANGE WAITING ON THE AI BUDGET (D-2824, `site-agent.md` §78.15): it reads as a queued card
   ============================================================================ */
.rec--budget{--k:var(--faint);background:var(--bg2)}
.rec--budget .rec__title{color:var(--mut)}
