/* ============================================================================
   eKassa.ee — disainisüsteem.  Vt docs/DISAIN.md.
   Üks fail, null sõltuvust, null välist fonti, null kaugpilti.
   CSP: style-src 'self' — ei ole inline-stiile ega style="..." atribuute.
   Astmelised viivitused tulevad :nth-child()-ist, mitte inline-stiilist.
   ========================================================================= */

/* ---------------------------------------------------------------------------
   1. TOKENID
   Miks eraldi token iga asja jaoks: müügilehte, poodi, kassat ja kviitungit
   ehitavad eri sessioonid eri failides. Ainus viis, kuidas nad kokku sobivad,
   on see, et keegi ei kirjuta värvi ega varju käsitsi.
   ------------------------------------------------------------------------ */
:root{
  color-scheme:light;

  /* Kogu neutraalskaala on ROHEKA alatooniga, mitte puhas hall. Puhas hall
     kõrvuti rohelise brändivärviga näeb külm ja odav; kerge rohekas tint paneb
     halli ja rohelise ühte perekonda. */
  --ink:#0B1410;        /* põhitekst */
  --ink-2:#3D4C45;      /* teisene tekst, kirjeldused */
  --ink-3:#6E7F76;      /* vihjed, ajatemplid, sildid */
  --paper:#FBFBF8;      /* lehe taust — soe valge, mitte steriilne #fff */
  --paper-2:#F2F5F0;
  --paper-3:#E8EEE7;
  --card:#FFFEFC;       /* kaardi valge on kraadi võrra SOOJEM kui lehe valge,
                           nii tõuseb kaart taustast ka ilma jooneta esile */
  --line:#E3E9E1;
  --line-2:#CBD6C9;

  --green:#0B6B2E;      /* UX-SPETS: makse kinnituse värv. Kogu bränd selle ümber. */
  --green-2:#12A150;
  --green-3:#0A5726;
  --green-4:#063A1A;    /* gradiendi sügavaim ots */
  --green-pale:#E7F4EC;
  --green-mist:#F1F8F3;

  --amber:#B45309; --amber-pale:#FEF3E2; --amber-line:#EFC98F;
  --red:#B42318;   --red-pale:#FEF0EF;   --red-line:#F1BBB6;

  --sans:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,monospace;

  /* Suur kontrast pealkirja ja teksti vahel eristab kujundatud lehe mallist:
     pealkiri on raske ja TIHE, tekst kerge ja lai. */
  --t-hero:clamp(2.7rem,6.4vw,5rem);
  --t-h1:clamp(2.05rem,4vw,3.15rem);
  --t-h2:clamp(1.5rem,2.6vw,2.1rem);
  --t-lead:clamp(1.14rem,1.7vw,1.4rem);
  --t-body:1.0625rem;   /* 17px — turuletil päikese käes loetav */
  --t-small:.9375rem;
  --t-micro:.75rem;

  --r-sm:10px; --r-md:14px; --r-lg:20px; --r-xl:28px; --r-full:999px;

  /* Varjud on ROHEKAD ja MITMEKIHILISED.
     Must vari valgel paberil näeb välja nagu määrdunud pilt. Kolm kihti
     (kontaktvari + kandev vari + ümbritsev udu) matkivad päris valgust;
     üks kiht näeb alati välja nagu CSS-i vaikeväärtus. */
  --shadow-1:
    0 1px 1px rgba(10,52,28,.04),
    0 2px 4px -1px rgba(10,52,28,.04),
    0 8px 16px -8px rgba(10,52,28,.07);
  --shadow-2:
    0 1px 1px rgba(10,52,28,.05),
    0 4px 8px -2px rgba(10,52,28,.06),
    0 16px 30px -12px rgba(10,52,28,.12);
  --shadow-3:
    0 1px 2px rgba(10,52,28,.06),
    0 8px 16px -6px rgba(10,52,28,.08),
    0 28px 50px -20px rgba(10,52,28,.16),
    0 52px 86px -44px rgba(10,52,28,.20);
  /* Rohelise nupu oma vari on brändivärvi tugevam versioon, mitte hall. */
  --shadow-green:
    0 1px 1px rgba(6,58,26,.22),
    0 6px 14px -4px rgba(6,58,26,.28),
    0 18px 34px -14px rgba(6,58,26,.34);

  /* Kaardil EI OLE `border`-it. Juuksekarva-peenike rõngas varjuna tähendab,
     et serv on TUNTAV, mitte NÄHTAV — see ongi vahe paberi ja kasti vahel. */
  --hair:0 0 0 1px rgba(10,52,28,.055);
  --hair-2:0 0 0 1px rgba(10,52,28,.10);
  /* Ülaserva valguskiir: valgus tuleb ülalt, nagu päris ruumis. */
  --edge:inset 0 1px 0 rgba(255,255,255,.85);

  --ease:cubic-bezier(.2,.7,.3,1);
  --fast:150ms; --base:280ms; --slow:620ms;

  --wrap:1140px;
  --gutter:clamp(20px,4.2vw,34px);
  --section-y:clamp(78px,9.5vw,132px);

  /* Fookusrõngas on muutuja, sest tumedatel pindadel peab ta olema valge. */
  --ring:var(--green);

  /* --- Osa 40 tokenid ---------------------------------------------------- */

  /* 🔴 KAKS ESIMEST PARANDAVAD MÄÄRAMATA MUUTUJA, mitte ei lisa maitset.
     `var(--mint)` seisis lauaarvuti navi aktiivse rea reeglis ja `var(--t-h3)`
     `.dashboard-onboarding h2`-s ilma, et kumbagi oleks kusagil defineeritud.
     Määramata muutuja teeb TERVE deklaratsiooni kehtetuks (invalid at
     computed-value time) — ehk aktiivsel navireal EI OLNUD rohelist serva ja
     ühenduskaardi pealkiri päris paljast `h2` suurust. Kumbki ei „katkenud"
     nähtavalt; nad lihtsalt ei ilmunud, ja seda liiki viga elab kaua. */
  --mint:#6FE7A3;       /* hele roheline TUMEDAL pinnal — navi, POS-summa */
  --t-h3:1.2rem;        /* sama, mis paljas h3 osas 2 */

  --ink-4:#8C9891;      /* kõige vaiksem tekst: statistika sildid */

  /* Statistikal on OMA skaala ja ta on TAOTLUSLIKULT hõre: päevakäive ja
     kontekstiarv ei tohi tulla samast astmest. Hierarhia on suurusvahe, mitte
     paksusvahe — kaks 900-kaalulist arvu ühesuuruses kirjas on kaks pealkirja,
     mitte pealkiri ja allmärkus. */
  --t-stat-hero:clamp(2.5rem,7.4vw,3.5rem);
  --t-stat:clamp(1.4rem,2.2vw,1.7rem);
  --t-label:.8125rem;   /* 13px, TAVALINE kirjapilt, TAVALINE tähevahe */

  /* Sügavus tuleb VALGUSEST, mitte joonest. Kolm korduvat välja, et iga pind
     oleks samast ruumist: rohekas helk ülalt vasakult, soe kreem servast,
     ülipeen paberitera. Tera nurk on sama, mis `body::before` omal — muidu
     paistab, et pind on lehe peale kleebitud, mitte lehest välja lõigatud. */
  --field-green:radial-gradient(120% 150% at 14% -34%,rgba(18,161,80,.13),transparent 64%);
  --field-warm:radial-gradient(92% 130% at 104% -12%,rgba(206,188,142,.20),transparent 60%);
  --grain:repeating-linear-gradient(112deg,rgba(10,52,28,.015) 0 1px,transparent 1px 3px);

  /* Tõstetud pind hoveril — sama perekond, mis --shadow-2, üks aste kõrgemal. */
  --shadow-lift:
    0 2px 3px rgba(10,52,28,.05),
    0 10px 20px -6px rgba(10,52,28,.09),
    0 30px 54px -22px rgba(10,52,28,.17);

  font-family:var(--sans);
  color:var(--ink);
}

/* ---------------------------------------------------------------------------
   2. ALUS
   ------------------------------------------------------------------------ */
*{box-sizing:border-box}

html{
  background:var(--paper);
  scroll-behavior:smooth;
  scroll-padding-top:92px;      /* kleepuv päis ei tohi ankrut katta */
  -webkit-text-size-adjust:100%;
}

body{
  margin:0;
  font-size:var(--t-body);
  line-height:1.62;
  background:transparent;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}

/* Atmosfäär on OMAETTE fikseeritud kiht, mitte body taust.
   Põhjus on jõudlus: `background-attachment:fixed` sunnib mõnda brauserit iga
   kerimiskaadriga tausta uuesti joonistama, ja see leht elab telefonis
   turuletil. Fikseeritud pseudoelement komponeeritakse üks kord. */
body::before{
  content:"";
  position:fixed;
  inset:0;
  z-index:-1;
  pointer-events:none;
  background-color:var(--paper);
  background-image:
    /* rohekas valgusväli paremal üleval — annab lehele suuna */
    radial-gradient(1150px 620px at 88% -16%, rgba(18,161,80,.11), transparent 62%),
    /* soe kreemine väli vasakul — hoiab ära, et valge oleks külm ja steriilne */
    radial-gradient(900px 540px at -10% 0%, rgba(206,188,142,.17), transparent 58%),
    /* ülipeen tera. 1px jooned 1,3% alfaga: mustrina nähtamatu, aga murrab
       suure lameda valge pinna ja annab talle paberi tunde. */
    repeating-linear-gradient(112deg, rgba(10,52,28,.013) 0 1px, transparent 1px 3px);
}

h1,h2,h3,h4,p,figure,ul,ol,dl{margin-top:0}
:where(h1,h2,h3,h4,p,ul,ol,dl):last-child{margin-bottom:0}

/* Suurel kirjal tuleb tähevahet KOKKU tõmmata, muidu laguneb pealkiri
   sõnajadaks. Väikesel kirjal on vastupidi. */
h1{font-size:var(--t-h1);line-height:1.05;letter-spacing:-.034em;font-weight:800;margin-bottom:.5em}
h2{font-size:var(--t-h2);line-height:1.12;letter-spacing:-.026em;font-weight:800;margin-bottom:.55em}
h3{font-size:1.2rem;line-height:1.25;letter-spacing:-.014em;font-weight:800;margin-bottom:.45em}
p{margin-bottom:1.05em}

a{color:var(--green);text-underline-offset:3px;text-decoration-thickness:1.5px;transition:color var(--fast) var(--ease)}
a:hover{color:var(--green-2)}

button,input,select,textarea{font:inherit;color:inherit}
img,svg{max-width:100%}

::selection{background:var(--green-pale);color:var(--green-3)}

/* 🔴 FOOKUS ON NÕUE, MITTE KAUNISTUS.
   Selles failis ei ole ühtegi `outline:none` deklaratsiooni. Rõngas on 3px,
   sest 2px kaob rohelisel ja hallil pinnal ära. `outline` järgib tänapäeva
   brauserites elemendi enda ümarust — seepärast EI OLE siin `border-radius`,
   mis muudaks elemendi kuju fookuse ajal. */
:focus-visible{outline:3px solid var(--ring);outline-offset:3px}

/* Tumedatel pindadel läheb roheline rõngas kaotsi → valge. */
.final-cta,.success,.pos-total{--ring:#fff}

/* Raha joondub veergu. See üksi eristab päris toodet prototüübist:
   ühelaiused numbrid tähendavad, et 12,90 ja 132,90 lõpevad samas kohas. */
table,
.price,.price-value,.cart-total,.cart-total strong,.cart-row-unit,.cart-row-total,
.success-total,
.order-line-qty,.order-line-total,
input[type=number]{
  font-variant-numeric:tabular-nums;
  font-feature-settings:"tnum" 1;
}

/* `.price` on NUMBER, mitte lõik. Ilma selle reeglita päris ta `<p>` suuruse
   ja halduse koondkaardil oli silt (12px, versaal, 800) suurem kui number ise
   — müüja tähtsaim arv nägi välja nagu allmärkus. Poekaardil kirjutab
   `.product .price` selle üle. */
.price{
  margin:2px 0 0;
  font-size:clamp(1.7rem,3vw,2.1rem);font-weight:900;
  letter-spacing:-.035em;line-height:1.1;color:var(--ink);
}

/* Reajoonisel olev ikoon pärib teksti värvi ja ei tohi kunagi kokku suruda. */
.ico{flex:none;width:20px;height:20px;stroke:currentColor;fill:none}

/* ---------------------------------------------------------------------------
   3. TÜPOGRAAFIA-ABILISED
   ------------------------------------------------------------------------ */

/* Eelpealkiri saab ette lühikese joone. Odav trikk, mis maksab null baiti ja
   annab igale sektsioonile toimetatud ajakirja rütmi.
   `flex` + `width:fit-content` (mitte `inline-flex`), sest inline-tasandil
   eelpealkiri hüppab brändinimega samale reale seal, kus nad on õed-vennad
   (POS-i ja halduse päis). `margin-inline:auto` keskjoondab seal, kus vaja. */
.eyebrow{
  display:flex;width:fit-content;align-items:center;gap:10px;
  text-transform:uppercase;letter-spacing:.15em;
  font-size:var(--t-micro);font-weight:800;color:var(--green);
  margin:0 0 14px;
}
.eyebrow::before{content:"";flex:none;width:22px;height:2px;border-radius:2px;background:currentColor;opacity:.5}

.lead{font-size:var(--t-lead);color:var(--ink-2);line-height:1.5;letter-spacing:-.008em}
.micro{font-size:var(--t-small);color:var(--ink-3);line-height:1.55}

/* Tagasilink on navigatsioon, mitte kaunistus: tal on päris puuteala. */
.backlink{
  display:inline-flex;align-items:center;gap:8px;
  min-height:44px;
  font-weight:700;color:var(--ink-2);text-decoration:none;
}
.backlink:hover{color:var(--green)}

/* Nupp, mis on semantiliselt nupp, aga visuaalselt link (nt „Eemalda"). */
.linkbutton{
  min-height:44px;padding:6px 2px;
  background:none;border:0;
  color:var(--ink-3);font-size:var(--t-small);font-weight:650;
  text-decoration:underline;text-underline-offset:3px;
  cursor:pointer;
  transition:color var(--fast) var(--ease);
}
.linkbutton:hover{color:var(--red)}
.linkbutton:active{color:var(--red);text-decoration-thickness:2px}

/* ---------------------------------------------------------------------------
   4. PÄIS JA BRÄND
   ------------------------------------------------------------------------ */
.sitebar{
  max-width:var(--wrap);margin:auto;
  padding:18px var(--gutter);
  display:flex;justify-content:space-between;align-items:center;gap:24px;
}
.landing-nav{
  position:sticky;top:0;z-index:40;
  background:rgba(251,251,248,.80);
  backdrop-filter:blur(16px) saturate(1.6);
  -webkit-backdrop-filter:blur(16px) saturate(1.6);
  border-bottom:1px solid rgba(227,233,225,.85);
}
.sitebar nav{display:flex;gap:6px;align-items:center}
.sitebar nav>a:not(.button){
  display:inline-flex;align-items:center;min-height:44px;padding:0 14px;
  border-radius:var(--r-full);
  color:var(--ink-2);font-weight:700;text-decoration:none;
  transition:color var(--fast) var(--ease),background var(--fast) var(--ease);
}
.sitebar nav>a:not(.button):hover{color:var(--green-3);background:var(--green-mist)}
.sitebar nav>a:not(.button):active{background:var(--green-pale)}
.sitebar nav .button{margin-left:10px}
/* Poe ja ostuvoo riba on kitsam ja püsib lehe kohal — ostja peab korvi
   nägema igal sammul. */
.shopbar{border-bottom:1px solid var(--line)}

/* Brändimärk on QR-koodi kolm otsingumustrit — täpselt see asi, mida toode
   müüb. Joonistatud gradientidega, sest pildifail oleks võrgupäring ja CSP
   lubab ainult 'self'. */
/* `gap` on siin TEADLIKULT 0: „eKassa" on tekstisõlm ja `.ee` on `<span>`,
   ehk flexis on nad KAKS eraldi elementi. `gap` lööks brändinime kaheks
   („eKassa .ee"). Vahe kuulub ainult märgi ja teksti vahele. */
.brand{
  display:inline-flex;align-items:center;gap:0;
  font-weight:900;font-size:1.28rem;letter-spacing:-.045em;
  color:var(--ink);text-decoration:none;
}
.brand::before{
  content:"";flex:none;width:26px;height:26px;margin-right:11px;border-radius:8px;
  background:
    linear-gradient(#fff,#fff) 6px 6px/6px 6px no-repeat,
    linear-gradient(#fff,#fff) 14px 6px/6px 6px no-repeat,
    linear-gradient(#fff,#fff) 6px 14px/6px 6px no-repeat,
    linear-gradient(158deg,var(--green-2),var(--green-3));
  box-shadow:0 2px 6px -1px rgba(6,58,26,.35),inset 0 1px 0 rgba(255,255,255,.30);
  print-color-adjust:exact;-webkit-print-color-adjust:exact;
}
.brand span{color:var(--green)}
.brand:hover{color:var(--ink)}

.barlink{
  display:inline-flex;align-items:center;min-height:44px;
  font-weight:700;color:var(--ink-2);text-decoration:none;
}
.barlink:hover{color:var(--green)}

/* ---------------------------------------------------------------------------
   5. NUPUD
   Igal interaktiivsel elemendil on neli seisundit: hover, focus-visible,
   active, disabled. Kui mõni puudub, tundub asi katki, mitte lihtne.
   ------------------------------------------------------------------------ */
.button{
  --btn-bg:linear-gradient(180deg,var(--green-2) 0%,var(--green) 58%,var(--green-3) 100%);
  position:relative;
  min-height:56px;
  padding:16px 30px;
  border:0;border-radius:var(--r-full);
  background:var(--btn-bg);
  color:#fff;text-decoration:none;text-align:center;
  font-family:var(--sans);font-size:1.0625rem;font-weight:800;line-height:1.2;
  letter-spacing:-.012em;
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  cursor:pointer;
  /* Ülemine sisemine valguskiir + alumine sisemine vari = nupp on KEHA,
     mitte värviline ristkülik. */
  box-shadow:var(--shadow-green),inset 0 1px 0 rgba(255,255,255,.26),inset 0 -1px 0 rgba(0,0,0,.16);
  transition:transform var(--fast) var(--ease),box-shadow var(--base) var(--ease),filter var(--fast) var(--ease);
}
.button:hover{
  transform:translateY(-2px);
  filter:saturate(1.05) brightness(1.06);
  box-shadow:
    0 2px 3px rgba(6,58,26,.22),
    0 10px 20px -6px rgba(6,58,26,.30),
    0 26px 44px -18px rgba(6,58,26,.38),
    inset 0 1px 0 rgba(255,255,255,.30);
}
/* Vajutus peab olema füüsiline: nupp läheb ALLA ja vari läheb VÄIKSEMAKS. */
.button:active{
  transform:translateY(1px);
  filter:brightness(.96);
  box-shadow:0 1px 2px rgba(6,58,26,.26),inset 0 1px 3px rgba(0,0,0,.20);
}

.button.secondary{
  --btn-bg:linear-gradient(180deg,#fff,#FBFCFA);
  color:var(--green-3);
  box-shadow:inset 0 0 0 1px var(--line-2),var(--shadow-1);
}
.button.secondary:hover{filter:none;color:var(--green);box-shadow:inset 0 0 0 1.5px var(--green-2),var(--shadow-2)}
.button.secondary:active{filter:none;box-shadow:inset 0 0 0 1.5px var(--green),inset 0 2px 4px rgba(10,52,28,.10)}

.button.light{
  --btn-bg:#fff;
  color:var(--green-3);
  box-shadow:0 2px 4px rgba(0,0,0,.10),0 14px 30px -12px rgba(0,0,0,.35),inset 0 -1px 0 rgba(0,0,0,.06);
}
.button.light:hover{filter:none;box-shadow:0 4px 8px rgba(0,0,0,.12),0 22px 44px -16px rgba(0,0,0,.42)}
.button.light:active{filter:none;box-shadow:0 1px 2px rgba(0,0,0,.20)}

.button.small{min-height:44px;padding:10px 20px;font-size:var(--t-small)}

/* Keelatud nupp ei ole hägune põhinupp — ta on ISE pind. Läbipaistvus ainsa
   vihjena teeb teksti loetamatuks ja näeb välja nagu renderdusviga. */
.button:disabled,.button[aria-disabled="true"]{
  --btn-bg:var(--paper-2);
  color:var(--ink-3);
  cursor:not-allowed;transform:none;filter:none;
  box-shadow:inset 0 0 0 1px var(--line);
}

/* ---------------------------------------------------------------------------
   6. HERO
   ------------------------------------------------------------------------ */
.hero{
  max-width:var(--wrap);margin:auto;
  padding:clamp(48px,6vw,84px) var(--gutter) clamp(72px,9vw,116px);
  display:grid;grid-template-columns:1.06fr .94fr;gap:clamp(32px,5vw,64px);
  align-items:center;
}
.hero h1{font-size:var(--t-hero);line-height:1.01;letter-spacing:-.04em;max-width:14ch;margin-bottom:.42em}
.hero .lead{max-width:36ch}
.actions{display:flex;flex-wrap:wrap;gap:14px;margin:32px 0 18px}

.hero-art{
  width:100%;max-height:540px;
  filter:drop-shadow(0 30px 48px rgba(10,52,28,.16));
}
.hero-art *{stroke:var(--ink);stroke-width:4.6;stroke-linecap:round;stroke-linejoin:round}
.hero-art .awning{fill:var(--green-pale)}
.hero-art .phone{fill:var(--ink)}
.hero-art .screen{fill:#fff;stroke:none}
.hero-art .qr{fill:var(--ink);stroke:none}
.hero-art .cup{fill:#fff}
.hero-art .sun{fill:#F5C95F;stroke:none}
.hero-art .stall{fill:none}
/* Vooskeem on lai ja madal — ta illustreerib sektsiooni, mitte lehte. */
.flow-art{max-height:220px;margin-top:clamp(20px,3vw,34px);filter:drop-shadow(0 16px 30px rgba(10,52,28,.12))}
.flow-art *{stroke-width:5.5}

/* Kolm nulli hero all — usaldussignaal, mitte kaunistus.
   `--r-lg`, mitte täisümar: /hinnad lehel kannab sama klass kahte lauset ja
   täisümar mitmerealine pill näeb välja nagu viga. */
.free-callout{
  display:inline-flex;align-items:center;flex-wrap:wrap;gap:10px;
  padding:15px 22px;border-radius:var(--r-lg);
  background:linear-gradient(180deg,#fff,var(--green-mist));
  color:var(--green-3);
  font-size:var(--t-small);font-weight:800;line-height:1.5;
  box-shadow:inset 0 0 0 1px rgba(11,107,46,.16),var(--shadow-1);
}
.free-callout::before{
  content:"";flex:none;width:9px;height:9px;border-radius:50%;
  background:var(--green-2);box-shadow:0 0 0 4px rgba(18,161,80,.16);
}
.free-callout strong{font-size:1.12em;letter-spacing:-.015em;font-variant-numeric:tabular-nums}

/* ---------------------------------------------------------------------------
   7. SEKTSIOONID JA KAARDID
   ------------------------------------------------------------------------ */
.section{padding:var(--section-y) var(--gutter);position:relative}
.section.alt{
  background:linear-gradient(180deg,rgba(242,245,240,.92),rgba(234,240,232,.96));
  box-shadow:inset 0 1px 0 var(--line),inset 0 -1px 0 var(--line);
}
.section-head{max-width:var(--wrap);margin:0 auto clamp(34px,4.5vw,56px)}
.section-head h2{font-size:var(--t-h1);max-width:18ch;margin-bottom:0}
.section-head .lead{max-width:64ch;margin:16px 0 0}

.steps,.feature-grid,.audiences{max-width:var(--wrap);margin:auto;display:grid;gap:20px}
.steps{grid-template-columns:repeat(3,1fr)}
.feature-grid{grid-template-columns:repeat(3,1fr)}

/* Kaardi retsept: EI OLE `border`-it. Juuksekarva-rõngas + kolm varjukihti +
   ülaserva valguskiir. Tulemus on paberileht laual, mitte joonistatud kast. */
.steps article,.feature-grid article{
  position:relative;overflow:hidden;
  padding:30px 28px 32px;
  border-radius:var(--r-xl);
  background:linear-gradient(180deg,var(--card),#FBFCF9);
  box-shadow:var(--hair),var(--shadow-1),var(--edge);
  transition:transform var(--base) var(--ease),box-shadow var(--base) var(--ease);
}
/* Ülaserva rohejoon ilmub hoveril — vaikne, aga annab kaardile elu. */
.steps article::after,.feature-grid article::after{
  content:"";position:absolute;inset:0 0 auto;height:3px;
  background:linear-gradient(90deg,var(--green),var(--green-2));
  transform:scaleX(0);transform-origin:left;
  transition:transform var(--base) var(--ease);
}
.steps article:hover,.feature-grid article:hover{
  transform:translateY(-6px);
  box-shadow:var(--hair-2),var(--shadow-3),var(--edge);
}
.steps article:hover::after,.feature-grid article:hover::after{transform:scaleX(1)}
.steps article p,.feature-grid article p{color:var(--ink-2);margin-bottom:0}

/* Sammu number läheb nurka, et ikoon jääks kaardi peategelaseks. Vaikimisi
   kahvatu, hoveril täisroheline — number on viide, mitte plakat. */
.steps article{padding-right:76px}
.step-no{
  position:absolute;top:26px;right:24px;
  display:inline-grid;place-items:center;width:36px;height:36px;border-radius:50%;
  background:var(--green-pale);color:var(--green-3);
  font-weight:900;font-size:1rem;line-height:1;
  box-shadow:inset 0 0 0 1px rgba(11,107,46,.18);
  transition:background var(--base) var(--ease),color var(--base) var(--ease),box-shadow var(--base) var(--ease);
}
.steps article:hover .step-no{background:var(--green);color:#fff;box-shadow:0 4px 12px -2px rgba(6,58,26,.40)}

.line-icon{display:block;width:64px;height:64px;margin:-4px 0 16px;overflow:visible}
.line-icon rect{fill:var(--green-pale);stroke:none;transition:fill var(--base) var(--ease)}
.line-icon path{fill:none;stroke:var(--green);stroke-width:3;stroke-linecap:round;stroke-linejoin:round;transition:stroke var(--base) var(--ease)}
/* Hoveril pöördub ikoon ümber: täidetud roheline tahvel, valge joonis. */
.steps article:hover .line-icon rect,.feature-grid article:hover .line-icon rect{fill:var(--green-2)}
.steps article:hover .line-icon path,.feature-grid article:hover .line-icon path{stroke:#fff}

/* ---------------------------------------------------------------------------
   8. HINNASTUS JA VÕRDLUS
   ------------------------------------------------------------------------ */
.pricing-section{
  max-width:var(--wrap);margin:auto;
  display:grid;grid-template-columns:1fr 1fr;gap:clamp(36px,6vw,76px);
  align-items:center;
}
.pricing-section .lead{max-width:46ch}
.pricing-section .free-callout{margin-bottom:18px}
.pricing-section .micro{max-width:52ch}
.pricing-card{
  position:relative;
  padding:clamp(26px,3vw,36px);
  border-radius:var(--r-xl);
  background:linear-gradient(180deg,#fff,#FBFCF9);
  /* Neljas varjukiht on ROHELINE — hinnakaart on lehe kalleim objekt ja tohib
     kanda pisut brändivärvi valgust. */
  box-shadow:
    var(--hair),
    var(--shadow-3),
    0 30px 70px -34px rgba(11,107,46,.34),
    var(--edge);
}
/* Gradientäär maskiga: 1px rohelisest kadumiseni. Tekitab „klaasi serva". */
.pricing-card::before{
  content:"";position:absolute;inset:0;border-radius:inherit;padding:1px;
  background:linear-gradient(155deg,var(--green-2),rgba(18,161,80,0) 46%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  mask-composite:exclude;pointer-events:none;
}

table{border-collapse:collapse;width:100%}
th,td{text-align:left;padding:15px 12px;border-bottom:1px solid var(--line)}

.pricing-card table{position:relative}
.pricing-card th,.legal th{padding-left:0;color:var(--ink-2);font-weight:650}
.pricing-card td,.legal tbody td{padding-right:0;text-align:right;color:var(--ink);font-weight:850;font-size:1.06rem;letter-spacing:-.015em}
.pricing-card tr:last-child th,.pricing-card tr:last-child td{border-bottom:0}
.pricing-card .free,.legal .free{background:linear-gradient(90deg,var(--green-mist),rgba(241,248,243,0) 88%)}
.pricing-card .free th,.legal .free th{position:relative;padding-left:16px;color:var(--green-3);font-weight:800}
.pricing-card .free th::before,.legal .free th::before{content:"";position:absolute;left:0;top:13px;bottom:13px;width:3px;border-radius:3px;background:var(--green-2)}
.pricing-card .free td,.legal .free td{color:var(--green-3)}
.pricing-card .button{width:100%;margin-top:26px;min-height:64px}

/* Võrdlustabel. Meie rida on esile tõstetud, aga mitte karjuv — aus võrdlus
   kaotab mõju, kui ta näeb välja nagu reklaam. */
.compare{min-width:760px}
.compare th,.compare td{vertical-align:top;font-size:var(--t-small);line-height:1.5}
.compare thead th{
  font-size:var(--t-micro);text-transform:uppercase;letter-spacing:.11em;
  color:var(--ink-3);font-weight:800;white-space:nowrap;
}
.compare tbody th{font-weight:700;color:var(--ink);width:24%}
.compare .ours{background:linear-gradient(90deg,var(--green-mist),rgba(241,248,243,.35))}
.compare .ours th,.compare .ours td{color:var(--green-3)}
.compare .ours strong{color:var(--green-3);font-weight:850}
.compare tbody tr:last-child th,.compare tbody tr:last-child td{border-bottom:0}

/* ---------------------------------------------------------------------------
   9. SIHTRÜHMAD JA KKK
   ------------------------------------------------------------------------ */
.audiences{grid-template-columns:repeat(4,1fr)}
.audiences span{
  /* `start`, mitte `center`: keskjoondus tsentreeriks IGA kaardi sisu eraldi
     ja kolmerealine tekst nihutaks oma pealkirja teiste omast välja. Pealkirjad
     peavad võres algama ühelt jooneltele. */
  display:grid;align-content:start;justify-items:center;gap:8px;text-align:center;
  min-height:150px;padding:30px 20px;
  border-radius:var(--r-xl);
  background:linear-gradient(180deg,var(--card),#FAFCF8);
  letter-spacing:-.015em;
  box-shadow:var(--hair),var(--shadow-1),var(--edge);
  transition:transform var(--base) var(--ease),box-shadow var(--base) var(--ease),color var(--fast);
}
/* Kaardil peab olema TÕEND, mitte ainult silt. Neli üksiku sõnaga kasti
   näevad välja nagu kohatäited, mille keegi unustas täitmata. */
.audiences strong{font-weight:850;font-size:1.12rem}
.audiences small{
  color:var(--ink-2);font-size:var(--t-small);font-weight:600;
  line-height:1.5;letter-spacing:0;
}
.audiences span:hover{transform:translateY(-4px);color:var(--green-3);box-shadow:var(--hair-2),var(--shadow-2),var(--edge)}
.audiences span:hover small{color:var(--green-3)}

/* KKK sektsioon joondub teiste sektsioonidega (sama `--wrap`), aga vastuste
   veerg jääb kitsaks. Varem oli max-width sektsioonil endal ja pealkiri
   hüppas lehe teiste pealkirjade suhtes 180px paremale. */
.faq{max-width:var(--wrap);margin:auto}
.faq details{max-width:860px;border-bottom:1px solid var(--line)}
.faq details:last-of-type{border-bottom:0}
.faq summary{
  display:flex;align-items:center;justify-content:space-between;gap:20px;
  min-height:68px;padding:14px 14px 14px 0;
  font-weight:800;font-size:1.08rem;letter-spacing:-.015em;
  cursor:pointer;list-style:none;
  border-radius:var(--r-sm);
  transition:color var(--fast) var(--ease),padding-left var(--base) var(--ease);
}
.faq summary::-webkit-details-marker{display:none}
.faq summary:hover{color:var(--green-3);padding-left:8px}
.faq summary::after{
  content:"+";flex:none;
  display:grid;place-items:center;width:34px;height:34px;border-radius:50%;
  background:var(--green-mist);color:var(--green);
  font-size:1.45rem;font-weight:400;line-height:0;
  transition:transform var(--base) var(--ease),background var(--fast),color var(--fast);
}
.faq summary:hover::after{background:var(--green-pale)}
.faq details[open] summary{color:var(--green-3)}
.faq details[open] summary::after{transform:rotate(45deg);background:var(--green);color:#fff}
.faq details p{color:var(--ink-2);padding:0 0 24px;max-width:70ch}

/* Sujuv avanemine ILMA JS-ita. Kui brauser seda ei toeta, kukub reegel välja
   ja `details` töötab täpselt nagu enne. */
@supports (interpolate-size:allow-keywords){
  :root{interpolate-size:allow-keywords}
  .faq details::details-content{
    block-size:0;overflow:hidden;
    content-visibility:hidden;
    transition:block-size var(--base) var(--ease),content-visibility var(--base) allow-discrete;
  }
  .faq details[open]::details-content{block-size:auto;content-visibility:visible}
}

/* ---------------------------------------------------------------------------
   10. LÕPUKUTSE
   ------------------------------------------------------------------------ */
.final-cta{
  position:relative;overflow:hidden;
  padding:clamp(76px,9vw,116px) var(--gutter);
  text-align:center;color:#fff;
  background:
    radial-gradient(90% 120% at 50% -20%, rgba(255,255,255,.22), transparent 60%),
    linear-gradient(158deg,var(--green-4),var(--green-3) 34%,var(--green) 68%,var(--green-2));
}
.final-cta h2{font-size:var(--t-h1);max-width:20ch;margin:0 auto .5em;letter-spacing:-.032em}
.final-cta .lead,.final-cta p{color:rgba(255,255,255,.88);max-width:46ch;margin:0 auto 32px}

/* ---------------------------------------------------------------------------
   11. JALUS — JURIIDILINE IDENTITEET
   See ei ole kujunduselement. Makselahenduse ülevaataja kontrollib täpselt
   neid välju; nende puudumine on tagasilükkamise alus.
   ------------------------------------------------------------------------ */
.identity{
  max-width:var(--wrap);margin:auto;
  padding:48px var(--gutter) 60px;
  border-top:1px solid var(--line);
  color:var(--ink-2);font-size:var(--t-small);
}
.identity address{font-style:normal;line-height:1.85;max-width:78ch}
.identity address strong{color:var(--ink);font-weight:800}
.identity nav{display:flex;flex-wrap:wrap;gap:8px 24px;margin-top:18px}
.identity a{
  color:var(--ink-2);text-decoration:none;
  border-bottom:1px solid var(--line-2);padding-bottom:2px;
  transition:color var(--fast) var(--ease),border-color var(--fast) var(--ease);
}
.identity a:hover{color:var(--green);border-bottom-color:var(--green)}

/* ---------------------------------------------------------------------------
   12. LIIKUMINE — SCROLL-PÕHINE ILMUMINE ILMA JS-ITA
   `animation-timeline:view()` teeb selle, mille jaoks mujal laaditakse teek.
   JS-varulahendus (public/s/reveal.js) jääb vanemate brauserite jaoks alles.
   ------------------------------------------------------------------------ */
@media (prefers-reduced-motion:no-preference){
  @supports (animation-timeline:view()){
    .reveal-group>*,
    .products>.product,
    .audiences>span{
      animation:rise both;
      animation-timeline:view();
      animation-range:entry 2% entry 46%;
    }
    /* Astmeline viivitus tuleb VAHEMIKUST ja :nth-child()-ist, mitte
       inline-stiilist — CSP ei luba style="..." atribuuti. */
    .reveal-group>*:nth-child(3n+2),.products>.product:nth-child(3n+2){animation-range:entry 6% entry 52%}
    .reveal-group>*:nth-child(3n+3),.products>.product:nth-child(3n+3){animation-range:entry 10% entry 58%}
  }

  /* Hero tuleb sisse lehe laadimisel — üks kord, lühidalt. */
  .hero>div>*{animation:rise var(--slow) var(--ease) both}
  .hero>div>*:nth-child(2){animation-delay:70ms}
  .hero>div>*:nth-child(3){animation-delay:140ms}
  .hero>div>*:nth-child(4){animation-delay:210ms}
  .hero>.hero-art{animation:art-in 820ms var(--ease) both}
}

/* 🔴 ILMUMINE KASUTAB `translate`-i, MITTE `transform`-i.
   Põhjus on kaskaad: `animation-fill-mode:both` jätab lõppväärtuse elemendi
   peale ka pärast animatsiooni ja animatsioon võidab tavalise deklaratsiooni.
   `transform:none` tapaks seega kaardi hover-tõusu JÄÄDAVALT kohe, kui kaart
   on korra ekraanile keritud. `translate` ja `transform` on eraldi omadused ja
   liituvad — nii saab kaart ilmuda JA hoveril tõusta. */
@keyframes rise{from{opacity:0;translate:0 20px}to{opacity:1;translate:none}}
@keyframes art-in{from{opacity:0;translate:0 24px;scale:.985}to{opacity:1;translate:none;scale:none}}

/* Kleepuv päis tiheneb kerimisel. Samuti scroll-timeline, null JS. Vaikimisi
   on päisel juba oma joon — kui brauser animatsiooni ei toeta, ei jää päis
   „katki", ta on lihtsalt alati tihe. */
@supports (animation-timeline:scroll()){
  .landing-nav{animation:nav-lift linear both;animation-timeline:scroll(root);animation-range:0 140px}
  @keyframes nav-lift{
    from{background-color:rgba(251,251,248,.62);box-shadow:0 0 0 rgba(10,52,28,0)}
    to{background-color:rgba(251,251,248,.92);box-shadow:0 10px 26px -18px rgba(10,52,28,.45)}
  }
}

/* JS-varulahendus (reveal.js lisab .motion-ready juurelemendile).
   🔴 KOGU plokk on `no-preference` sees. Põhjus ei ole stiil, vaid ohutus:
   siin peidetakse sisu `opacity:0`-ga kuni IntersectionObserver ta vabastab.
   Kes on liikumise välja lülitanud, ei tohi kunagi sattuda olukorda, kus
   sisu on peidus ja vabastaja ei jooksnud. */
@media (prefers-reduced-motion:no-preference){
  .motion-ready .reveal-group:not(.is-visible)>*{opacity:0;translate:0 14px}
  .motion-ready .reveal-group>*{transition:opacity var(--slow) var(--ease),translate var(--slow) var(--ease)}
  .motion-ready .reveal-group>*:nth-child(2){transition-delay:70ms}
  .motion-ready .reveal-group>*:nth-child(3){transition-delay:140ms}
  .motion-ready .reveal-group>*:nth-child(4){transition-delay:210ms}
  .motion-ready .reveal-group>*:nth-child(5){transition-delay:280ms}
  .motion-ready .reveal-group>*:nth-child(6){transition-delay:350ms}
}

/* ---------------------------------------------------------------------------
   13. TEKSTILEHED
   ------------------------------------------------------------------------ */
.page{max-width:var(--wrap);margin:0 auto;padding:clamp(32px,4.5vw,56px) var(--gutter) clamp(72px,9vw,110px);min-height:62vh}
.page.narrow{max-width:820px}
.page>a:not(.button):not(.backlink){display:inline-flex;align-items:center;min-height:44px;font-weight:700;color:var(--ink-2);text-decoration:none}

.legal{max-width:820px}
.legal h1{font-size:var(--t-h1)}
.legal h2{margin-top:52px;font-size:var(--t-h2)}
.legal p,.legal li{color:var(--ink-2);max-width:72ch}
.legal .free-callout{margin-bottom:1.2em}
/* Hinnakiri sisulehel saab sama kaardi kui hinnasektsioonis — sama andmed,
   sama välimus, muidu tundub, et neid on kaks. */
.legal table{
  max-width:560px;margin:0 0 1.4em;
  padding:6px 20px;border-radius:var(--r-lg);
  background:var(--card);box-shadow:var(--hair),var(--shadow-1);
  border-collapse:separate;border-spacing:0;
}
.legal tbody tr:last-child th,.legal tbody tr:last-child td{border-bottom:0}
.updated{margin-top:64px;color:var(--ink-3);font-size:var(--t-small)}

/* 404 ja muud neutraalsed teated. */
.notice{
  max-width:620px;margin:auto;
  padding:clamp(64px,12vh,140px) var(--gutter);
  text-align:center;
}
.notice p{color:var(--ink-2)}
.notice .button{margin-top:12px}
/* `.eyebrow` ja `.actions` on flex-kastid — nad EI päri `text-align:center`.
   Ilma nende kahe reata seisaks 404-l eelpealkiri ja nupupaar vasakus servas,
   pealkiri aga keskel. */
/* `color` on siin kohustuslik: `.notice p` on (0,1,1) ja võidab `.eyebrow`
   (0,1,0) — ilma selleta kaotab eelpealkiri oma rohelise. */
.notice .eyebrow{margin-inline:auto;color:var(--green)}
.notice .actions{justify-content:center}

/* ---------------------------------------------------------------------------
   14. POOD — MÜÜJA PÄIS
   Ostja otsustab siin, kas müüja on päris. Seepärast on registrikood, aadress
   ja kontakt PÄISES, mitte jaluse peenkirjas.
   ------------------------------------------------------------------------ */
.shop{max-width:var(--wrap);margin:auto;padding:var(--gutter)}

.shop-head{
  position:relative;overflow:hidden;
  padding:clamp(26px,3.8vw,44px);
  margin:6px 0 clamp(24px,3.5vw,40px);
  border-radius:var(--r-xl);
  background:linear-gradient(148deg,var(--green-mist) 0%,#fff 56%,var(--paper-2) 100%);
  box-shadow:var(--hair),var(--shadow-1),var(--edge);
}
/* Pehme rohevälja nurgas — üks kiht valgust, mitte muster. */
.shop-head::after{
  content:"";position:absolute;top:-100px;right:-80px;width:320px;height:320px;border-radius:50%;
  background:radial-gradient(closest-side,rgba(18,161,80,.15),transparent);
  pointer-events:none;
}
.shop-head>*{position:relative;z-index:1}
.shop-head h1{font-size:var(--t-h1);margin-bottom:.4em}
.shop-head .shop-intro{
  margin:0 0 24px;max-width:56ch;
  color:var(--ink-2);font-size:var(--t-lead);font-weight:400;line-height:1.5;
  text-transform:none;letter-spacing:-.008em;
}

/* Rekvisiidid on faktiloend, mitte lõik: iga rida on kontrollitav väide. */
.seller-facts{
  list-style:none;padding:0;margin:0 0 20px;
  display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:8px 26px;
}
.seller-fact{
  display:flex;align-items:flex-start;gap:10px;
  color:var(--ink-2);font-size:var(--t-small);line-height:1.5;
}
.seller-fact .ico{color:var(--green);margin-top:1px}
.seller-fact a{color:var(--ink-2);text-decoration:none;border-bottom:1px solid var(--line-2)}
.seller-fact a:hover{color:var(--green);border-bottom-color:var(--green)}

.trust-row{list-style:none;padding:0;margin:0;display:flex;flex-wrap:wrap;gap:10px}
.trust-chip{
  display:inline-flex;align-items:center;gap:9px;
  padding:9px 16px;border-radius:var(--r-full);
  background:#fff;color:var(--green-3);
  font-size:var(--t-small);font-weight:750;
  box-shadow:inset 0 0 0 1px rgba(11,107,46,.15),var(--shadow-1);
}
.trust-chip .ico{width:17px;height:17px;color:var(--green-2)}

/* Korvilink päises + loendur. Loendur tuleb serverist, seega ta on olemas ka
   ilma JS-ita. */
.cart-link{
  display:inline-flex;align-items:center;gap:10px;
  min-height:48px;padding:0 18px;border-radius:var(--r-full);
  background:#fff;color:var(--green-3);
  font-weight:800;text-decoration:none;white-space:nowrap;
  box-shadow:var(--hair),var(--shadow-1);
  transition:transform var(--fast) var(--ease),box-shadow var(--base) var(--ease),color var(--fast);
}
.cart-link:hover{transform:translateY(-1px);color:var(--green);box-shadow:inset 0 0 0 1.5px var(--green-2),var(--shadow-2)}
.cart-link:active{transform:translateY(0);box-shadow:inset 0 0 0 1.5px var(--green)}
.cart-link .ico{width:21px;height:21px}
/* 320px telefonis ei mahu bränd + sõna + loendur ühele reale. Sõna kaob,
   ikoon ja number jäävad — lingi ligipääsetav nimi tuleb `aria-label`-ist,
   nii et ekraanilugeja ei kaota midagi. */
@media (max-width:360px){
  .cart-link-text{display:none}
  .cart-link{padding:0 14px}
}
.cart-count{
  display:inline-grid;place-items:center;min-width:24px;height:24px;padding:0 7px;
  border-radius:var(--r-full);
  background:var(--green);color:#fff;
  font-size:.8rem;font-weight:900;line-height:1;font-variant-numeric:tabular-nums;
}

/* Korviteade poelehel: mida sul juba on ja üks tee edasi. */
.cart-banner{
  display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:14px;
  margin:0 0 24px;padding:14px 16px 14px 22px;
  border-radius:var(--r-lg);
  background:linear-gradient(180deg,var(--green-mist),#fff);
  box-shadow:inset 0 0 0 1px rgba(11,107,46,.14),var(--shadow-1);
}
.cart-banner-text{color:var(--green-3);font-weight:800;font-variant-numeric:tabular-nums}

/* ---------------------------------------------------------------------------
   15. TOOTEKAARDID
   Lehe kalleim vara: müüja näitab neid oma klientidele. Kaart peab näima
   vitriinina, mitte tabelireana.
   ------------------------------------------------------------------------ */
.products{display:grid;grid-template-columns:repeat(auto-fill,minmax(268px,1fr));gap:24px}

.product{
  position:relative;display:flex;flex-direction:column;overflow:hidden;
  padding:0;border-radius:var(--r-xl);
  background:linear-gradient(180deg,var(--card),#FBFCF9);
  box-shadow:var(--hair),var(--shadow-1),var(--edge);
  transition:transform var(--base) var(--ease),box-shadow var(--base) var(--ease);
}
.product:hover{transform:translateY(-6px);box-shadow:var(--hair-2),var(--shadow-3),var(--edge)}

/* Vitriin: radiaalne helk vasakul üleval annab suuna, diagonaalne gradient
   sügavuse. `--art-tint` vahetub toote kaupa, nii et võre näeb välja
   kureeritud, mitte genereeritud. */
.product-art{
  --art-tint:var(--green-mist);
  --art-deep:#E9F1E6;
  position:relative;overflow:hidden;
  height:212px;margin:0;
  display:grid;place-items:center;
  color:var(--green-3);
  background:
    radial-gradient(115% 88% at 26% 6%, rgba(255,255,255,.96), rgba(255,255,255,0) 58%),
    linear-gradient(158deg,var(--art-tint) 0%,var(--art-deep) 54%,var(--paper-3) 100%);
  box-shadow:inset 0 -1px 0 var(--line);
}
.product-art-1{--art-tint:#F1F8F3;--art-deep:#E6F0E7}
.product-art-2{--art-tint:#F6F5EE;--art-deep:#EDEDE1}
.product-art-3{--art-tint:#F0F6F6;--art-deep:#E3EEEE}
.product-art-4{--art-tint:#F7F3EC;--art-deep:#EFE7DA}
.product-art-5{--art-tint:#F2F5F9;--art-deep:#E5EAF1}
.product-art-6{--art-tint:#F5F2F6;--art-deep:#EAE4EC}

/* Kontaktvari toote all — ese SEISAB pinnal, ei hõlju tühjuses. See üksik
   ellips teeb kaardile rohkem kui ükski raam. */
.product-art::after{
  content:"";position:absolute;left:50%;bottom:26px;
  width:140px;height:16px;margin-left:-70px;border-radius:50%;
  background:radial-gradient(closest-side,rgba(10,52,28,.20),rgba(10,52,28,0));
  transition:transform var(--slow) var(--ease),opacity var(--slow) var(--ease);
}
.product-art svg{
  position:relative;width:132px;height:auto;
  filter:drop-shadow(0 6px 10px rgba(10,52,28,.10));
  transition:transform var(--slow) var(--ease);
}
.product-art svg :is(path,circle,ellipse,line,polyline,polygon,rect){
  fill:none;stroke:currentColor;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;
}
.product:hover .product-art svg{transform:translateY(-6px) scale(1.05) rotate(-1.5deg)}
.product:hover .product-art::after{transform:scaleX(1.14);opacity:.7}

.product-name,.product-desc,.product .price,.product .stock,.product-in-cart{padding-inline:20px}
/* Nimel ja kirjeldusel on MIINIMUMKÕRGUS kahe ja kolme rea jagu. See ei ole
   pedantsus: ilma selleta algab hinnajoon igal kaardil eri kõrguselt ja võre
   näeb välja juhuslik. Kaks rida nime + kolm rida teksti katab pea kõik
   päris tootenimed; ülejäänu venitab `flex:1`. */
.product-name{min-height:2.5em;font-size:1.14rem;margin:20px 0 8px;letter-spacing:-.018em}
/* Tootenimi on LINK tootelehele (`/<slug>/toode/<slug>`).
   Vaikimisi oleks ta roheline ja alla joonitud — kaardivõrel tähendaks see
   kümmet rohelist alla joonitud pealkirja kõrvuti ja pealkirjad lakkaksid
   olemast pealkirjad. Seepärast kannab ta tindivärvi ja saab joone alles
   hiire all; `:focus-visible` rõngas tuleb üldreeglist ja teda EI OLE siin
   maha võetud, sest klaviatuuriga liikuja peab nägema, kus ta on.
   Puuteala: rida on 1.14rem × 1.2 ≈ 22px, kaart ise on suur ja nupp „Lisa
   korvi" on 60px — doktriini 88px nõue puudutab KASSAT, mitte kataloogi
   teisest sisenemisteed. */
.product-name>.product-link{color:inherit;text-decoration:none}
.product-name>.product-link:hover{color:var(--green-3);text-decoration:underline}
.product-desc{flex:1;min-height:4.65em;color:var(--ink-2);font-size:var(--t-small);line-height:1.55;margin-bottom:16px}

/* Hind eraldatakse kirjeldusest TÄISLAIA juuksekarvaga: ülal on jutt,
   all on äri. */
.product .price{
  margin:0;padding-top:16px;
  border-top:1px solid var(--line);
  font-size:1.55rem;font-weight:900;letter-spacing:-.03em;line-height:1.2;
}
.product .stock{
  display:flex;align-items:center;gap:8px;
  margin:6px 0 0;font-size:var(--t-small);font-weight:700;
}
.product .stock::before{content:"";flex:none;width:7px;height:7px;border-radius:50%;background:currentColor}
.stock-in{color:var(--green-3)}
.stock-in::before{box-shadow:0 0 0 3px rgba(18,161,80,.16)}
.stock-low{color:var(--amber)}
.stock-low::before{box-shadow:0 0 0 3px rgba(180,83,9,.14)}
.stock-out{color:var(--ink-3)}

.product-in-cart{margin:8px 0 0;color:var(--green-3);font-size:var(--t-small);font-weight:700}
.product-in-cart a{color:var(--green-3)}

.product-add{margin-top:auto;padding:18px 20px 20px}
.product-add .button{width:100%;min-height:60px}

/* Otsas toode ei tohi näida saadavana — aga teda ei peideta, sest ostja peab
   nägema, et müüjal see toode ÜLDSE on. */
.product-soldout .product-art{filter:saturate(.4);opacity:.78}
.product-soldout:hover{transform:none;box-shadow:var(--hair),var(--shadow-1),var(--edge)}
.product-soldout .price{color:var(--ink-2)}

.shop-empty{
  grid-column:1/-1;
  padding:clamp(40px,7vw,72px) 32px;text-align:center;
}

/* ---------------------------------------------------------------------------
   16. SAMMUNÄIDIK
   Ostja peab iga hetk teadma, mitu sammu on ees.
   ------------------------------------------------------------------------ */
.checkout-steps{
  display:flex;align-items:center;
  list-style:none;padding:0;margin:10px 0 28px;
}
.checkout-step{
  display:flex;align-items:center;gap:10px;
  color:var(--ink-3);font-size:var(--t-small);font-weight:700;white-space:nowrap;
}
.checkout-step:not(:last-child){flex:1}
.checkout-step:not(:last-child)::after{
  content:"";flex:1;height:2px;min-width:16px;margin:0 14px;
  border-radius:2px;background:var(--line-2);
}
/* Nimi tohib kokku suruda enne kui number — number on ainus, mis ütleb
   „mitmes samm", ja tema kadumine teeks näidiku mõttetuks. */
.checkout-step-name{min-width:0;overflow:hidden;text-overflow:ellipsis}
.checkout-step-no{
  flex:none;display:grid;place-items:center;
  width:30px;height:30px;border-radius:50%;
  background:#fff;color:var(--ink-3);
  font-size:.88rem;font-weight:900;line-height:1;
  box-shadow:inset 0 0 0 1.5px var(--line-2);
}
.checkout-step.is-done{color:var(--green-3)}
.checkout-step.is-done .checkout-step-no{background:var(--green);color:#fff;box-shadow:none}
.checkout-step.is-done::after{background:var(--green-2)}
.checkout-step.is-current{color:var(--ink)}
.checkout-step.is-current .checkout-step-no{background:var(--green-pale);color:var(--green-3);box-shadow:inset 0 0 0 2px var(--green)}
/* Lai näidik on lauaarvutis; telefonis asendab teda üherealine tekst. */
.checkout-progress{
  display:none;
  margin:0 0 22px;padding:10px 16px;border-radius:var(--r-full);
  background:var(--green-mist);color:var(--green-3);
  font-size:var(--t-small);font-weight:800;
  box-shadow:inset 0 0 0 1px rgba(11,107,46,.14);
}

/* ---------------------------------------------------------------------------
   17. KORV
   ------------------------------------------------------------------------ */
.cart-list{display:block;margin-bottom:22px}
.cart-row{
  display:grid;
  grid-template-columns:minmax(0,1fr) auto auto;
  grid-template-areas:"main qty total" "remove qty total";
  column-gap:24px;row-gap:6px;align-items:center;
  padding:20px 22px;margin-bottom:12px;
  border-radius:var(--r-lg);
  background:var(--card);
  box-shadow:var(--hair),var(--shadow-1);
  transition:box-shadow var(--base) var(--ease)}
.cart-row:hover{box-shadow:var(--hair-2),var(--shadow-2)}
.cart-row-main{grid-area:main}
/* Silt kuulub välja KOHALE, mitte kõrvale. Vormis on peidetud väli, silt,
   number ja nupp — grid paneb sildi numbri peale ja nupu numbri kõrvale,
   ilma et markupis oleks lisamähist. */
.cart-row-form{
  grid-area:qty;
  display:grid;grid-template-columns:auto auto;
  align-items:end;column-gap:12px;
}
.cart-row-form .button{grid-column:2;grid-row:2}
.cart-row-total{grid-area:total;margin:0;font-size:1.32rem;font-weight:900;letter-spacing:-.025em;text-align:right}
.cart-row-remove{grid-area:remove}
.cart-row-name{margin:0 0 4px;font-size:1.12rem}
.cart-row-name a{color:var(--ink);text-decoration:none}
.cart-row-name a:hover{color:var(--green)}
.cart-row-unit{margin:0;color:var(--ink-3);font-size:var(--t-small)}
.cart-row-warn{margin:6px 0 0;color:var(--amber);font-size:var(--t-small);font-weight:750}
.cart-qty{grid-column:1;grid-row:1;font-size:var(--t-micro);font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3)}
.cart-qty-input{
  grid-column:1;grid-row:2;
  display:block;width:88px;min-height:56px;margin-top:6px;padding:12px;
  border:1px solid var(--line-2);border-radius:var(--r-sm);
  background:#fff;text-align:center;font-size:1.1rem;font-weight:800;
  box-shadow:inset 0 1px 2px rgba(10,52,28,.05);
  transition:border-color var(--fast),box-shadow var(--fast);
}
.cart-qty-input:hover{border-color:var(--line)}
.cart-qty-input:focus{border-color:var(--green);box-shadow:inset 0 1px 2px rgba(10,52,28,.05),0 0 0 4px var(--green-pale)}

/* Kokkuvõte on kaart, mitte rida. Summa on lehe suurim number. */
.cart-summary{
  padding:clamp(22px,3vw,28px);
  border-radius:var(--r-xl);
  background:linear-gradient(180deg,#fff,var(--green-mist));
  box-shadow:var(--hair),var(--shadow-2),var(--edge);
  display:grid;gap:14px;justify-items:stretch;
}
.cart-total{
  display:flex;justify-content:space-between;align-items:center;gap:20px;
  font-weight:750;font-size:1.08rem;color:var(--ink-2);
}
.cart-total strong{
  color:var(--ink);
  font-size:clamp(1.9rem,5.5vw,2.4rem);font-weight:900;letter-spacing:-.035em;line-height:1;
}
.cart-note{margin:0;color:var(--ink-3);font-size:var(--t-small)}
.cart-summary .button{width:100%;min-height:88px;font-size:1.1rem}
.cart-summary .backlink{justify-content:center}

.empty{
  padding:clamp(40px,6vw,64px) 32px;text-align:center;
  border-radius:var(--r-xl);
  background:linear-gradient(180deg,#fff,var(--paper-2));
  box-shadow:inset 0 0 0 1px var(--line),var(--shadow-1);
  color:var(--ink-2);
}
.empty::before{
  content:"";display:block;width:52px;height:52px;margin:0 auto 20px;border-radius:16px;
  background:var(--green-mist);box-shadow:inset 0 0 0 1px rgba(11,107,46,.14);
}
.empty h2{color:var(--ink)}
.empty .button{margin-top:8px}

/* ---------------------------------------------------------------------------
   18. KASSA (CHECKOUT)
   Doktriin: puuteala >= 88px. Telefon on siin PEAMINE seade, mitte erand.
   ------------------------------------------------------------------------ */
/* Kaks klassi, sest `.page.narrow` on kaks klassi: kassaleht on kahe veeruga
   ja 820px oleks kokkuvõtte jaoks liiga kitsas. */
.page.narrow.checkout-page{max-width:1080px}
.checkout-layout{display:grid;grid-template-columns:minmax(0,1fr) 344px;gap:28px;align-items:start}
.checkout{display:grid;gap:20px;align-content:start}

.field{display:block}
.field-label{display:block;font-weight:750;margin-bottom:8px}
.field-input{
  display:block;width:100%;min-height:88px;padding:18px 20px;
  border:1px solid var(--line-2);border-radius:var(--r-md);
  background:#fff;font-size:1.06rem;
  box-shadow:inset 0 1px 2px rgba(10,52,28,.05);
  transition:border-color var(--fast),box-shadow var(--fast);
}
.field-input:hover{border-color:var(--line)}
.field-input:focus{border-color:var(--green);box-shadow:inset 0 1px 2px rgba(10,52,28,.04),0 0 0 4px var(--green-pale)}
.field-hint{display:block;margin-top:8px;color:var(--ink-3);font-size:var(--t-small);line-height:1.5}
.field-error{margin:8px 0 0;color:var(--red);font-size:var(--t-small);font-weight:750}
.field-invalid .field-input{border-color:var(--red);box-shadow:inset 0 1px 2px rgba(10,52,28,.04),0 0 0 4px var(--red-pale)}
/* `:user-invalid` alles siis, kui kasutaja on väljaga TEGELENUD — mitte punane
   vorm kohe lehe avamisel. */
.field-input:user-invalid{border-color:var(--red);box-shadow:0 0 0 4px var(--red-pale)}

.checkout-company,.field-group{
  padding:8px 22px 20px;border:0;border-radius:var(--r-md);
  background:var(--card);box-shadow:var(--hair),var(--shadow-1);
}
.field-group{padding-top:20px}
.field-group.field-invalid{box-shadow:inset 0 0 0 1.5px var(--red-line),var(--shadow-1)}
.checkout legend{padding:0;margin-bottom:14px;font-weight:800;font-size:1.05rem}
.checkout-company summary{
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  min-height:88px;margin:0 -22px;padding:0 22px;
  font-weight:800;cursor:pointer;list-style:none;
}
.checkout-company summary::-webkit-details-marker{display:none}
.checkout-company summary::after{
  content:"+";flex:none;display:grid;place-items:center;
  width:34px;height:34px;border-radius:50%;
  background:var(--green-mist);color:var(--green);
  font-size:1.4rem;font-weight:400;line-height:0;
  transition:transform var(--base) var(--ease),background var(--fast),color var(--fast);
}
.checkout-company summary:hover::after{background:var(--green-pale)}
.checkout-company[open] summary::after{transform:rotate(45deg);background:var(--green);color:#fff}
/* Suletult ei tohi kaardi alla jääda tühja põhja — muidu näeb kokkuklapitud
   plokk välja nagu tühi kast. */
.checkout-company:not([open]){padding-bottom:8px}
.checkout-company .field+.field{margin-top:16px}

/* Kättesaamise valik on KAART, mitte raadionupp teksti kõrval. Sõrmega
   turuletil tabab kaarti; 20-pikslist ringi ei taba. */
.choice{
  display:flex;align-items:center;gap:14px;
  min-height:88px;padding:16px 18px;
  border-radius:var(--r-md);
  background:#fff;
  box-shadow:inset 0 0 0 1.5px var(--line);
  cursor:pointer;
  transition:box-shadow var(--fast) var(--ease),background var(--fast) var(--ease);
}
.choice+.choice{margin-top:10px}
.choice:hover{background:var(--green-mist);box-shadow:inset 0 0 0 1.5px var(--line-2)}
.choice:has(input:checked){background:var(--green-pale);box-shadow:inset 0 0 0 2px var(--green)}
.choice:focus-within{outline:3px solid var(--ring);outline-offset:2px}
.choice input{flex:none;width:26px;height:26px;margin:0;accent-color:var(--green)}
.choice-text{display:grid;gap:3px}
.choice-label{font-weight:800;letter-spacing:-.012em}
.choice-hint{color:var(--ink-3);font-size:var(--t-small);line-height:1.4}

.checkout-submit{width:100%;min-height:88px;font-size:1.1rem;margin-top:4px}
.checkout-legal{margin:0;color:var(--ink-3);font-size:var(--t-small);line-height:1.55}

/* Kokkuvõte kõrval jääb kerimisel nähtavaks — ostja ei tohi kaotada silmist,
   mille eest ta maksab. */
.order-summary{
  position:sticky;top:22px;
  padding:24px;border-radius:var(--r-xl);
  background:linear-gradient(180deg,var(--card),var(--green-mist));
  box-shadow:var(--hair),var(--shadow-2),var(--edge);
}
.order-summary-title{
  font-size:var(--t-micro);text-transform:uppercase;letter-spacing:.14em;
  color:var(--ink-3);font-weight:800;margin-bottom:14px;
}
.order-summary .cart-total{
  margin-top:14px;padding-top:16px;
  border-top:1px solid var(--line);
  font-size:1rem;
}
.order-summary .cart-total strong{font-size:1.7rem}
.order-summary-note{
  display:flex;align-items:flex-start;gap:10px;
  margin:14px 0 0;color:var(--ink-2);font-size:var(--t-small);line-height:1.5;
}
.order-summary-note .ico{color:var(--green);margin-top:2px}
.order-summary .backlink{margin-top:12px}

/* ---------------------------------------------------------------------------
   19. TEATED
   ------------------------------------------------------------------------ */
.error,.demo-banner{
  position:relative;
  padding:18px 22px 18px 24px;
  border-radius:var(--r-md);
  margin-bottom:26px;
  line-height:1.5;
}
/* Vasak värviriba kannab teate raskuse; äär ümber teeks kastikese. */
.error::before,.demo-banner::before{
  content:"";position:absolute;left:0;top:10px;bottom:10px;width:4px;border-radius:0 4px 4px 0;
  background:currentColor;
}
.error{background:var(--red-pale);color:var(--red);box-shadow:inset 0 0 0 1px var(--red-line)}
.error-title{margin:0;font-weight:850;font-size:1.05rem}
.error-list{margin:10px 0 0;padding-left:20px}
.error-list a{color:var(--red);font-weight:700}
.error p:not(.error-title){margin:8px 0 0;color:var(--red);font-weight:400}

.demo-banner{
  display:flex;align-items:center;flex-wrap:wrap;gap:12px;
  background:var(--amber-pale);color:var(--amber);
  box-shadow:inset 0 0 0 1px var(--amber-line);
}
.demo-banner-tag{
  flex:none;padding:4px 10px;border-radius:var(--r-sm);
  background:var(--amber);color:#fff;
  font-size:var(--t-micro);font-weight:900;letter-spacing:.1em;
}
.demo-banner-text{font-size:var(--t-small);font-weight:650}

/* ---------------------------------------------------------------------------
   20. MAKSELEHT
   ------------------------------------------------------------------------ */
.payment{max-width:760px}
.pay-seller,.pay-order,.pay-banks{
  margin-bottom:22px;padding:clamp(20px,3vw,28px);
  border-radius:var(--r-xl);
  background:var(--card);
  box-shadow:var(--hair),var(--shadow-1),var(--edge);
}
.pay-order h1{font-size:var(--t-h2);margin-bottom:.3em}
.pay-order-ref{margin:0 0 6px;color:var(--ink-3);font-size:var(--t-small)}
.pay-order .cart-total{margin-top:6px;padding-top:16px;border-top:1px solid var(--line)}
.pay-vat-note{margin:12px 0 0;color:var(--ink-3);font-size:var(--t-small)}
.pay-banks h2{font-size:1.2rem}

/* Osapool (müüja / ostja) — sama plokk makselehel ja kviitungil. */
/* `min-width:0` ei ole kaunistus: `.receipt-parties` on grid ja grid-elemendi
   vaikimisi `min-width:auto` tähendab, et üks pikk katkematu e-posti aadress
   ajab veeru laiemaks kui `1fr` — kviitung läheks paberil viltu. */
.party{display:grid;min-width:0}
.party-role{
  font-size:var(--t-micro);text-transform:uppercase;letter-spacing:.14em;
  color:var(--ink-3);font-weight:800;margin-bottom:10px;
}
.party-body{display:grid;gap:2px;font-style:normal;line-height:1.55}
.party-name{font-size:1.15rem;font-weight:850;color:var(--ink);margin-bottom:4px;letter-spacing:-.018em}
.party-line{color:var(--ink-2);font-size:var(--t-small);overflow-wrap:anywhere}
.party-line a{color:var(--ink-2);text-decoration:none;border-bottom:1px solid var(--line-2)}
.party-line a:hover{color:var(--green);border-bottom-color:var(--green)}

/* Tellimuse read: nimi ja kogus vasakule, summa paremale ühelaiuste
   numbritega. Kolm välja, kaks veergu — sest summa peab olema üksinda. */
.order-lines{list-style:none;padding:0;margin:18px 0 0}
.order-line{
  display:grid;grid-template-columns:minmax(0,1fr) auto;
  column-gap:18px;row-gap:2px;align-items:center;
  padding:12px 0;border-bottom:1px solid var(--line);
}
.order-line:last-child{border-bottom:0}
.order-line-name{grid-column:1;grid-row:1;font-weight:750;letter-spacing:-.01em}
.order-line-qty{grid-column:1;grid-row:2;color:var(--ink-3);font-size:var(--t-small)}
.order-line-total{grid-column:2;grid-row:1/3;font-weight:850;letter-spacing:-.015em;white-space:nowrap}
.order-line-discount{grid-column:1;color:var(--green-3);font-size:var(--t-micro)}

/* Tellimuse detail on üleandmisleht: sildid jäävad vaikseks, väärtused on
   skannitavad. Grid murrab telefonis ise üheks veeruks, sest fikseeritud
   laiusega isikuandmete veerg lükkaks pika e-posti ekraanist välja. */
.order-detail-facts{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));
  gap:12px;margin:0 0 24px;
}
.order-detail-facts>div{min-width:0;padding:14px 16px;border-radius:var(--r-md);background:var(--paper-2);box-shadow:var(--hair)}
.order-detail-facts dt{color:var(--ink-3);font-size:var(--t-micro);font-weight:800;text-transform:uppercase;letter-spacing:.08em}
.order-detail-facts dd{margin:4px 0 0;font-weight:750;overflow-wrap:anywhere}
.order-detail-buyer,.order-detail-lines{margin-top:28px}
.order-detail-total{display:flex;justify-content:space-between;gap:20px;padding-top:16px;border-top:2px solid var(--ink);font-size:1.15rem}
.order-detail-total strong{font-variant-numeric:tabular-nums;white-space:nowrap}

.banks{display:grid;grid-template-columns:repeat(2,1fr);gap:14px}
.bank{
  position:relative;overflow:hidden;
  min-height:88px;padding:14px 18px;
  border:0;border-radius:var(--r-md);
  background:linear-gradient(180deg,#fff,#FBFCFA);
  color:var(--ink);
  font-family:var(--sans);font-size:1.08rem;font-weight:800;letter-spacing:-.018em;
  display:flex;align-items:center;justify-content:flex-start;gap:14px;
  cursor:pointer;
  box-shadow:var(--hair),var(--shadow-1);
  transition:transform var(--fast) var(--ease),box-shadow var(--base) var(--ease);
}
.bank:hover{transform:translateY(-3px);box-shadow:var(--hair-2),var(--shadow-2)}
.bank:active{transform:translateY(0);box-shadow:inset 0 2px 5px rgba(10,52,28,.14)}
/* Panga oma värv on VÄRVIKIIP ja all peen riba — mitte terve nupp. Nii jääb
   valik ühtseks komplektiks, aga iga pank on ühe pilguga ära tuntav.
   Riba on alati täislaiune ja muutub hoveril tugevamaks: poolik riba näeks
   välja nagu renderdusviga, mitte nagu kavatsus. */
.bank::after{
  content:"";position:absolute;inset:auto 0 0;height:3px;
  background:var(--bank,var(--green-2));
  opacity:.4;
  transition:opacity var(--base) var(--ease),height var(--base) var(--ease);
}
.bank:hover::after,.bank:focus-visible::after{opacity:1;height:5px}
.bank svg{flex:none;width:36px;height:36px}
.bank svg rect{fill:var(--bank,var(--green));stroke:none}
/* Üldine „pluss" märk ei tähenda pangavalikus midagi ja loeb kui „lisa".
   Kiip ilma glüüfita on aus värvitähis. */
.bank svg path{display:none}
.bank-name{white-space:nowrap}
.bank-swedbank{--bank:#F35B18}
.bank-seb{--bank:#55A51C}
.bank-lhv{--bank:#1A1A1A}
.bank-coop{--bank:#E11F2A}
.bank-luminor{--bank:#702082}

.secure-note{
  display:flex;align-items:flex-start;justify-content:center;gap:10px;
  margin:20px 0 0;color:var(--ink-3);font-size:var(--t-small);line-height:1.5;
}
.secure-note .ico{color:var(--green);margin-top:2px}

/* ---------------------------------------------------------------------------
   21. ÕNNESTUMINE
   UX-SPETS: see ekraan peab päikese käes turuletil ÜHE pilguga läbi minema.
   Seepärast on ta täisekraan, roheline ja lehe suurima kirjaga.
   ------------------------------------------------------------------------ */
.success{
  min-height:92vh;
  min-height:92svh;
  color:#fff;text-align:center;
  padding:clamp(56px,9vh,92px) max(var(--gutter),calc((100vw - 680px)/2));
  background:
    radial-gradient(80% 90% at 50% 0%, rgba(255,255,255,.20), transparent 62%),
    linear-gradient(158deg,var(--green-4),var(--green-3) 30%,var(--green) 66%,var(--green-2));
  animation:success-in var(--slow) var(--ease);
}
.success .eyebrow{color:rgba(255,255,255,.85);margin-inline:auto}
.success-mark{
  margin:0 auto 26px;width:116px;height:116px;
  display:grid;place-items:center;border-radius:50%;
  background:#fff;color:var(--green);
  font-size:4rem;font-weight:900;line-height:1;
  /* Kontsentrilised rõngad varjuna: kinnitusmärk KIIRGAB, mitte ei istu. */
  box-shadow:
    0 0 0 10px rgba(255,255,255,.16),
    0 0 0 24px rgba(255,255,255,.08),
    0 18px 40px rgba(3,32,14,.34);
  animation:success-pulse 900ms var(--ease);
}
.success h1{font-size:var(--t-hero);letter-spacing:-.04em;margin-bottom:.15em}
.success-total{font-size:clamp(2.2rem,7vw,3rem);font-weight:900;letter-spacing:-.04em;margin-bottom:.3em}
.success-ref,.success-seller,.success-mail{color:rgba(255,255,255,.9)}
.success-ref{font-size:var(--t-small);color:rgba(255,255,255,.76)}
.success-seller strong,.success-mail strong{color:#fff}
.success .order-lines{
  text-align:left;margin:26px 0;padding:4px 22px;
  border-radius:var(--r-lg);
  background:rgba(255,255,255,.10);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.18);
}
.success .order-line{border-bottom-color:rgba(255,255,255,.20)}
.success .order-line-qty{color:rgba(255,255,255,.68)}
.success-actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:12px 22px;margin-top:22px}
.success-actions .button{min-height:64px}
.success-back{color:rgba(255,255,255,.86)}
.success-back:hover{color:#fff}
@keyframes success-in{from{opacity:.25}to{opacity:1}}
@keyframes success-pulse{0%{transform:scale(.62)}58%{transform:scale(1.08)}100%{transform:scale(1)}}

/* ---------------------------------------------------------------------------
   22. KVIITUNG
   Kviitung on raamatupidamisdokument. Ta peab välja nägema nagu dokument,
   mitte nagu veebileht — ja ta peab printima puhtalt.
   ------------------------------------------------------------------------ */
.receipt{
  position:relative;overflow:hidden;
  max-width:820px;margin:44px auto;
  padding:clamp(26px,4vw,56px);
  background:#fff;border-radius:var(--r-lg);
  box-shadow:var(--hair),var(--shadow-2);
}
/* Roheline kirjaplangi riba ülaservas. */
.receipt::before{content:"";position:absolute;inset:0 0 auto;height:4px;background:linear-gradient(90deg,var(--green-3),var(--green-2))}
.receipt-head{
  display:flex;align-items:flex-start;justify-content:space-between;gap:26px;flex-wrap:wrap;
  padding-bottom:22px;margin-bottom:30px;
  border-bottom:2px solid var(--ink);
}
.receipt-head-left{min-width:0}
.receipt .brand{margin:0 0 12px;font-size:1.12rem}
.receipt-title{font-size:clamp(1.7rem,4vw,2.2rem);margin:0}
.receipt-ref{display:grid;gap:4px;margin:0;min-width:210px}
.receipt-ref-row{display:flex;justify-content:space-between;gap:20px;font-size:var(--t-small)}
.receipt-ref-row dt{color:var(--ink-3)}
.receipt-ref-row dd{margin:0;font-weight:800;color:var(--ink);font-variant-numeric:tabular-nums}

.receipt-parties{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:24px;margin:0 0 32px}

.receipt-table{margin-bottom:26px}
.receipt-table-caption{
  text-align:left;padding:0 0 10px;
  font-size:var(--t-micro);text-transform:uppercase;letter-spacing:.14em;
  color:var(--ink-3);font-weight:800;
}
.receipt-table thead th{
  font-size:var(--t-micro);text-transform:uppercase;letter-spacing:.1em;
  color:var(--ink-3);font-weight:800;
}
.receipt-table td:not(:first-child),.receipt-table th:not(:first-child){text-align:right}
.receipt-table tbody td{font-variant-numeric:tabular-nums}
.receipt-table tfoot th{
  padding-top:18px;
  border-top:2px solid var(--ink);border-bottom:0;
  font-size:1.14rem;text-transform:none;letter-spacing:-.02em;
  color:var(--ink);font-weight:900;
}
.receipt-notes{margin-top:8px}
.receipt-note{margin:0 0 6px;color:var(--ink-3);font-size:var(--t-small);line-height:1.55}
/* `.print-button` on nüüd VIHJE, mitte nupp — brauseri prindikäsku ei saa
   CSP-turvaliselt ilma inline-skriptita käivitada. */
.print-button{margin-top:28px;color:var(--ink-3);font-size:var(--t-small)}

/* ═══════════════════════════════════════════════════════════════════════════
   23. KASSA (POS) — ALGUS
   🔴 SEE MARKER ON MASINALOETAV. `scripts/check-pos-contract.sh` loeb kõike
   „23. KASSA (POS) — ALGUS" ja „23. KASSA (POS) — LÕPP" vahelt ja kukub, kui
   leiab siit `overflow:auto|scroll`, `position:fixed`, `max-height`,
   `height:100%` või `contain:`. Ära nihuta markereid.

   KOLM KIHTI, MIS EI VAHETA KUNAGI KOHTA (UX-SPETS §5.1):
     1. `.pos-head`  — kleepuv. 56 px, testrežiimis 94 px. Sisu ei saa kasvada.
     2. `.pos-body`  — AINUS koht, mille sisu kasvab. Tema kerija on `<html>`.
     3. `.pos-bottom`— kleepuv. 144 px TÜHJA korviga, 144 px viiekümne reaga.

   KERIMISTÕESTUS ÜHE LAUSEGA: kassateel ei ole ÜHTEGI `overflow` deklaratsiooni
   ja ei ühtegi kõrguse lage. Kleepuvus ei loo kerimiskonteinerit. Seega on
   kerijaid täpselt üks — vaateava.
   ------------------------------------------------------------------------ */

/* --- 23.1 KEST ----------------------------------------------------------- */
/* 🔴 FLEX, MITTE VÕRE. ÄRA ÜHTLUSTA TAGASI VÕREKS.
   Võre-elemendi `position:sticky` sisalduskast ON tema enda võre-ala. `auto`-real
   seisval päisel ei ole seal ühtegi pikslit liikumisruumi — ta kerib minema ja
   kleepumist EI TOIMU. Flex-konteineris on kleepuva lapse sisalduskast kogu
   konteineri sisukast, seega päis kleepub kogu lehe ulatuses. Sama lõks on repos
   juba elus: `.testmode-strip{position:sticky}` (osa 34) on `.app-shell` võre
   laps ja tema kleepuvus on seetõttu mõjuta.

   🔴 SIIA EI TOHI KUNAGI TULLA `transform`, `filter`, `backdrop-filter`,
   `perspective`, `will-change` ega `contain:paint|layout`. Iga neist teeks
   `.admin-nav` fixed-riiulist kesta lapse ja tõstaks menüü keset lehte.
   (Sama hoiatus on app.css:3160 ja 2873.) */
.pos-shell{
  display:flex;flex-direction:column;
  min-height:100vh;min-height:100svh;min-height:100dvh;
  --pos-head:56px;      /* riba enda kõrgus, testribata */
  --pos-tile:92px;      /* UX-SPETS §5.1 */
  --pos-bar:144px;      /* UX-SPETS §5.1 — KONSTANT, mitte funktsioon korvist */
  --pos-gap:12px;
  /* Koguse nupp plaadil. 60 px = UX-SPETSi SAGEDANE klass. 320–359 px ekraanil
     kahaneb 52-le, sest muidu jääks `−` ja `+` serva vahe alla MIL-STD-1472H
     nõutud 32 px: (320−32−12)/2 = 138 px plaat, miinus 2×60 = 18 px. */
  --pos-step:60px;
  background:linear-gradient(180deg,var(--paper) 0 62%,rgba(232,238,231,.55));
}
/* Vaatekonteiner nimetab oma `display` ise, mistõttu peab `[hidden]` olema
   tugevam reegel. Brauseri vaikestiil üksi kaotaks sellele deklaratsioonile. */
.pos-view[hidden]{display:none}
.pos-view{display:flex;flex:1 1 auto;flex-direction:column;min-width:0}
.pos-line[hidden]{display:none}
.pos-lines[hidden],.empty-first-step[hidden]{display:none}
.pos-body{
  display:flex;flex-direction:column;gap:clamp(14px,2vw,20px);
  flex:1 1 auto;
  padding:8px var(--gutter) 0;
}
.pos-body>*{min-width:0}
/* Ainus koht, kus tühi ruum täidetakse: peategelane venib, kaunistus mitte.
   Sama leping, mis app.css:2462. Lauaarvutis on see AINUS asi, mis hoiab ära
   auditi kirjeldatud „450 px tühja tausta" siis, kui tooteid on kolm. */
.pos-body>:is(.pos-tape,.pos-lines,.empty-first-step){flex:1 1 auto}

/* Ankur ei tohi jääda kleepuva kihi alla (WCAG 2.2 SC 2.4.11). Arvud on
   käsitsi, sest `html` ei näe `.pos-shell` muutujaid. 144+12 = 156 ≥ UX-SPETS
   §5.3 nõutud 152 px. `env()`-i EI OLE: `viewport-fit=cover` ei ole meta-sildis
   ja seetõttu on paigutusvaateava juba turvaalast seespool. */
html:has(.pos-shell){scroll-padding-top:64px;scroll-padding-bottom:156px}
html:has(.pos-shell .testmode-strip){scroll-padding-top:102px}

/* --- 23.2 PÄIS: testriba JA 56 px riba ÜHE kleepuva elemendina ------------ */
/* 🔴 MIKS RIBA ON PÄISE SEES, MITTE ERALDI KIHT.
   Kaks eraldi kleepuvat elementi nõuavad, et teine teaks esimese TÄPSET
   kõrgust (`top:38px`). Aga `.testmode-strip` on `flex-wrap:wrap` ja tema tekst
   MURDUB 375 px peal teisele reale — siis on ta 59 px ja päis kataks riba
   alumise serva. Üks kleepuv element ei tea kõrgusi ega vaja neid.
   Kõrvalmõju on VÕIT: testriba on nüüd püsivalt ekraanil, mitte ainult lehe
   ülaservas. Otsus #27 („võimatu mitte märgata") kehtib tugevamalt kui enne. */
/* 🔴 KLEEPUV PÄIS PEAB OLEMA LÄBIPAISTMATU KOGU ULATUSES.
   Mõõdetud 15.08.2026: riba lõppes 39 px juures, otsinguriba algas 55 px
   juures — VAHEL OLI 16 px LÄBIPAISTVAT VÖÖTI, kust kerivad tooteread ja
   lindi read läbi paistsid.
   Põhjus oli proosaline: `.testmode-strip` on `<p>` ja kandis lõigu
   vaikemarginit. `.pos-head .testmode-strip` nullis ainult `position`-i ja
   `z-index`-i, mitte marginit. Taust päisel on teine lukk — ükski tulevane
   vahe ei saa enam auku teha. */
.pos-head{position:sticky;top:0;z-index:50;background:var(--paper)}
.pos-head .testmode-strip{position:static;z-index:auto;margin:0}
.pos-bar{
  display:grid;grid-template-columns:44px minmax(0,1fr) 44px;
  align-items:center;
  min-height:var(--pos-head);
  padding-inline:max(6px,calc(var(--gutter) - 14px));
  background:rgba(251,251,248,.94);
  backdrop-filter:blur(14px) saturate(1.5);
  -webkit-backdrop-filter:blur(14px) saturate(1.5);
  box-shadow:inset 0 -1px 0 var(--line);
}
/* 🔴 IGA PÄISEELEMENT NIMETAB OMA REA. `.pos-find` on `grid-row:1` ja katab
   veerud 2–5; kui ülejäänud neli jäävad `grid-row:auto` peale, EI MAHU nad
   automaatpaigutuses enam esimesele reale ja grid avab teise. Mõõdetud
   tagajärg: `grid-template-rows: 44px 44px` ja päis 56 px asemel 88 px —
   ilma ühegi veateateta, sest teine rida on tühi ja nähtamatu. */
.pos-bar>*{grid-row:1}
.pos-bar>:is(.pos-bar-clear,.pos-bar-more){
  display:grid;place-items:center;
  min-width:44px;min-height:44px;
  border:0;border-radius:var(--r-full);background:transparent;
  color:var(--ink-2);font-size:1.3rem;text-decoration:none;cursor:pointer;
}
/* ✕ on ÜLEVAL-VASAKUL: Parhi mõõtis selle piirkonna mugavuseks μ=3,7 (ekraani
   ebamugavaim) vs keskel μ=5,7. HALB ERGONOOMIKA ON SIIN TURVAFUNKTSIOON —
   ja seetõttu ei kutsu ka värv. `--ink-3`, mitte `--red`. */
.pos-bar-clear{grid-column:1;justify-self:start;color:var(--ink-3)}
.pos-bar-clear:active{background:var(--red-pale);color:var(--red)}
/* Tühja korviga on ✕ kohal AINULT paigahoidja: alaline hävitav kontroll,
   millel pole midagi hävitada, õpetab müüjat teda ignoreerima. */
.pos-bar-clear.is-off{visibility:hidden}
.pos-bar-more{grid-column:3}
/* Vaate nimi otsinguvälja asemel seal, kus otsida ei ole midagi. */
.pos-bar-title{
  grid-column:2;grid-row:1;margin:0;min-width:0;
  overflow:hidden;overflow:clip;white-space:nowrap;text-overflow:ellipsis;
  color:var(--ink-2);font-size:var(--t-micro);font-weight:800;
  letter-spacing:.16em;text-transform:uppercase;text-align:center;
}

/* --- 23.3 OTSING (UX-SPETS §5.3) ---------------------------------------- */
/* 🔴 VÄLI ON ALATI DOM-IS JA TAL ON PÄRIS KAST.
   `display:none` või `content-visibility:hidden` tähendaks, et `<label for>` ei
   saa teda fokuseerida ja iOS ei ava klaviatuuri — ilma JS-ita ei oleks otsingul
   ÜHTEGI teed. `opacity:0` + `pointer-events:none` säilitab kasti; märgendi
   aktiveerimine kutsub `focus()` (see EI OLE osutussündmus välja peal, seega
   `pointer-events:none` ei sega), ja `:focus-within` lülitab kihi kohe elavaks.
   Spetsi PÄRIS nõue — „ei istu ekraanil püsivalt, ei varasta plaadirida" — on
   täidetud: väli katab poe nime lahtri, mitte kataloogi. */
/* 🔴 OTSING ON PÜSIVALT EKRAANIL JA PÄISE KESKMISES VEERUS.
   Varem oli ta `opacity:0` all ja avanes ⌕ nupust — nii kirjutab `UX-SPETS.md`
   §5.3 („ei istu ekraanil püsivalt; väliturul on väikesed klahvid
   kasutuskõlbmatud ja püsiv väli varastaks ühe plaadirea").

   MARTTI NÕUE 14.08.2026 ON VASTUPIDINE ja ta seisab letis:
   „otsingu väli peaks olema kõige üleval mitte kuskil nupu all."
   Spetsi hind oli üks plaadirida; peidetud välja hind on see, et müüja ei tea,
   et otsing üldse olemas on. Teine on kallim.

   PLAADIRIDA EI KAO, sest väli võtab poe NIME koha, mitte kataloogi oma —
   päis jääb 56 px peale. Poe nimi on kassaekraanil niikuinii kõige vähem
   vajalik info: müüja teab, kelle letis ta seisab. */
.pos-find{
  grid-column:2;grid-row:1;
  position:relative;display:grid;align-items:center;
}
.pos-find input{
  min-height:44px;padding:0 44px 0 12px;
  border:1px solid var(--line);border-radius:var(--r-md);background:#fff;
  font:inherit;font-size:var(--t-body);
}
.pos-find input:focus-visible{outline:0;border-color:var(--green);box-shadow:0 0 0 4px var(--green-pale)}
/* Brauseri oma ✕ (`type=search`) läheb ära, sest meil on OMA — kaks risti ühes
   väljas on kaks eri suurust, kaks eri käitumist ja üks segaduses müüja.
   `type=search` jääb ALLES: temaga saab väli rolli `searchbox` ja Escape
   tähenduse, mida `type=text` ei anna. */
.pos-find input::-webkit-search-cancel-button{-webkit-appearance:none;appearance:none}
/* ✕ on DOM-is „Otsi" nupu JÄREL (vt pos-view.ts punast märkust) ja siin
   paigutatud tagasi välja sisse. `position:absolute` on lubatud; `fixed` oleks
   kassa CSS-i valvuri viga. */
.pos-find-clear{
  position:absolute;right:2px;top:50%;transform:translateY(-50%);
  display:grid;place-items:center;
  width:40px;height:40px;
  border:0;border-radius:var(--r-full);background:transparent;
  color:var(--ink-3);font-size:1rem;line-height:1;cursor:pointer;
}
.pos-find-clear[hidden]{display:none}
.pos-find-clear:hover{background:var(--paper-2);color:var(--ink)}
.pos-find-clear:active{background:var(--paper-3)}


/* --- 23.4 KATALOOG ------------------------------------------------------- */
/* Veergude arv on PIDEV funktsioon, mitte katkepunkt: laiuse muutmisel ei teki
   ega kao ühtegi elementi. Alampiir on 132 px, mitte 148: MÕÕDETUD, et 375 px
   annab mõlemal juhul täpselt kaks veergu (floor(347/144)=2 ja floor(347/160)=2),
   aga 320 px (vana iPhone SE) annab 148-ga ÜHE ja 132-ga KAKS. Kaks veergu
   vanal seadmel on seega tasuta. */
.pos-catalog{
  display:grid;align-content:start;gap:var(--pos-gap);
  grid-template-columns:repeat(auto-fill,minmax(clamp(132px,22vw,236px),1fr));
  grid-auto-rows:minmax(var(--pos-tile),auto);
}
/* 🔴 `.pos-tile`-il EI OLE `overflow`-i. Tootenimi MURDUB (kahele reale) ja teda
   ei lõigata, seega ei ole ellipsist ega `-webkit-line-clamp`-i vaja kusagil —
   ja seetõttu jääb „üks kerimisala" masinaga tõestatavaks. Ümarad nurgad hoiab
   `border-radius:inherit` nupu peal, mitte lõikamine. */
/* 🔴 ÜKS RIDA, MIS ÄRATAS SURNUD FUNKTSIOONI.
   `public/s/pos.js` on ALGUSEST PEALE seadnud filtreeritud plaadile
   `hidden = true` — ja plaat jäi ekraanile. Põhjus on kaks rida allpool:
   `display:grid` on AUTORI deklaratsioon ja võidab brauseri vaikereegli
   `[hidden]{display:none}`, ükskõik kui spetsiifiline see on.
   Mõõdetud 15.08.2026: `hiddenAttr:true, display:"grid", offsetHeight:92`.
   Tagajärg letis oli see, et otsing nõudis Enterit ja iga täht maksis
   serveripäringu. Sama lõks on selles failis juba kaks korda dokumenteeritud
   (`.pos-view[hidden]` r1467, `.pos-tile-steps[hidden]` r1640) — ja tabas
   sellegipoolest kolmandat korda. */
.pos-tile[hidden]{display:none}
.pos-tile{
  position:relative;display:grid;
  border-radius:var(--r-md);
  background:linear-gradient(180deg,var(--card),#FAFCF8);
  box-shadow:var(--hair),var(--shadow-1);
  transition:transform var(--fast) var(--ease),box-shadow var(--base) var(--ease);
}
.pos-tile-add{
  display:grid;grid-template-rows:minmax(0,1fr) auto;align-content:space-between;
  justify-items:start;gap:6px;
  width:100%;min-height:var(--pos-tile);padding:12px 14px;
  border:0;border-radius:inherit;background:transparent;
  color:var(--ink);font:inherit;text-align:left;cursor:pointer;
}
.pos-tile-name{overflow-wrap:anywhere;font-size:1rem;font-weight:750;line-height:1.2;letter-spacing:-.01em}
/* Hind on ROHELINE, sest roheline tähendab siin failis RAHA. Sama põhjusega ei
   ole roheline `−`/`+` nuppudel (vt 23.6): koguse muutmine ei ole raha. */
/* „Näita veel N toodet" — telefoni plaadipiiri avaja. Ta on TEISENE nupp ja
   peab seda ka välja nägema: kataloog on peategelane, tema on uks. */
.pos-more-wrap{display:grid;margin:0}
.pos-more[hidden]{display:none}
.pos-more{
  display:grid;place-items:center;
  width:100%;min-height:52px;padding:0 18px;
  border:0;border-radius:var(--r-md);
  background:var(--paper-2);box-shadow:var(--hair);
  color:var(--ink-2);font:inherit;font-size:var(--t-small);font-weight:800;
  cursor:pointer;
  transition:background-color var(--fast) var(--ease),color var(--fast) var(--ease);
}
.pos-more:hover{background:var(--green-mist);color:var(--green-3)}
.pos-more:active{background:var(--paper-3)}

.pos-tile-buy{display:flex;align-items:center;gap:9px;min-width:0}
.pos-tile-price{
  color:var(--green-3);font-size:1.0625rem;font-weight:900;
  letter-spacing:-.02em;font-variant-numeric:tabular-nums;
}
/* 🔴 SEE RING ON AINUS ASI, MIS ÜTLEB „PLAAT ON NUPP".
   Plaat on `<button>`, aga ta näeb välja nagu kaart. Demokassas on iga
   külastaja esmakordne kasutaja ja tema esimene küsimus on „kuhu ma vajutan".
   Ring on tahtlikult VAIKNE — mitte roheline täidis, sest roheline tähendab
   selles failis RAHA ja hind seisab tema kõrval. Kutse peab olema loetav,
   mitte valjem kui summa, mida ta kõrval seisab. */
.pos-add-hint{
  display:grid;place-items:center;flex:0 0 auto;
  width:23px;height:23px;border-radius:var(--r-full);
  background:var(--paper-2);color:var(--ink-2);
  box-shadow:inset 0 0 0 1.5px var(--line-2);
  font-size:.95rem;font-weight:800;line-height:1;
  transition:background-color var(--fast) var(--ease),color var(--fast) var(--ease),
             box-shadow var(--fast) var(--ease),opacity var(--base) var(--ease);
}
/* Puudutus värvib ta rohelisele — kinnitus tuleb sealt, kust vajutati. */
.pos-tile-add:hover .pos-add-hint,
.pos-tile-add:active .pos-add-hint{
  background:var(--green);color:#fff;box-shadow:inset 0 0 0 1.5px var(--green-3);
}
/* 🔴 VIHJE KAOB, AGA TEMA RUUM MITTE.
   Kui kogus on üle nulli, on plaadil juba `[−] N [+]` juhtriba ja ring oleks
   kolmas plussmärk samal plaadil. `opacity`, mitte `display:none`: kadumine
   nihutaks hinda 32 px vasakule IGA esimese puute juures ja tagasi iga
   eemalduse juures — turuletil tähendaks see, et number hüppab silme ees
   kaheksa tundi järjest.
   Seisund loetakse juhtriba `hidden`-lipust, mitte `.is-in-cart` klassist:
   `pos.js` võtab kohaliku puute peal `hidden` maha, aga klassi EI muuda, ehk
   klass valetaks kuni järgmise serveripäringuni. */
.pos-tile:has(.pos-tile-steps:not([hidden])) .pos-add-hint{opacity:0;pointer-events:none}
/* 🔴 KOGUS OLI NURGAMÄRGIS JA TA SEISIS NIME PEAL.
   `position:absolute;top:8px;right:8px` ilma et `.pos-tile-name` oleks talle
   ruumi jätnud → „Metsamesi 500 g" all luges ekraanilt „Metsamesi 500" ja
   number kattis „g"-d. Absoluutne element EI RESERVEERI ruumi; seda peab
   tegema tema naaber, ja seda ei tehtud.

   Ja teine, suurem viga: korvis oleva rea kogust sai muuta AINULT korvivaates.
   Turuleti kõige sagedasem parandus („üks liiga palju") nõudis vaate vahetust.

   Mõlemad kaovad ühe muudatusega: kogus elab nüüd oma juhtribas plaadi all,
   koos `−` ja `+` nupuga. Riba on olemas AINULT siis, kui kogus > 0 — tühi
   plaat jääb 92 px peale ja kataloogi tihedus ei kannata.

   KÕRVALEKALLE UX-SPETS §5.1-st, teadlik: spetsi diagramm ei näe plaadil
   miinusnuppu ette ja §5.2 paneb `−`/`+` korvivaatesse. Martti nõue
   14.08.2026 on otsene ja tuleb letist: „teenindaja ei peaks alt avama seda
   ostukorvi vaid saaks kassas kohe muuta kõike." Spetsi MÕTE — suur sihtmärk,
   `−` ja `+` piisavalt kaugel — on täidetud: nupud on 60 px (SAGEDANE klass)
   ja nende serv-servalt vahe on 375 px ekraanil 45 px, 390 px juures 53 px,
   ehk üle MIL-STD-1472H nõutud 32 px. Vana nurgamärgis oli 26 px kõrge ehk
   allpool KÕIKI puuteklasse — ta ei olnud sihtmärk üldse. */
/* `[hidden]` PEAB võitma selgesõnalise `display`-i (sama õppetund, mis
   `.pos-cash-back` juures): brauseri vaikimisi `display:none` kaob, kui
   reeglis on `display:grid`, ja peidetud riba jääks ekraanile. */
.pos-tile-steps[hidden]{display:none}
.pos-tile-steps{
  display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;
  border-top:1px solid var(--line);
}
/* 🔴 ASETUS NIMETATAKSE SIIN, MITTE EI PÄRITA. `.pos-step-minus` ja
   `.pos-step-plus` kannavad korvivaate `grid-column` väärtusi ja need
   rakenduvad ka siin — mõõdetud tagajärg oli `grid-template-columns:
   12.4px 96.6px 0px 60px`, ehk NELI veergu kolme asemel, kogus vasakus servas
   miinusnupu all. Kolm last, kolm nimetatud veergu, null pärimist. */
/* 🔴 KÕIK KOLM ON ÜHEL REAL — ja seda peab ÜTLEMA.
   `.pos-step-minus`/`-plus` kannavad korvivaatest `grid-row:1/3` ja see rändas
   klassiga kaasa: mõõdetud 15.08.2026 — nupud reas `1/3`, kogus reas `1`, ehk
   ribal oli KAKS rida (29,8 px + 30,2 px) ja kogus istus ülemises. `1×` oli
   nuppude keskmest 15 px kõrgemal.
   See on TÄPSELT sama viga, mille ma nende veergude peal juba parandasin —
   paigutusreegel, mis rändab klassiga kaasa, tuleb tagasi teises teljes. */
/* `>.pos-step`, mitte `>*`: universaalselektor annab spetsiifsuse 0,1,0 ja
   kaotab korvivaate `.pos-step-minus{grid-row:1/3}` reeglile, mis on samuti
   0,1,0 ja seisab failis HILJEM. Klassiga tõuseb see 0,2,0 peale ja võidab. */
.pos-tile-steps>.pos-step{grid-row:1}
.pos-tile-steps>.pos-tile-count{grid-row:1}
.pos-tile-steps>.pos-step-minus{grid-column:1}
/* 🔴 `align-self:center` ON SIIN KOHUSTUSLIK, MITTE LIIANE.
   Ribal on `align-items:center`, aga kogus istus sellest hoolimata ülaservas:
   mõõdetud 15.08.2026 — nupu kese 226 px, koguse kese 211 px, ehk 15 px
   kõrgemal. Põhjus on koguse enda `display:flex; align-items:baseline`, mis
   paneb võre teda BAASJOONE järgi joondama, mitte kasti keskme järgi.
   30 px kõrgune element 60 px nuppude vahel peab olema keskel — muidu loeb
   riba kolme eri kõrgusega asjana, mitte ühe juhtelemendina. */
.pos-tile-steps>.pos-tile-count{grid-column:2;grid-row:1;align-self:center}
.pos-tile-steps>.pos-step-plus{grid-column:3}
.pos-tile-steps .pos-step{
  min-width:var(--pos-step);min-height:var(--pos-step);
  border:0;border-radius:0;background:transparent;
  color:var(--ink);font:inherit;font-size:1.5rem;font-weight:750;
  line-height:1;cursor:pointer;
}
.pos-tile-steps .pos-step-minus{border-bottom-left-radius:var(--r-md)}
.pos-tile-steps .pos-step-plus{border-bottom-right-radius:var(--r-md)}
.pos-tile-steps .pos-step:active{background:var(--paper-2)}
.pos-tile-steps .pos-step:disabled{color:var(--ink-3);cursor:not-allowed}
/* `<output>`, mitte `<span>`: kogus ON arvutatud väärtus ja see on tema semantika. */
/* `display:flex`, MITTE `grid`: `::after` („×") on grid'is omaette RIDA ja
   number murdus tema kohale kahele reale. Mõõdetud: `grid-template-rows:
   29.8px 25.3px`. Flex hoiab nad ühel real, baasjoonel. */
.pos-tile-count{
  display:flex;align-items:baseline;justify-content:center;
  color:var(--green-3);font-size:1.15rem;font-weight:900;
  font-variant-numeric:tabular-nums;
}
.pos-tile-count:not(:empty)::after{content:"×";margin-left:1px;font-size:.85em;opacity:.55}
/* Kitsal ekraanil kahaneb nupp, MITTE nende vahe: valepuude `−` ja `+` vahel on
   kogu liidese kalleim eksitus (MIL-STD-1472H nõuab esimeste kontaktpunktide
   vahet ≥5 mm). 320 px juures annab 52 px nupp 34 px vahe, 60 px annaks 18. */
@media (max-width:359px){ .pos-shell{--pos-step:52px} }
/* Korvis olev toode kannab kataloogis rohelist rõngast: müüja loeb korvi
   koosseisu ILMA korvi avamata. See on infodisain, mitte kaunistus. */
.pos-tile.is-in-cart{
  box-shadow:inset 0 0 0 2px var(--green),var(--shadow-2);
}
.pos-tile:focus-within{box-shadow:inset 0 0 0 2px var(--green),var(--shadow-2)}
/* Laost otsas: KOLM signaali, sest värv üksi ei kanna päikeses (UX-SPETS §5.1).
   Nimi on `<s>`-ga läbi kriipsutatud, silt on merevaik, nupp on `disabled`. */
.pos-tile.is-out{background:var(--paper-2);box-shadow:var(--hair)}
.pos-tile.is-out .pos-tile-name s{text-decoration-thickness:2px}
.pos-tile-add:disabled{color:var(--ink-3);cursor:not-allowed}
.pos-tile-flag{
  padding:2px 8px;border-radius:var(--r-sm);
  background:var(--amber);color:#fff;
  font-size:var(--t-micro);font-weight:900;letter-spacing:.1em;
  print-color-adjust:exact;-webkit-print-color-adjust:exact;
}
/* Hõljumine ainult hiirega — puutel jääb `:hover` kleepuma. */
@media (hover:hover){
  .pos-tile:not(.is-out):hover{transform:translateY(-2px);box-shadow:var(--hair-2),var(--shadow-lift)}
}
/* 120 ms vilgatus (UX-SPETS §5.1). JS-ita tuleb ta serveri `#toode-<id>`
   fragmendist, JS-iga klassist — kaks teed, üks animatsioon. */
.pos-tile:target,.pos-tile.is-hit{animation:pos-hit 120ms var(--ease) 1}
@keyframes pos-hit{from{background:var(--green-pale)}to{background:var(--card)}}

/* --- 23.5 ALUMINE RIBA — 144 px, ALATI ---------------------------------- */
/* 🔴 STICKY, MITTE FIXED, JA KEHA VIIMASE LAPSENA. Kolm tasuta võitu:
     1. iOS-i `position:fixed` + ekraaniklaviatuuri veaklass kaob ära.
     2. `.app-foot{margin-bottom:calc(64px+88px+…)}` käsitsi kompensatsiooni ei
        ole vaja — riba VÕTAB voos oma 144 px ise.
     3. Kerimise LÕPUS on riba oma STAATILISES asendis, seega ta ei peida mitte
        kunagi viimast plaati. `fixed` peidaks.
   Lühikese sisu korral surub `margin-top:auto` ta vaateava põhja ja kleepumist
   ei toimugi; pika sisu korral on `.pos-body` sisukast vaateavast kõrgem ja
   `bottom:0` naelutab ta põhja. Üks reeglikomplekt, null meediapäringut.
   Negatiivne külgmarginaal viib ta servast servani ILMA `fixed`-ita — ja
   lauaarvuti 220 px riiuli juures on ta seetõttu automaatselt õiges kohas. */
.pos-bottom{
  position:sticky;bottom:0;z-index:40;
  margin-top:auto;margin-inline:calc(var(--gutter) * -1);
  display:grid;grid-template-rows:minmax(56px,auto) minmax(88px,auto);
  min-height:var(--pos-bar);
  background:linear-gradient(180deg,rgba(251,251,248,.86),var(--paper) 34%);
  backdrop-filter:blur(14px) saturate(1.4);
  -webkit-backdrop-filter:blur(14px) saturate(1.4);
  box-shadow:0 -1px 0 var(--line),0 -18px 34px -26px rgba(10,52,28,.5);
}
/* 🔴 56 + 88 = 144 TÄPSELT, ILMA VAHETA. Spetsi diagrammil on 44 + 88 + 12 px
   polstrit; meie kulutame selle 12 px teisesele reale, sest sinna satub
   tagasivõtu nupp ja 44 px on doktriinis HARVA tegevuse klass. Sama arv, parem
   jaotus. Vahe asemel on juuksekarva-joon. */
.pos-bottom>*{margin:0;box-shadow:inset 0 -1px 0 var(--line)}
.pos-bottom>:last-child{box-shadow:none}
/* Rea 1 kolm nägu. Kõik kolm on 56 px — riba kõrgus ei muutu kunagi. */
.pos-idle,.pos-sum-cart,.pos-undo{grid-row:1}
/* 🔴 ASETUS KUULUB RIBALE, MITTE NUPULE. `.pos-pay{grid-row:2}` ilma
   vanemata rakendus ka sularahavaate „Salvesta sularahamüük" nupule, mis ei
   ole üldse ribas — ja `.pos-cash` võre tõstis ta sisu ETTE, ehk müüja nägi
   „salvesta" nuppu ENNE summat ja saadud raha välja. Sama vealiik, mis
   `.pos-tile-steps` veergudel: paigutusreegel, mis rändab klassiga kaasa. */
.pos-bottom>.pos-pay{grid-row:2}
/* TÜHI KORV EI TOHI OLLA TÜHI KROOM. Püsiv riba, mis ei ütle mitte midagi, on
   halvim liik kroomi — ja tühjal kassal näeb müüja just seda kõige sagedamini.
   Siin on päevakäive, ehk riba on tööriist siis, kui korvis on midagi, ja
   armatuurlaud siis, kui ei ole. */
.pos-idle{
  display:none;align-items:baseline;gap:10px;
  padding-inline:var(--gutter);color:var(--ink-2);font-size:var(--t-small);
}
.pos-idle strong{color:var(--ink);font-size:1.3rem;font-weight:900;font-variant-numeric:tabular-nums}
/* 🔴 TÜHJA KORVIGA EI OLE KEELATUD NUPPU — TA EI OLE ÜLDSE OLEMAS.
   Martti 15.08.2026: „see võta makse nupp on paigutatud halvasti ja arvutist
   vaadates jätab katkise või ebaprofessionaalse mulje."

   Ta vaatas demot NII, NAGU KLIENT SEDA ESIMEST KORDA NÄEB: korv on tühi,
   ja esimene asi, mis prospektile silma jääb, oli HALL, KEELATUD maksenupp
   summaga 0,00 €. Keelatud juhtelement loeb katkise asjana — ja see on
   ekraan, mis peab meile kliente tooma.

   Nüüd on riba tühja korviga ARMATUURLAUD: päevanumber on tema sisu, mitte
   kaassõna keelatud nupu kõrval.

   🔴 JA RIBA KÕRGUS EI JÄÄ SAMAKS — SEE OLI SIIN VALE.
   Selle kommentaari eelmine versioon lubas, et kõrgus jääb 144 px peale,
   „seega esimene lisatud toode ei nihuta midagi". Lubadus oli tõene, aga ta
   maksis rohkem, kui ta ostis. Mõõdetud 375×812 tootmises, tühja korviga:

       .pos-bottom   668…812   144 px
       .pos-idle     668…724    56 px
       .pos-pay      display:none
       .pos-sum-cart display:none

   ehk alumine 88 px rida oli TÄIESTI TÜHI — 11 % vaateavast, mis ei näidanud
   mitte midagi ja kattis ära lindi, mida ta oleks pidanud paljastama. Martti
   15.08.2026: „see tühi ala… võtab lihtsalt ruumi ja peidab viimaseid
   tehinguid."

   Konstantne kõrgus (KASSA-SPEKK §9) oli kirjutatud eeldusel, et maksenupp on
   ALATI olemas, ainult keelatud. Kui ta muutus `display:none`-iks (õigel
   põhjusel — vt ülalt), jäi reserveeritud rida alles ja kaitses nuppu, mida ei
   eksisteeri. See ei olnud enam konstantne riba, vaid tühi riba.

   Kokkutõmbamine EI TEE nihkeid: `.pos-bottom` on `position:sticky` voo LÕPUS,
   seega tema kasvamine ei liiguta ühtegi elementi tema kohal — ta lihtsalt
   katab rohkem vaateava põhja. Mõõdetud: esimese plaadi ülemine serv on enne
   ja pärast esimest puudet samal pikslil. */
.pos-bottom.is-empty>.pos-idle{display:flex}
.pos-bottom.is-empty>.pos-sum-cart{display:none}
.pos-bottom.is-empty>.pos-pay{display:none}
.pos-bottom.is-empty{place-content:center;min-height:0;grid-template-rows:minmax(56px,auto)}
.pos-bottom.is-empty>.pos-idle{
  justify-content:center;align-items:baseline;
  font-size:var(--t-body);
}
.pos-bottom.is-empty>.pos-idle strong{font-size:1.9rem}
.pos-sum-cart{
  display:flex;align-items:center;gap:8px;
  padding-inline:var(--gutter);
  border:0;background:transparent;color:var(--ink-2);
  font:inherit;font-weight:800;text-align:left;cursor:pointer;
}
.pos-sum-chevron{color:var(--ink-3);font-size:1.2rem}
.pos-cap{
  grid-row:1;justify-self:end;align-self:center;
  padding-inline:var(--gutter);
  color:var(--amber);font-size:var(--t-small);font-weight:800;
}
.pos-cap[hidden]{display:none}

/* MAKSENUPP — KAKS RIDA, JA SUMMA ON LEHE SUURIM ASI.
   Kassa on numbriekraan. Vana `.pos-total strong` oli 37–46 px; ühelegi
   ühereaslahendusele („Võta makse · 24,50 €") ei mahu 88 px sisse loetavat
   numbrit. Silt on väike ja vaikne, number on suur ja tabular. */
.pos-pay{
  display:grid;align-content:center;justify-items:center;gap:2px;
  width:100%;min-height:88px;padding:0 var(--gutter);
  border:0;border-radius:0;
  background:linear-gradient(180deg,#17BC5F,var(--green-2) 60%,var(--green));
  box-shadow:var(--shadow-green),inset 0 1px 0 rgba(255,255,255,.25);
  color:#fff;font:inherit;text-decoration:none;cursor:pointer;
}
.pos-pay-label{font-size:.9rem;font-weight:800;letter-spacing:.06em;opacity:.86}
.pos-pay-sum{
  font-size:clamp(1.9rem,5.6vw,2.2rem);font-weight:900;
  letter-spacing:-.03em;line-height:1.05;font-variant-numeric:tabular-nums;
}
.pos-pay:disabled{background:var(--paper-3);box-shadow:none;color:var(--ink-3);cursor:not-allowed}
.pos-pay-danger{background:linear-gradient(180deg,#D0473C,var(--red));box-shadow:var(--shadow-2)}
.pos-ask-keep{
  display:grid;place-items:center;
  padding-inline:var(--gutter);color:var(--ink-2);font-weight:800;text-decoration:none;
}

/* --- 23.6 TAGASIVÕTT (UX-SPETS §5.2) ------------------------------------ */
/* 🔴 TAGASIVÕTT HÕIVAB AINULT RIBA ÜLEMISE REA. Spetsi lause „alumine riba
   muutub 8 sekundiks nupuks" loeb sõna-sõnalt nii, et maksmine on 8 sekundit
   võimatu — ostja seisab letis kaardiga käes. Spetsi MÕTE oli anda AEGA
   MÄRGATA. 56 px sihtmärk + 8 s + kogu aeg puutuv 88 px maksenupp täidab mõtte
   ja ei osta seda ostja ootamise hinnaga. */
.pos-undo{display:none;align-items:center;gap:10px;padding-inline:var(--gutter);background:var(--amber-pale)}
.pos-bottom.has-undo>.pos-undo{display:flex}
.pos-bottom.has-undo>:is(.pos-sum-cart,.pos-idle){display:none}
.pos-undo-do{
  flex:1 1 auto;min-height:56px;
  border:0;background:transparent;color:#7A3D06;
  font:inherit;font-weight:850;text-align:left;cursor:pointer;
}
/* 8 sekundit NÄIDATAKSE kahaneva 3 px ribakesega. Ta on kaunistus: nupp ise ei
   kao, sest automaatselt kaduv juhtelement on WCAG 2.2 SC 2.2.1 ajapiirang.
   Nupp kaob järgmise tegevusega, sest server ei kanna vana kogust edasi. */
.pos-undo-timer{flex:0 0 64px;height:3px;background:var(--amber-line);transform-origin:left}
@media (prefers-reduced-motion:no-preference){
  .pos-undo-timer{animation:pos-undo 8s linear forwards}
}
@keyframes pos-undo{from{transform:scaleX(1)}to{transform:scaleX(0)}}
/* 🔴 SEE PLOKK PEAB OLEMA OSA 28 KOHUSTUSLIKUST reduce-PLOKIST HILJEM.
   Ilma selleta kirjutaks `animation-duration:.01ms!important` ribakese 10 ms
   peale ja jätaks mulje, et tagasivõtt AEGUS — kuigi nupp on alles. Vähendatud
   liikumise režiimis ei ole ribakest üldse. */
@media (prefers-reduced-motion:reduce){
  .pos-undo-timer{animation:none!important;display:none}
}

/* ---------------------------------------------------------------------------
   23.6b VAATE AVANEMINE — liikumine, mis ütleb „see on uus ekraan"
   ---------------------------------------------------------------------------
   Martti nõue 14.08.2026: „kogu see kassa peab olema animeeritud, et kui
   avatakse qr makse või sularaha makse siis see peab väga ilusasti animeeritult
   avama."

   🔴 IGA VAATEVAHETUS ON TÄISLEHE LAADIMINE (iga puude on idempotentne GET).
   Seega ei ole siin „üleminekut" kahe oleku vahel, mida animeerida — on
   SISENEMINE. Kogu asi on `animation` lehe renderdusel, null JS-i, null
   olekumasinat. See on ühtlasi ainus kuju, mis töötab ka ilma JS-ita.

   Astmeline viivitus tuleb `:nth-child()`-ist, MITTE inline-stiilist
   (CSP `style-src 'self'`, DISAIN.md lõpp).

   KIIRUS ON PIIR, MITTE MAITSE: 260 ms sisenemine + kuni 120 ms aste. Müüja
   ootab järjekorraga selja taga; animatsioon, mis paneb teda ootama, on
   halvem kui animatsiooni puudumine. `--base` = 260 ms tuleb DISAIN.md-st. */
@keyframes pos-view-in{
  from{opacity:0;translate:0 14px}
  to{opacity:1;translate:none}
}
@keyframes pos-bar-in{
  from{opacity:0;translate:0 100%}
  to{opacity:1;translate:none}
}
@keyframes pos-qr-in{
  from{opacity:0;scale:.92}
  to{opacity:1;scale:none}
}

/* 🔴 ANIMATSIOON KÄIB VAATE MUUTUSEL, MITTE IGAL VAHETUSEL.
   Kui kassa hakkas sisu paigal vahetama, hakkasid need reeglid jooksma ka
   TAVALISE PLAADIPUUTE peal — kogu kataloog ilmus uuesti sisse ja Martti
   ütles täpselt õige asja: „tuleb selline animatsioon nagu terve leht laeks
   uuesti". Sisenemine tähendab UUT EKRAANI. Sama ekraani värskendus ei tohi
   liikuda üldse: `pos.js` võrdleb `data-pos-view` vana ja uut väärtust ning
   lisab `.is-entering` AINULT siis, kui vaade päriselt vahetus.
   Esimesel laadimisel on klass serveri renderduses kohe olemas. */
@media (prefers-reduced-motion:no-preference){
  /* Sularaha ja makseviis: kolm-neli last tulevad ülalt alla, üksteise järel.
     Järjekord ON info — müüja silm liigub täpselt seda teed, mida ekraan
     temalt ootab: summa → väli → vastus. */
  .is-entering .pos-cash>*,.is-entering .pos-payment-choice>*{animation:pos-view-in var(--base) var(--ease) both}
  .is-entering .pos-cash>*:nth-child(2),.is-entering .pos-payment-choice>*:nth-child(2){animation-delay:40ms}
  .is-entering .pos-cash>*:nth-child(3),.is-entering .pos-payment-choice>*:nth-child(3){animation-delay:80ms}
  .is-entering .pos-cash>*:nth-child(4),.is-entering .pos-payment-choice>*:nth-child(4){animation-delay:120ms}
  .is-entering .pos-cash>*:nth-child(5),.is-entering .pos-payment-choice>*:nth-child(5){animation-delay:160ms}
  /* 🔴 NÄHTAMATU LAPS EI TOHI ASTET SÜÜA. `.sr-only` submit-nupp on
     sularahavaates neljas laps ja ta võttis 120 ms astme endale, jättes
     nähtava lingi 0 ms peale — järjekord ekraanil oli vale, kuigi CSS oli
     „õige". `:nth-child()` loeb KÕIKI lapsi, ka neid, keda keegi ei näe. */
  .pos-cash>.sr-only,.pos-payment-choice>.sr-only{animation:none}

  /* Alumine riba tuleb ALT — ta on kroom, mitte sisu, ja tema suund ütleb seda. */
  .is-entering .pos-bottom{animation:pos-bar-in var(--base) var(--ease) both}

  /* QR skaleerub sisse. Ta on ainus asi, mida ostja skannib, ja väike kasv
     juhib pilgu temani ilma et ekraan hüppaks. `scale`, mitte `translate`:
     nihkuv QR-kood on hetkeks skannimatu. */
  .is-entering .qr-screen svg{animation:pos-qr-in var(--base) var(--ease) both;animation-delay:60ms}
  .is-entering .qr-amount{animation:pos-view-in var(--base) var(--ease) both}
  .is-entering .qr-screen>.waiting{animation:pos-view-in var(--base) var(--ease) both;animation-delay:120ms}
  .is-entering .qr-screen>.actions{animation:pos-view-in var(--base) var(--ease) both;animation-delay:160ms}

  /* Kataloog ja korv saavad sama sisenemise, aga ILMA astmeta: kaheteistkümne
     plaadi järjestikune ilmumine oleks etendus, mitte kinnitus, ja müügiekraan
     avaneb kümneid kordi päevas. */
  .is-entering .pos-catalog,.is-entering .pos-lines{animation:pos-view-in var(--base) var(--ease) both}
}

/* Vahetuse ajal EI TOHI ekraan hüpata. Kursor ütleb, et midagi toimub, aga
   sisu jääb paigale kuni uus saabub — vilkuv tühi ekraan oli just see, mille
   pärast see kiht üldse ehitati. */
.is-swapping .pos-body{cursor:progress}

/* Maksenupu tagasiside summa muutumisel. `transform` ei liiguta ühtegi teist
   elementi — paigutus jääb paigale ja ainult nupp reageerib. */
@keyframes pos-pay-bump{
  0%{transform:none}
  38%{transform:scale(.985)}
  100%{transform:none}
}
@media (prefers-reduced-motion:no-preference){
  .pos-pay.is-bumping{animation:pos-pay-bump 260ms var(--ease) 1}
}

/* --- LAADIMISKATE ---------------------------------------------------------
   Ainus ootamine, mis kassas alles on: tellimuse kirjutus D1-sse. Kate on
   `position:fixed` ja katab kogu ekraani — mitte selleks, et ilus olla, vaid
   selleks, et müüja EI SAAKS teist korda vajutada. Kaks tellimust sama kauba
   eest on kallim viga kui üks sekund ootamist.

   `[hidden]` peab võitma — neljas kord selles failis. */
.pos-loading[hidden]{display:none}
.pos-loading{
  position:fixed;inset:0;z-index:90;
  display:grid;place-items:center;
  background:rgba(252,252,250,.86);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
}
/* Kolm punkti ÜHEL real, tekst nende all — mõlemad keskel. Ilma
   `grid-template-columns`-ita venis kaart üle terve ekraani ja punktid
   kukkusid kolme eri veergu; `justify-content:center` hoiab kaardi sisu
   laiuse juures, mitte konteineri oma. */
.pos-loading-card{
  display:grid;grid-template-columns:repeat(3,auto);
  justify-content:center;justify-items:center;align-items:center;
  gap:16px 9px;
  max-width:min(88vw,340px);
  padding:26px 32px;
  border-radius:var(--r-lg);
  background:var(--card);box-shadow:var(--shadow-2);
}
.pos-loading-text{
  grid-row:2;grid-column:1/-1;margin:0;
  color:var(--ink-2);font-size:var(--t-body);font-weight:800;text-align:center;
}
.pos-loading-dot{
  grid-row:1;width:10px;height:10px;border-radius:var(--r-full);
  background:var(--green-2);opacity:.35;
}
@media (prefers-reduced-motion:no-preference){
  .pos-loading-dot{animation:pos-loading-pulse 1.05s var(--ease) infinite}
  .pos-loading-dot:nth-child(2){animation-delay:.15s}
  .pos-loading-dot:nth-child(3){animation-delay:.3s}
}
@keyframes pos-loading-pulse{
  0%,100%{opacity:.35;transform:none}
  45%{opacity:1;transform:translateY(-4px)}
}

/* ---------------------------------------------------------------------------
   23.6c LAUAARVUTI — laius on ruum, mitte venitus
   ---------------------------------------------------------------------------
   Martti 14.08.2026: „see UX telefonis on väga hea, aga arvutis ei ole."

   MÕÕDETUD TOOTMISES 1440x900, ja igas numbris on sama viga:

     otsinguväli ..... 1312 px (väljale, mis vajab 320)
     kataloog ........ 1372 x 153 px — üks rida plaate lehe ülaservas
     lint ............ 1372 x 530 px — read kandsid „#32 · Ootel · 8,90 €",
                       ehk ~1000 px tühja IGA rea kohta
     alumine riba .... 1440 px lai, „3 toodet" vasakus servas ja maksenupp
                       paremas, ~1000 px eimidagit vahel

   See ei ole halb disain — see on TELEFONI disain, mis on venitatud. Telefonis
   on täislaius õige, sest laiust ei ole. Lauaarvutis on laius RUUM ja teda
   tuleb jagada, mitte täita.

   Murdepunkt on 1100 px: allpool jääb tahvel ja telefon PUUTUMATA (Martti
   ütles, et need on head, ja neid ei tohi „ühtlustada"). */
@media (min-width:1100px){
  /* Kaks veergu: kataloog kasvab, lint on kitsas rööbas paremal. Lindi read
     loevad 380 px juures täpselt nagu telefonis — see kuju on juba tõestatud. */
  .pos-view[data-pos-view-panel="myyk"] .pos-body{
    display:grid;grid-template-columns:minmax(0,1fr) 380px;
    /* 🔴 ESIMENE RIDA ON `1fr`, MITTE `auto`. Riba on võre TEINE rida ja
       `position:sticky;bottom:0` mõõdab end oma võreala vastu — `auto` reaga
       jäi ala täpselt sisu kõrguseks ja riba kukkus ekraanist ALLA (mõõdetud:
       riba y=900 ehk vaateava alumisel serval, nähtamatu). `1fr` + vaateava
       kõrgune `min-height` annab talle ala, mille sees kleepuda on mõtet. */
    grid-template-rows:1fr auto;
    min-height:calc(100dvh - var(--pos-head));
    column-gap:28px;align-items:start;
  }
  .pos-view[data-pos-view-panel="myyk"] .pos-catalog{grid-column:1;grid-row:1}
  /* 🔴 RIBA ULATUB ÜLE MÕLEMA VEERU. Ta on `.pos-body` laps ja sattus muidu
     võre TEISE veergu — mõõdetud: riba x=992, laius 448 px, „3 toodet" murdus
     kahele reale. Kleepuv riba, mis katab ainult paremat kolmandikku, ei ole
     riba. */
  .pos-view[data-pos-view-panel="myyk"] .pos-bottom{
    grid-column:1/-1;grid-row:2;align-self:end;margin-top:0;
  }
  /* 🔴 RÖÖBAS EI KLEEPU. Esimene versioon oli `position:sticky` — ja mõõtmine
     näitas, miks see vale on: rööbas on 658 px, ekraanist jääb pärast päist ja
     riba alles ~645, ehk kleepuva elemendi ALUMINE OTS on kättesaamatu. Ta
     jäigi riba alla 53 px võrra ja päevanumbrit ei näinud keegi.

     Teine kerimisala on adminnis keelatud (Martti 13.08.2026), seega rööbas ei
     tohi ka ise kerida. Ainus aus lahendus on lasta tal kerida KOOS LEHEGA —
     ja päris kataloogiga (30+ toodet) on vasak veerg niikuinii pikem, seega
     rööbas ei jää silmist ära. */
  .pos-rail{
    grid-column:2;grid-row:1;
    display:grid;gap:10px;align-content:start;
    /* Viimane rida peab riba alt välja jääma. */
    padding-bottom:calc(var(--pos-bar) + 12px);
  }
  /* 🔴 OTSING ON ÄÄREST ÄÄRENI. Varem seisis siin 420 px lagi põhjendusega
     „pikima tootenime jagu" — see mõõdab VÄLJUNDIT (nimi mahub) ja mitte
     SIHTMÄRKI (kui lihtne on välja tabada). Martti 15.08.2026: „otsingu lahter
     võiks olla äärest ääreni." 1440 px ekraanil oli väli 29 % laiusest ja
     ülejäänud 71 % oli tühi kleepuv riba — see luges tühja kohana, mitte
     väljana. Ainus asi, mis temast vasakule jääb, on ✕ (katkesta müük), ja
     tema 44 px on RESERVEERITUD ka tühja korviga: kokkukukkuv veerg
     nihutaks otsinguvälja iga müügi alguses ja lõpus 44 px võrra. */
  .pos-bar .pos-find{justify-self:stretch;width:auto}
  .pos-bar .pos-find input{width:100%}

  /* Alumine riba: sisu koondub PAREMALE, maksenupu kõrvale. „3 toodet" ja
     maksenupp 1000 px kaugusel teineteisest ei ole paar, vaid kaks üksikut
     asja — ja müüja silm peab nende vahel edasi-tagasi käima. */
  .pos-view:not([hidden]) .pos-bottom{
    grid-template-columns:minmax(0,1fr) auto;
    align-items:center;gap:0 20px;
    padding-inline:var(--gutter);
  }
  .pos-view:not([hidden]) .pos-bottom>.pos-sum-cart{grid-column:1;grid-row:1;justify-self:end}
  .pos-view:not([hidden]) .pos-bottom>.pos-idle{grid-column:1;grid-row:1;justify-self:end}
  .pos-view:not([hidden]) .pos-bottom>.pos-pay{
    grid-column:2;grid-row:1;
    width:auto;min-width:280px;border-radius:var(--r-lg);
  }
  /* Rööbas on lauaarvutis PÄEVA VEERG, mitte lindi jätk. Numbrid tulevad
     ülemisse serva, sest sinna vaatab müüja siis, kui letis on hetk hinge
     tõmmata — lint on ajalugu ja tema koht on all. */
  .pos-rail .pos-day{
    order:-1;
    grid-template-columns:repeat(auto-fit,minmax(120px,1fr));
    gap:8px;
  }
  .pos-rail .pos-day>li{
    display:grid;gap:2px;padding:12px 14px;
    border-radius:var(--r-md);background:var(--card);box-shadow:var(--hair);
  }
  .pos-rail .pos-day>li>span{
    color:var(--ink-3);font-size:var(--t-micro);font-weight:800;
    letter-spacing:.12em;text-transform:uppercase;
  }
  .pos-rail .pos-day>li>strong{
    color:var(--ink);font-size:1.35rem;font-weight:900;
    letter-spacing:-.02em;font-variant-numeric:tabular-nums;
  }

  /* Lindi read on rööpas KOMPAKTSED. Telefoni 98 px rida × kuus + päevariba
     annab 658 px, mis 900 px ekraanil pärast päist ja riba enam ei mahu — ja
     kleepuv element, mille alumine ots on kättesaamatu, on halvem kui
     kerimine. 380 px laiuse juures mahub sama info kahele reale ja hingab. */
  .pos-rail .pos-tape>li{padding:11px 14px}
  .pos-rail .tape-name{font-size:var(--t-small)}
  .pos-rail .tape-note{font-size:var(--t-micro)}
  .pos-rail .tape-sum{font-size:var(--t-body)}

  /* Makseviis ja sularaha on ÜHE küsimuse ekraanid — nad ei tohi lauaarvutis
     laiali valguda. Sama mõõt, mis telefonis, keskel. */
  .pos-cash,.pos-payment-choice{max-width:520px;margin-inline:auto}
}

/* --- DEMO: LUKUSTATUD NAV JA „MIS VEEL ON" ---------------------------------
   Demo näitab ainult kassat ja prospekt järeldab, et toode ONGI kassa. Nav on
   odavaim viis öelda „siin on veel kuus asja".

   🔴 LUKUSTATUD PUNKT EI OLE `disabled` NUPP. `disabled` on umbtee; link on
   kutse. Ta viib `/proovi?osa=<jagu>` peale, kus seisab vastus TEMA kohta —
   mitte üldine müügijutt. Hall ikoon ilma seletuseta jätaks mulje poolikust
   tootest, mitte suuremast tootest. */
.admin-nav.is-locked .is-teaser{opacity:.62}
.admin-nav.is-locked .is-teaser:hover,
.admin-nav.is-locked .is-teaser:focus-visible{opacity:1}
/* Lukk on SILDI KÕRVAL, mitte tema kohal. Esimene versioon oli
   `position:absolute; top:6px` — see on alumise riba loogika, aga lauaarvutis
   on nav VERTIKAALNE külgriba ja märk hõljus sildist eraldi, nagu kuuluks ta
   kellelegi teisele. Inline hoiab ta sildi juures mõlemas paigutuses.

   🔴 EMOTIKON 🔒 SAI SVG-KS. Emotikon renderdub igal platvormil OMA VÄRVIS
   (iOS-il kollane tabalukk, Windowsil hall) — tumedal külgribal tähendas see
   kuut kollast täppi, mis tõmbasid rohkem pilku kui aktiivne rida. SVG pärib
   `currentColor` ja on sama vaikne kui tekst tema kõrval. */
/* 🔴 ALUMISEL RIBAL LUKKU EI OLE. Martti 15.08.2026: „sealt alumiselt menüült
   võid ära kaotada need luku märgid."
   Telefonis on lukk sildi ALL omaette real (ikoone seal ei ole) ja ta tegi
   viiest sildist viis kahekorruselist tulpa — märk, mis kordab seda, mida
   klõps niikuinii ütleb. Külgribal ta JÄÄB: seal on ta sildi kõrval samal
   real ja seletab, miks punkt on hägune. */
.nav-lock{display:none}
@media (min-width:981px){
  .admin-nav .nav-lock{
    display:block;width:13px;height:13px;flex:0 0 auto;
    margin-left:6px;opacity:.62;
  }
}

/* --- LIITUMISVORM -----------------------------------------------------------
   🔴 KAPSEL, MITTE VENIV LEHT — ja mõõdetud põhjusega. Esimene versioon oli
   `main.page` laiune: 1280 px ekraanil venisid väljad 1100 px laiaks ja
   88 px kõrgeks. Tulemus luges POOLIKU lehena, mitte vormina — ja see on
   esimene ekraan, mida uus klient näeb.

   Mõõt tuleb `.auth-card`-ilt (460 px): sisselogimine ja liitumine on sama
   žanr ja kaks eri laiust õpetaks, et üks neist on ajutine.

   🔴 VÄLI ON 56 px, MITTE 88. 88 px on TURULETI klass — märjad käed, kinnas,
   päike. Liitumisvorm täidetakse laua taga ja seal maksab 88 px ainult
   kerimist: seitse välja × 88 px on 616 px ainult kaste. UX-SPETS §5.1 järgi
   on see „harv" tegevus ja tema põrand on 44 px. */
.signup{width:min(520px,100%);margin-inline:auto}
.signup h1{font-size:var(--t-h2);margin:.1em 0 14px}
.signup>.lead{margin:0 0 26px}
.signup-form .field+.field,
.signup-form .field-check{margin-top:18px}
.signup-form .field-input{min-height:56px}
.signup-form .micro{margin:6px 0 0}
.signup-form .field-error{margin:6px 0 0}
.signup-form .button{width:100%;min-height:64px;margin-top:24px;font-size:1.05rem}
/* Vormi JÄREL tulev seletus vajab oma vahe. `.micro` globaalne reegel annab
   ainult tüpograafia, mitte marginaali, ja `<p>` vaikeväärtus jäi nupu varju
   alla — mõõdetud 16.08.2026, tekst istus varju sees. */
.signup>.micro{margin:26px 0 0}
/* Nõusoleku märkeruut on RUUT ja tekst tema kõrval — mitte teksti sisse
   peidetud. GDPR art 7: nõusolek peab olema üheselt mõistetav tegu. */
.field-check{display:flex;align-items:flex-start;gap:10px;line-height:1.5}
.field-check input{margin-top:3px;width:20px;height:20px;flex:0 0 auto;accent-color:var(--green)}

/* --- ÄRIREGISTRI OTSING LIITUMISVORMIL ---------------------------------------
   Üks väli, mille alt kukub loend. Iga rida on NUPP, mitte div: valik ise on
   edasiminek („Edasi" nuppu ei ole, UX-SPETS §3.2) ja klaviatuuriga peab
   jõudma sinna, kuhu hiirega. */
.rik{margin-bottom:20px}
.rik-loend{display:grid;gap:8px;margin-top:10px}
.rik-loend[hidden]{display:none}
.rik-rida{
  display:grid;gap:3px;justify-items:start;
  width:100%;padding:14px 16px;
  border:0;border-radius:var(--r-md);
  background:var(--card);box-shadow:var(--hair),var(--shadow-1);
  font:inherit;text-align:left;cursor:pointer;
  transition:box-shadow var(--fast) var(--ease);
}
.rik-rida:hover{box-shadow:inset 0 0 0 2px var(--green),var(--shadow-2)}
.rik-nimi{font-size:1.02rem;font-weight:800;color:var(--ink)}
.rik-meta{color:var(--ink-2);font-size:var(--t-small);line-height:1.45}
.rik-ok{color:var(--green-3);font-size:var(--t-micro);font-weight:800}
/* 🔴 KEELDUMINE ON HALL, MITTE PUNANE. Likvideeritav ettevõte ei ole KASUTAJA
   viga — punane süüdistaks teda millegis, mida ta ei teinud. Hall + põhjus
   ütleb sama asja ilma näpuga näitamata. */
.rik-rida.is-off{background:var(--paper-2);box-shadow:var(--hair);cursor:not-allowed}
.rik-rida.is-off .rik-nimi{color:var(--ink-2)}
.rik-keeld{color:var(--amber);font-size:var(--t-micro);font-weight:800}
.rik-tyhi{margin:0;color:var(--ink-2)}
.rik-abi{display:inline-flex;min-height:44px;align-items:center;font-weight:700}
.rik-valitud{
  display:grid;gap:2px;margin:12px 0 0;padding:14px 16px;
  border-radius:var(--r-md);background:var(--green-mist);box-shadow:var(--hair);
}
.rik-valitud[hidden]{display:none}
.rik-litsents{margin:10px 0 0}

/* Kinnitusekraan kirjast tulnud lingil: kolm fakti, mida liituja loeb ENNE
   kui ta konto loob. Definitsiooniloend, sest need ON paarid — silt ja
   väärtus — ja ekraanilugeja peab neid nii kuulma. */
.kinnitus{
  display:grid;grid-template-columns:auto 1fr;gap:8px 18px;
  margin:0 0 26px;padding:18px 20px;
  border-radius:var(--r-lg);background:var(--paper-2);box-shadow:var(--hair);
}
.kinnitus dt{color:var(--ink-2);font-size:var(--t-small);font-weight:700}
.kinnitus dd{margin:0;font-weight:800;color:var(--ink);overflow-wrap:anywhere}
.kood-form .kood-input{min-height:72px}

/* --- PLATVORMI ARVE ---------------------------------------------------------
   Leht, mille müüja avab E-KIRJAST. Ta ei ole sisse logitud, ta ei tea, mis
   teda ees ootab, ja tal on üks küsimus: kui palju ja kuhu. Kõik muu on
   tõendusmaterjal, mis peab olemas olema (KMS §37 lg 7 kümme rekvisiiti), aga
   ei tohi vastust varjata. */
.invoice{max-width:760px;margin-inline:auto}
.invoice h1{font-size:var(--t-h2);margin:.1em 0 18px}
.invoice-paid{
  margin:0 0 20px;padding:14px 18px;border-radius:var(--r-md);
  background:var(--green-pale);color:var(--green-3);font-weight:800;
}
.invoice-meta{display:grid;gap:6px 24px;margin:0 0 24px}
.invoice-meta>div{display:flex;flex-wrap:wrap;gap:4px 10px}
.invoice-meta dt{color:var(--ink-3);font-size:var(--t-small)}
.invoice-meta dd{margin:0;color:var(--ink);font-weight:700;font-size:var(--t-small)}
.invoice-parties{
  display:grid;gap:18px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));
  margin:0 0 26px;
}
.invoice-parties h2{margin:0 0 6px;font-size:var(--t-micro);letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3)}
.invoice-parties p{margin:0;line-height:1.6}
.invoice-lines{padding:20px 22px;border-radius:var(--r-lg);background:var(--card);box-shadow:var(--hair),var(--shadow-1)}
.invoice-lines h2{margin:0 0 8px;font-size:1.05rem}
/* 🔴 „Teenuse maht" on JURIIDILINE nõue, mitte peenkiri. Ainult lõppsumma ei
   täida KMS §37 lg 7 p 6 ja nõuetevastase arve puhul võib klient seaduslikult
   tasumisest keelduda — seega ta loetakse, mitte peidetakse. */
.invoice-scope{margin:0 0 18px;color:var(--ink-2);line-height:1.7}
.invoice-sums{display:grid;gap:4px;margin:0 0 12px}
.invoice-sums>div{display:flex;justify-content:space-between;gap:16px}
.invoice-sums dt{color:var(--ink-2);font-size:var(--t-small)}
.invoice-sums dd{margin:0;font-weight:700;font-variant-numeric:tabular-nums}
.invoice-total{
  display:flex;align-items:baseline;justify-content:space-between;gap:16px;
  margin:0;padding-top:14px;border-top:1px solid var(--line);
}
.invoice-total strong{font-size:var(--t-h2);font-weight:900;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.invoice-pay{margin-top:28px}
.invoice-pay h2{font-size:1.05rem;margin:0 0 12px}
.invoice-way{
  padding:18px 20px;border-radius:var(--r-lg);
  background:var(--paper-2);box-shadow:var(--hair);
}
.invoice-way+.invoice-way{margin-top:14px}
.invoice-way h3{margin:0 0 10px;font-size:var(--t-body)}
.invoice-way .invoice-meta{margin:0}
.invoice-way .micro{margin:10px 0 0}

/* --- MÜÜGIKOOND ------------------------------------------------------------
   Ekraan, mida müüja näitab oma RAAMATUPIDAJALE. Ta peab ühe pilguga ütlema
   kolm asja: mis kuu, kui palju müüki, ja mis failid siit tulevad. Rohkem
   mitte — iga lisaelement siin on üks küsimus, mille raamatupidaja müüjale
   esitab, ja müüja ei tea vastust. */
.koond-intro{margin-bottom:20px}
.koond-intro .lead{margin:0 0 8px}
.koond-intro .micro{margin:0}

/* Kuuvalik on RIBA, mitte rippmenüü: kaksteist kuud on korraga nähtavad ja
   „eelmine kuu" (see, mida päriselt vajatakse) on teine element vasakult,
   mitte kahe klõpsu taga. */
.koond-kuud{
  display:flex;flex-wrap:wrap;gap:8px;
  margin:0 0 20px;
}
.koond-kuu{
  display:inline-flex;align-items:center;min-height:44px;
  padding:0 16px;border-radius:var(--r-full);
  background:var(--paper-2);box-shadow:var(--hair);
  color:var(--ink-2);font-size:var(--t-small);font-weight:700;text-decoration:none;
  transition:background-color var(--fast) var(--ease),color var(--fast) var(--ease);
}
.koond-kuu:hover{background:var(--green-mist);color:var(--green-3)}
.koond-kuu.is-current{
  background:var(--green);color:#fff;box-shadow:var(--shadow-1);
  cursor:default;pointer-events:none;
}

/* Kuu number on lehe suurim asi, sest see on ainus arv, mida müüja siit
   MEELDE JÄTAB — ta kontrollib teda oma peas pangakonto vastu. */
.koond-summa{
  display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 16px;
  margin:0 0 18px;padding:16px 18px;
  border-radius:var(--r-lg);background:var(--card);box-shadow:var(--hair),var(--shadow-1);
  color:var(--ink-2);font-size:var(--t-small);
}
.koond-summa strong{color:var(--ink);font-size:var(--t-h3);font-weight:900;letter-spacing:-.02em}

.koond-failid{display:grid;gap:12px;margin:0;padding:0;list-style:none}
.koond-failid a{
  display:grid;gap:4px;
  padding:16px 18px;border-radius:var(--r-lg);
  background:var(--card);box-shadow:var(--hair),var(--shadow-1);
  color:var(--ink);text-decoration:none;
  transition:box-shadow var(--base) var(--ease),translate var(--fast) var(--ease);
}
.koond-failid a:hover{box-shadow:inset 0 0 0 2px var(--green),var(--shadow-2);translate:0 -1px}
.koond-failid strong{font-size:1.05rem;font-weight:800}
/* 🔴 SELETUS ON OSA LINGIST, MITTE TEMA KÕRVAL. Müüja ei tea, mis vahe on
   „käibel" ja „tehingutel" — ja kui ta valib vale faili, saab raamatupidaja
   poole tööd. Üks lause iga faili kohta on odavam kui üks e-kiri. */
.koond-failid span{color:var(--ink-2);font-size:var(--t-small);line-height:1.5}

.proovi-list{display:grid;gap:12px;margin:22px 0;padding:0;list-style:none}
.proovi-item{
  padding:16px 18px;border-radius:var(--r-lg);
  background:var(--card);box-shadow:var(--hair);
}
/* Klõbistatud jagu seisab esimesena JA on märgitud — prospekt klõpsas
   konkreetset punkti ja peab kohe nägema, et vastus on tema oma. */
.proovi-item.is-current{box-shadow:inset 0 0 0 2px var(--green),var(--shadow-1)}
.proovi-item h2{margin:0 0 4px;font-size:1.05rem;font-weight:800}
.proovi-item p{margin:0;color:var(--ink-2);font-size:var(--t-small)}

/* --- TELLIMUSE ÜLEANDMISPLOKK ---------------------------------------------
   Ekraan on ÜLEANDMISHETKE jaoks: müüja loeb nime valjusti ette ja kontrollib
   ühe pilguga, kas makstud. Seepärast on nimi siin suurim asi lehel — suurem
   kui tellimuse number, mida keegi valjusti ei ütle. */
.order-handover{
  display:grid;gap:6px;justify-items:start;
  padding:18px 20px;margin:0 0 14px;
  border-radius:var(--r-lg);background:var(--green-pale);
}
.order-handover-who{
  margin:0;color:var(--ink);
  font-size:clamp(1.5rem,4.5vw,2rem);font-weight:900;letter-spacing:-.02em;
}
.order-handover-state{display:flex;align-items:center;gap:12px;margin:0}
.order-handover-state>strong{
  color:var(--green);font-size:1.35rem;font-weight:900;
  font-variant-numeric:tabular-nums;
}
.order-handover-mail{margin:0;color:var(--ink-2);font-size:var(--t-small)}
/* Number, kanal, aeg ja makseviis on VÄIKSELT — neid vaadatakse hiljem,
   mitte leti taga. */
.order-detail-meta{margin-top:14px;font-size:var(--t-small);color:var(--ink-2)}

/* --- TELLIMUSE POPOVER ----------------------------------------------------
   Natiivne `<dialog>`: fookuslõks, Esc ja taustaklõps tulevad brauserilt.
   Müüja ei lahku kassast, et vaadata, mida telliti. */
.pos-order{
  width:min(560px,92vw);max-height:min(86dvh,760px);
  padding:0;border:0;border-radius:var(--r-lg);
  background:var(--card);box-shadow:var(--shadow-2);color:var(--ink);
}
.pos-order::backdrop{background:rgba(15,21,17,.42);backdrop-filter:blur(3px)}
/* 🔴 AINUS KOHT KASSAS, KUS TEINE KERIMISALA ON LUBATUD — ja ta on lubatud
   sellepärast, et dialoog EI OLE leht. Ta on ajutine aken lehe peal ja tema
   sees kerimine ei võistle lehe kerimisega, sest leht on tema taga lukus
   (`showModal()` teeb `inert`). Keeld puudutas kahte samaaegselt kerivat ala
   ÜHEL ekraanil; siin on neid korraga üks. */
.pos-order-body{overflow:auto;overscroll-behavior:contain;padding:22px var(--gutter) 0}
.pos-order-body>*+*{margin-top:12px}
.pos-order-close{position:sticky;bottom:0;padding:14px var(--gutter);background:var(--card)}
.pos-order-close .button{width:100%}

/* --- 23.7 KORVIVAADE (UX-SPETS §5.2) ------------------------------------ */
.pos-lines{list-style:none;margin:0;padding:0;display:grid;gap:8px;align-content:start}
.pos-line{
  display:grid;grid-template-columns:minmax(0,1fr) 60px 40px 60px;
  align-items:center;column-gap:8px;row-gap:2px;
  min-height:72px;padding:10px 14px;
  border-radius:var(--r-md);background:var(--card);
  box-shadow:var(--hair),var(--shadow-1);
}
.pos-line-name{grid-column:1;grid-row:1;overflow-wrap:anywhere;font-size:1rem;font-weight:750}
.pos-line-meta{grid-column:1;grid-row:2;color:var(--ink-3);font-size:var(--t-small);font-variant-numeric:tabular-nums}
.pos-line-meta strong{color:var(--ink);font-weight:850}
/* 🔴 `−` ja `+` ON NEUTRAALSED, MITTE ROHELISED. Roheline on selles failis
   RAHA ja KINNITUS (sama värv, mis makse kinnitusel, DISAIN.md). Koguse
   muutmine ei ole kumbki. Nii kannab roheline ekraanil täpselt ÜHTE tähendust:
   hind, kogusemärk, korvirõngas, maksenupp. */
.pos-step{
  grid-row:1/3;display:grid;place-items:center;
  width:60px;height:60px;padding:0;
  border:0;border-radius:var(--r-full);
  background:var(--paper-2);box-shadow:var(--hair);
  color:var(--ink);font-size:1.6rem;font-weight:900;line-height:1;cursor:pointer;
}
.pos-step:active{background:var(--paper-3)}
.pos-step:disabled{color:var(--ink-3);box-shadow:none;cursor:not-allowed}
.pos-step-minus{grid-column:2}
.pos-line-qty{grid-column:3;grid-row:1/3;justify-self:center;min-width:40px;text-align:center;font-size:1.15rem;font-weight:900;font-variant-numeric:tabular-nums}
.pos-step-plus{grid-column:4}
/* „−" ja „+" servade vahe = 40 + 8 + 8 = 56 px ≥ 32 px (MIL-STD-1472H ≥5 mm).
   See paar on kogu liidese tõenäolisim valepuude koht — ÄRA KITSENDA. */
.pos-line-price{grid-column:1/-1;grid-row:3}
.pos-line-price summary{display:grid;align-items:center;min-height:44px;color:var(--ink-3);font-size:var(--t-small);font-weight:800;cursor:pointer}
.pos-line-price input{width:100%;max-width:160px;min-height:44px;padding:0 10px;border:1px solid var(--line);border-radius:var(--r-sm);font:inherit;font-variant-numeric:tabular-nums}
.pos-lines-note{margin:0;color:var(--ink-3);font-size:var(--t-small)}

/* --- 23.8 TÜHJENDAMISE KINNITUS ----------------------------------------- */
/* Ainus kinnitusdialoog kogu kassas ja ta on TÄISEKRAAN (UX-SPETS §5.2).
   `window.confirm()` ei esine kassateel kordagi — teda klõpsatakse läbi
   lugemata ja modaal on päikeses loetamatu. */
.pos-body-ask{justify-content:center}
.pos-ask{margin:auto 0;text-align:center}
.pos-ask h2{margin:0 0 8px;font-size:var(--t-h2)}
.pos-ask p{margin:0;color:var(--ink-2);font-size:var(--t-lead)}
/* --- SULARAHA: neli asja ülalt alla, null valikut -------------------------
   Esimene versioon oli VORM — kolm kiirnuppu, vaba väli, eraldi „Arvuta"
   nupp ja siis salvestus. Neli otsust seal, kus letis on aega ühe jaoks.
   Kiirnupud tundusid abina, aga nad on VALIK, ja valik on samuti töö. */
/* 🔴 `minmax(0,1fr)`, MITTE vaikimisi. Grid-elemendi vaikelaius on
   `min-content` ja `<input>` kannab brauseri sisemist `size`-laiust (~20 märki)
   — mõõdetud tagajärg oli 416 px väli 350 px konteineris ja terve leht kerkis
   horisontaalselt. Sama lõks nagu igal pool mujal selles failis: võre ei kahane
   ilma loata. Külgpolstrit siin EI OLE — `.pos-body` annab juba äärise ja kaks
   polstrit liitusid 40 pikslini. */
/* 🔴 SISU ON VERTIKAALSELT KESKEL, MITTE ÜLEVAL. Kolm elementi ülaservas
   jätsid alla 400 px tühja tausta ja ekraan luges pooleliolevana. Keskel on ta
   üks kompaktne asi, mille müüja haarab ühe pilguga.
   `minmax(0,1fr)` on veerule kohustuslik: `<input>` kannab brauseri sisemist
   `size`-laiust ja grid-element ei kahane ilma loata — mõõdetud tagajärg oli
   416 px väli 350 px konteineris ja terve leht kerkis horisontaalselt. */
/* `flex:1 1 auto`, MITTE `min-height:100%`. `.pos-body` on flex-veerg ilma
   määratud kõrguseta, seega protsent ei lahene millekski ja `align-content`
   ei saanud midagi keskele tõsta — mõõdetud: sisu 278 px 733 px konteineris,
   kõik ülaservas. Flex annab talle vaba ruumi ja alles siis on „keskel" tõene. */
.pos-cash,.pos-payment-choice{
  flex:1 1 auto;
  display:grid;grid-template-columns:minmax(0,1fr);gap:20px;
  padding:24px 0;align-content:center;justify-items:center;
}
.pos-payment-choice{text-align:center}
.pos-payment-choice>h2{margin:0;font-size:var(--t-h2)}
.pos-payment-due{display:grid;gap:5px;margin:0}
.pos-payment-due>span{
  color:var(--ink-3);font-size:var(--t-micro);font-weight:800;
  letter-spacing:.16em;text-transform:uppercase;
}
.pos-payment-due>strong{
  font-size:clamp(2.5rem,10vw,3.5rem);font-weight:900;line-height:1;
  letter-spacing:-.04em;font-variant-numeric:tabular-nums;
}
.pos-payment-choice>.payment-choice-grid{width:100%;margin:4px 0}
.pos-cash>*{width:100%}
.pos-cash .micro{text-align:center}
.pos-cash-contact,.pos-cash-discount label{display:grid;width:100%;gap:8px;text-align:left}
.pos-cash-contact>span,.pos-cash-discount label>span{color:var(--ink-2);font-size:var(--t-small);font-weight:800}
.pos-cash-contact input,.pos-cash-discount input{
  width:100%;min-width:0;min-height:54px;padding:0 14px;border:1px solid var(--line);
  border-radius:var(--r-md);background:#fff;color:var(--ink);font:inherit;
}
.pos-cash-discount{display:grid;width:100%;gap:10px;padding:16px;border-radius:var(--r-lg);background:var(--paper-2)}
.pos-cash-discount .button{min-height:54px}
.pos-discount-ok{margin:0;color:var(--green-2);font-size:var(--t-small);font-weight:800}
.pos-cash-backlinks{display:flex;flex:1 1 auto;align-items:center;justify-content:space-around;gap:10px;padding:0 var(--gutter)}
.pos-cash-backlinks .linkbutton{min-height:48px}
.pos-cash-backlinks .danger{color:var(--red)}
/* Kogu ekraan on ÜHEL TELJEL. Tasutav summa, sisestusväli ja vastus on kõik
   keskjoondatud — vasakjoondus jättis nad kolme eri telje peale ja silm pidi
   iga sammu juures kohta otsima. Kassaekraan on numbriekraan; number on siin
   peategelane ja ta seisab keskel. */
.pos-cash-row{display:grid;gap:4px;margin:0;justify-items:center;text-align:center}
.pos-cash-row>span{
  color:var(--ink-3);font-size:var(--t-micro);font-weight:800;
  letter-spacing:.16em;text-transform:uppercase;
}
.pos-cash-due{
  color:var(--ink);font-size:clamp(2.2rem,8vw,2.8rem);font-weight:900;
  letter-spacing:-.035em;line-height:1;font-variant-numeric:tabular-nums;
}
/* Valikulised väljad on kokku klapitud: nad on olemas siis, kui vaja, ja
   ekraanilt ära siis, kui ei ole. `<details>` töötab ilma JS-ita. */
.pos-cash-extra{width:100%;text-align:left}
.pos-cash-extra>summary{
  display:grid;place-items:center;
  min-height:44px;padding:0 14px;
  border-radius:var(--r-full);
  color:var(--ink-2);font-size:var(--t-small);font-weight:800;
  cursor:pointer;list-style:none;
}
.pos-cash-extra>summary::-webkit-details-marker{display:none}
.pos-cash-extra>summary::after{content:" ▾";color:var(--ink-3)}
.pos-cash-extra[open]>summary::after{content:" ▴"}
.pos-cash-extra>*+*{margin-top:10px}
.pos-cash-contact,.pos-cash-discount label{display:grid;gap:6px;margin:0}
.pos-cash-contact>span,.pos-cash-discount label>span{
  color:var(--ink-2);font-size:var(--t-small);font-weight:800;
}
.pos-cash-contact>input,.pos-cash-discount input{
  width:100%;min-width:0;min-height:52px;padding:0 14px;
  border:1px solid var(--line);border-radius:var(--r-md);background:#fff;
  color:var(--ink);font:inherit;font-size:var(--t-body);
}
.pos-cash-discount{display:grid;gap:10px;margin:0}
.pos-cash-discount input{text-transform:uppercase;letter-spacing:.08em;font-weight:800}
.pos-discount-ok{margin:0;color:var(--green);font-size:var(--t-small);font-weight:800}

.pos-cash-field{display:grid;gap:8px;margin:0;justify-items:center;text-align:center}
.pos-cash-field>span{
  color:var(--ink-2);font-size:var(--t-small);font-weight:800;
}
/* Väli on ekraani suurim sihtmärk: ta ON see, mida müüja siia tuli tegema. */
.pos-cash-field>input{
  width:100%;min-width:0;
  min-height:76px;padding:0 18px;
  border:2px solid var(--line);border-radius:var(--r-lg);background:#fff;
  color:var(--ink);font:inherit;
  font-size:2rem;font-weight:900;letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;text-align:center;
}
.pos-cash-field>input:focus-visible{outline:0;border-color:var(--green-2);box-shadow:0 0 0 5px var(--green-pale)}
/* Vastus. Kriips, mitte „0,00 €": null loeks nagu vastus, kriips ütleb ausalt,
   et küsimust ei ole veel esitatud. */
/* `[hidden]` PEAB võitma. Vaikimisi annab brauser `display:none`, aga iga
   selgesõnaline `display` lööb ta üle — element jäi ekraanile ja „ilmub alles
   siis, kui summa on sisestatud" oli lubadus, mida CSS vaikselt tühistas. */
.pos-cash-back[hidden]{display:none}
.pos-cash-back{
  display:grid;gap:2px;margin:0;padding:16px 18px;
  border-radius:var(--r-lg);background:var(--green-pale);text-align:center;
}
.pos-cash-back>span{
  color:var(--green);font-size:var(--t-micro);font-weight:800;
  letter-spacing:.16em;text-transform:uppercase;
}
.pos-cash-back>strong{
  color:var(--green-2);font-size:clamp(2.6rem,10vw,3.4rem);font-weight:900;
  letter-spacing:-.035em;line-height:1;font-variant-numeric:tabular-nums;
}
.pos-cash-back.is-short{background:var(--red-pale)}
.pos-cash-back.is-short>span{color:var(--red)}
.pos-cash-back.is-short>strong{color:var(--red)}
.pos-cash-warn{
  display:grid;place-items:center;margin:0;
  color:var(--red);font-size:var(--t-small);font-weight:800;
}
.pos-foot{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px 22px;
  margin-top:auto;padding:10px 0;border-top:1px solid var(--line);
  color:var(--ink-3);font-size:var(--t-small);
}
.pos-foot p{margin:0}
.pos-foot strong{color:var(--ink-2);font-weight:800}
.pos-foot nav{display:flex;flex-wrap:wrap;gap:2px 18px}
.pos-foot a{display:inline-flex;align-items:center;min-height:44px;color:var(--ink-2);font-weight:700;text-decoration:none}

/* --- 23.9 LAUAARVUTI ----------------------------------------------------- */
/* Kassal EI OLE teist veergu üheski laiuses. See ei ole kompromiss, see on
   PARANDUS: teine veerg tähendaks teist kasvavat sisu ja kleepuvat paneeli selle
   sees — täpselt see, mille Martti mõõtis „kahe scrollitava alana". Lauaarvuti
   võit on tihedus (4–6 veergu ühe pilguga), mitte veerg.
   `.admin-nav` riiul JÄÄB: ≥981 px maksab ta NULL vertikaalset pikslit. */
@media (min-width:981px){
  /* Laius tuleb muutujast, sest riba VOLDITAKSE kokku (`html.nav-peidus`,
     osa 41). Üleminek on lubatud alles siis, kui `pos.js` on salvestatud
     oleku kohale seadnud — muidu animeeriks leht laadimisel 220 → 76. */
  .pos-shell.has-nav{padding-left:var(--nav-w,220px)}
  html.nav-animeerib .pos-shell.has-nav{transition:padding-left var(--base) var(--ease)}
  /* ☰ ON LAUAARVUTIS DUBLIKAAT. Külgriba seisab ekraanil püsivalt ja kannab
     täpselt samu sihte — nupp, mis viib sinna, kus sa juba oled, õpetab müüjat
     päist mitte usaldama. Telefonis (≤980 px) on nav peidus ja ☰ on ainus
     väljapääs, seega seal ta JÄÄB. */
  /* Selektor peab võitma reegli `.pos-bar>:is(.pos-bar-clear,.pos-bar-more)`
     (0,2,0), mis annab talle `display:grid`. Meediapäring ei lisa kaalu. */
  .pos-bar>.pos-bar-more{display:none}
  .pos-bar{grid-template-columns:44px minmax(0,1fr)}
  /* Servani ulatuv sihtmärk on TELEFONI reegel telefoni põhjendusega (Hoober:
     67 % ühekäelistest kasutab paremat pöialt). Hiirel pöialt ei ole ja 990 px
     roheline plokk loeks nii, nagu oleks kogu ekraan nupp. */
  .pos-pay{width:auto;max-width:460px;justify-self:end;margin-right:var(--gutter);border-radius:var(--r-lg)}
}
@media (max-width:980px){
  /* 88 px nav + 144 px riba = 232 px alumist kroomi 844 px ekraanist ehk 27 %.
     See lammutaks kolme kihi mudeli. Väljapääs on päise ☰ ja UX-SPETS §5.4
     kehtestab kioskiloogika juba maksevaates.

     🔴 SELEKTOR ON `~`, MITTE TÜHIK — JA SEE VAHE MAKSIS MAKSENUPU.
     Reegel oli kirjutatud kujul `.pos-shell .admin-nav` (järglane), aga nav EI
     OLE kesta sees: nii `haldus-kassa.ts` kui `demo.ts` liidavad ta kesta
     KÕRVALE (`posScreen(...) + adminNav(...)`), sest kest on `<form>` ja nav
     tema sees oleks pesastatud vorm. Reegel ei sobitunud seega MITTE KUNAGI.

     Mõõdetud tootmises 15.08.2026, 768×1024:
       .pos-pay    y 936…1024
       .admin-nav  y 936…1024,  z-index 80 vs riba 40
     Sama ristkülik. Maksenupp oli 88 pikslit 88-st kaetud, ehk kassas EI
     SAANUD tahvlis makset vastu võtta. Martti: „menüü alla jääb see võta makse
     vastu nupp nüüd tableti vaates."

     Demokassas tekkis see eile (`5f264ae`, lukustatud nav); päris kassas on ta
     olnud alates `687b15c`-st, ehk kogu POS-i ümberkirjutuse aja. Vana reegel
     nägi mõlemal juhul välja nagu ta töötaks. */
  .pos-shell~.admin-nav{display:none}
}
/* TAHVEL PÜSTASENDIS ON ERAND JA TA ON MÕÕDETUD, MITTE MAITSE.
   Spetsi 27 % on arvutatud TELEFONI kõrgusest (844 px). 1024 px kõrgusel on
   sama 232 px kroomi 23 % ja sisule jääb 792 px — rohkem, kui telefonil üldse
   kokku on. Menüü peitmine oleks siin hind ilma põhjuseta, ja demokassas maksab
   ta kõige rohkem: lukustatud nav ON müügiargument („kassa ei ole ainus").

   Piire on KAKS, sest telefonid on muutunud pikaks: iPhone 15 Pro Max on
   püstasendis 932 px kõrge ja läbiks üksiku `min-height` tingimuse. Tahvel on
   ühtaegu LAI ja KÕRGE. 600 px on tahvli alumine serv (iPad mini 744 px, iPhone
   Pro Max 430 px).

   🔴 RIBA TÕSTAB `bottom`, MITTE KESTA `padding-bottom`. Proovisin kõigepealt
   polstrit ja MÕÕTSIN, et see on vale: `.pos-bottom` ei ole kesta laps vaid
   elab `.pos-body` sees, seega kesta polster ei piira teda — ta lihtsalt lükkas
   kogu lehe 88 px allapoole ja maksenupp läks y 1080 peale, ehk 1024 px
   vaateavast TÄIESTI välja. Hullem kui algne viga.
   Kleepuv element kuuletub omaenda `bottom`-nihkele: `bottom:88px` paneb ta
   seisma täpselt navi kohale. Voos jääb ta samasse kohta, seega ükski rida ei
   kao ega teki teist kerimisala. */
@media (max-width:980px) and (min-width:600px) and (min-height:900px){
  .pos-shell~.admin-nav{display:grid}
  .pos-bottom{bottom:calc(88px + env(safe-area-inset-bottom))}
  html:has(.pos-shell){scroll-padding-bottom:244px}
}
/* Rõhtpaigutus JA 200 % suum (WCAG 1.4.4 — suumitud vaateava on madal vaateava,
   mitte äärejuht). 844×390: 48 + 116 = 164 px kroomi, kataloogile 226 px = 2 rida. */
@media (max-height:560px){
  .pos-shell{--pos-head:48px;--pos-tile:76px;--pos-bar:116px}
  .pos-bottom{grid-template-rows:minmax(44px,auto) minmax(72px,auto)}
  .pos-pay{min-height:72px}
  .pos-pay-sum{font-size:1.6rem}
  html:has(.pos-shell){scroll-padding-top:56px;scroll-padding-bottom:128px}
}
@media print{
  /* Kroom ei ole dokument. Kassaekraani prindib müüja ainult tootenimekirja
     pärast, ja siis ei tohi 144 px roheline nupp lehte süüa. */
  .pos-head,.pos-bottom{display:none}
  .pos-shell{display:block;min-height:0;background:none}
  .pos-body{display:block;padding:0}
}

/* --- 23.10 NELI SEISUKLASSI, MIDA pos.js JUBA KIRJUTAB ------------------- */
/* 🔴 `grep -n "is-late\|is-offline\|is-expired\|is-idle" public/s/app.css` andis
   ENNE seda plokki 0 vastet, kuigi `public/s/pos.js` r148/173/191/196/253
   kirjutab neid kõiki. Ehk makseootel ekraani seisundid olid NÄHTAMATUD ja
   ainus muutus oli tekst. Neli rida, mis panevad juba kirjutatud koodi tööle. */
.waiting.is-late .waiting-dot{background:var(--amber)}
.waiting.is-offline{box-shadow:inset 0 0 0 1.5px var(--amber-line)}
.waiting:is(.is-offline,.is-expired,.is-idle) .waiting-dot{animation:none;background:var(--ink-3)}
.waiting:is(.is-expired,.is-idle){color:var(--ink-2)}

/* ═══════════════════════════════════════════════════════════════════════════
   23. KASSA (POS) — LÕPP
   ═══════════════════════════════════════════════════════════════════════════ */


/* ═══ MUUDATUSED OLEMASOLEVATES OSADES (väike diff, suur mõju) ═══════════ */

/* osa 32, r2528 ja r2587 ja r2691 — `hidden` → `hidden;clip` PAARINA.
   `overflow:clip` EI LOO kerimiskonteinerit (CSS Overflow 3), `hidden` loob.
   Paar hoiab Safari <16 töökorras ja annab uuematele õige semantika. See ei ole
   regressioon vaid tagavara — ära „lihtsusta" ühte deklaratsiooniks. */
.pos-tape{overflow:hidden;overflow:clip}
.pos-feed-alert{margin:0 0 10px}
.pos-feed-alert a{
  display:block;padding:11px 14px;border-radius:var(--r-md);
  background:var(--green-pale);color:var(--green-3);font-weight:800;text-align:center;
  box-shadow:inset 0 0 0 1px rgba(11,107,46,.16);
}
.pos-day{overflow:hidden;overflow:clip}
.empty-first-step{overflow:hidden;overflow:clip}

/* osa 41.2, r4512 — selektor `.tape-orders` → KÕIK `.pos-tape` lindid.
   Vana kommentaar väitis, et `.pos-tape` on kassa ostukorv kogusenupu ja
   summaga. KONTROLLITUD: haldus-kassa.ts:164 `.pos-tape` on VIIMASTE TEHINGUTE
   nimekiri ja korviread elavad mujal. Seega surus tänane reegel mõlema kassa
   lindi 375 px juures kolme veergu kokku ilma ühegi põhjuseta. */
@media (max-width:620px){
  .pos-tape>li:not(.tape-day){grid-template-columns:minmax(0,1fr) auto;column-gap:12px}
  .pos-tape>li>.tape-name{grid-column:1;grid-row:1}
  .pos-tape>li>.tape-sum{grid-column:2;grid-row:1;align-self:center}
  .pos-tape>li>.tape-note{grid-column:1;grid-row:2}
  .pos-tape>li>.status{grid-column:2;grid-row:2;justify-self:end;align-self:center}
}

/* ---------------------------------------------------------------------------
   24.1 LIIKUMINE KASSAEKRAANIL — kinnitus, mitte kaunistus
   ---------------------------------------------------------------------------
   Martti nõue 14.08.2026: „need tellimused mis sisse tulevad ja kassa teenimise
   ülevaade peaks olema ilusalt animeeritud, et see annaks selle highend tunde".

   Kaks reeglit, mis hoiavad selle kaunistusest eemal:
   1. Liikumine ütleb, MIS MUUTUS. Lindi rida tuleb sisse, sest ta on UUS.
      Päevanumber liigub, sest ta KASVAS. Miski ei liigu lihtsalt ilu pärast.
   2. `prefers-reduced-motion` kate on KOHUSTUSLIK (DISAIN.md) ja ta on
      failis juba olemas — need reeglid langevad tema alla automaatselt. */

@keyframes pos-tape-in{
  from{opacity:0;transform:translateY(10px)}
  to{opacity:1;transform:none}
}
/* Astmeline viivitus tuleb `:nth-child()`-ist, MITTE inline-stiilist
   (CSP `style-src 'self'`, DISAIN.md lõpp). Kuus rida, kuus astet. */
.pos-tape>li{animation:pos-tape-in var(--base) var(--ease) both}
.pos-tape>li:nth-child(2){animation-delay:40ms}
.pos-tape>li:nth-child(3){animation-delay:80ms}
.pos-tape>li:nth-child(4){animation-delay:120ms}
.pos-tape>li:nth-child(5){animation-delay:160ms}
.pos-tape>li:nth-child(6){animation-delay:200ms}

/* UUS rida — `pos.js` lisab klassi siis, kui tellimuse id on suurem kui see,
   mida leht laadimisel nägi. Roheline pulss kaob ise ja jätab tavalise rea. */
@keyframes pos-tape-new{
  0%{background:var(--green-pale);box-shadow:inset 3px 0 0 var(--green-2)}
  100%{background:transparent;box-shadow:inset 3px 0 0 transparent}
}
.pos-tape>li.is-new{animation:pos-tape-in var(--base) var(--ease) both,pos-tape-new var(--slow) var(--ease) 1}

/* Päevanumbri kasv. `pos.js` loeb sihtväärtuse ja tiksutab teda; CSS annab
   ainult lühikese tõuke, et silm muutust MÄRKAKS. */
@keyframes pos-count-bump{
  0%{transform:none}
  40%{transform:translateY(-3px) scale(1.05)}
  100%{transform:none}
}
.pos-idle strong.is-counting,.pos-day strong.is-counting{
  animation:pos-count-bump var(--base) var(--ease) 1;
  display:inline-block;
}

/* ---------------------------------------------------------------------------
   24. QR-EKRAAN
   ------------------------------------------------------------------------ */
.qr-screen{max-width:760px;margin:auto;text-align:center}
.qr-screen .eyebrow{margin-inline:auto}
.qr-screen h1{font-size:var(--t-h1)}
/* Vaikne ala on SVG sees; väline polster kahandaks skannitavaid mooduleid. */
.qr-screen svg{display:block;width:min(78vw,300px);min-width:260px;height:auto;margin:4px auto}
/* 🔴 SUMMA JA QR OLID MÕLEMAD PEAAEGU MUSTAD JA SULASID KOKKU.
   `--ink` (#0F1511) summa istus otse QR-i moodulite kohal, mis on #000 —
   kaks musta plokki üksteise otsas. Ostja peab summat kontrollima ENNE kui ta
   pangas kinnitab, ja ta ei leidnud teda üles.

   Summa on nüüd ROHELINE (`--green`, DISAIN.md rahavärv: „ainus signaal, mis
   päikeses turuletil läbi läheb") ja kannab silti. QR jääb ainsaks mustaks
   asjaks ekraanil — kaks eri asja, kaks eri värvi, null kokkusulamist. */
.qr-amount{
  display:grid;justify-items:center;gap:2px;
  margin:0 0 10px;
}
.qr-amount-label{
  color:var(--ink-3);
  font-size:var(--t-micro);font-weight:800;
  letter-spacing:.16em;text-transform:uppercase;
}
/* `--green` (#0B6B2E) oli 41 px numbri jaoks liiga tume ja luges peaaegu
   mustana — ehk täpselt see, mille eest ta pidi eristuma. `--green-2`
   (#12A150) on DISAIN.md „elav aktsent"; suure rasvase teksti kontrast
   heleda paberi vastu on 3,4:1, mis ületab WCAG 1.4.3 suure teksti nõude 3:1. */
.qr-amount-value{
  color:var(--green-2);
  font-size:clamp(2.6rem,10vw,3.4rem);font-weight:900;
  letter-spacing:-.035em;line-height:1;
  font-variant-numeric:tabular-nums;
}

/* KIOSKIREŽIIM (UX-SPETS §5.4). Müüja pöörab avatud telefoni võõra poole:
   päist, kaubamärki, jalust ega ühtegi linki mujale siin EI OLE. Ainsad
   juhtelemendid on „Katkesta müük" ja „Kontrolli makset". */
.qr-kiosk .qr-kiosk-bar{
  display:flex;justify-content:flex-start;
  padding:10px var(--gutter) 0;
}
.qr-kiosk .qr-kiosk-bar .button{min-height:44px;padding-inline:18px;font-size:var(--t-small)}
/* Jalust siin EI RENDERDATA (vt `demo.ts` kommentaari) — peitmise reeglit
   siia ei kirjutata, sest peidetud link on ikka link. */
/* `.actions` on flex-kast ja flex EI PÄRI `text-align:center`-it. Ilma selle
   reata seisis „Kontrolli makset" ekraani vasakus servas ja „Katkesta müük"
   (tavaline `<p>`) keskel — kaks nuppu kahes eri joondes. */
.qr-screen .actions,.success .actions{justify-content:center}
.qr-screen .actions{margin-top:4px}
.qr-screen>.waiting{margin-block:0;padding:12px 18px}

/* ---------------------------------------------------------------------------
   25. HALDUS
   ------------------------------------------------------------------------ */
.admin>header{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;flex-wrap:wrap;margin-bottom:30px}
.admin>header h1{margin-bottom:0}
.admin>header .eyebrow{margin:12px 0 10px}

/* Horisontaalse kerimise varjud puhta CSS-iga: `local` gradiendid katavad
   servad, `scroll` gradiendid jäävad paigale ja paistavad välja ainult siis,
   kui sisu on kerimata. Null JS, null kerimiskuulajat. */
.table-wrap{
  overflow-x:auto;
  border-radius:var(--r-lg);
  box-shadow:var(--hair),var(--shadow-1);
  background:
    linear-gradient(90deg,#fff 32%,rgba(255,255,255,0)) left center/48px 100% no-repeat local,
    linear-gradient(-90deg,#fff 32%,rgba(255,255,255,0)) right center/48px 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%,rgba(10,52,28,.16),rgba(10,52,28,0)) left center/16px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%,rgba(10,52,28,.16),rgba(10,52,28,0)) right center/16px 100% no-repeat scroll,
    #fff;
}
.table-wrap table{min-width:640px}
.table-wrap th,.table-wrap td{padding:16px 18px}
.table-wrap thead th{
  font-size:var(--t-micro);text-transform:uppercase;letter-spacing:.11em;
  color:var(--ink-3);font-weight:800;
  border-bottom:1px solid var(--line-2);
}
.table-wrap tbody tr{transition:background var(--fast) var(--ease)}
.table-wrap tbody tr:hover{background:var(--green-mist)}
.table-wrap tbody tr:last-child td{border-bottom:0}
/* 🔴 VEERUD LOETAKSE LÕPUST, MITTE ALGUSEST — ja see on parandus, mis tehti
   TEIST KORDA.

   Esimene kord: siin seisis `nth-child(3)` = raha ja `last-child` = aeg, mis
   käis nelja veeru kohta, mida enam ei olnud → olekumärgis tõmmati paremasse
   serva ja SUMMA renderdati halli peenkirjana.
   Teine kord: `nth-child(5)` = raha käis VIIE veeru kohta, ja siis kadus
   `/haldus-demo`-lt ostja veerg (isikuandmed avalikul lehel, 13.08.2026) →
   sama viga, sama tabel, vastupidises suunas.

   Tabeleid on nüüd kaks ja nad on ERI LAIUSED, seda taotluslikult:
     `/haldus-demo`        Tellimus · Olek · Aeg · Summa            (avalik)
     `/haldus/tellimused`  Tellimus · Ostja · Olek · Aeg · Summa    (autenditud)
   Ostja veerg on ainus vahe ja ta on TÄPSELT see, mille pärast autentimine
   olemas on. Lõpust lugemine teeb mõlemad õigeks ja kolmandat parandust ei
   tule: raha on ALATI viimane veerg ja aeg tema ees, ükskõik kui palju
   veerge on ees. */
.admin td:last-child,.admin th:last-child{text-align:right;font-weight:800;font-variant-numeric:tabular-nums}
.admin tbody td:last-child{color:var(--ink);font-size:1.05rem}
.admin td:first-child{color:var(--ink-3);font-weight:700}
.admin td:nth-last-child(2){color:var(--ink-3);font-size:var(--t-small);white-space:nowrap}

.status{
  display:inline-flex;align-items:center;gap:8px;
  padding:7px 14px;border-radius:var(--r-full);
  font-weight:800;font-size:var(--t-small);white-space:nowrap;
}
.status::before{content:"";width:7px;height:7px;border-radius:50%;background:currentColor}
.status.paid{background:var(--green-pale);color:var(--green-3)}
.status.pending{background:var(--amber-pale);color:var(--amber)}

/* ---------------------------------------------------------------------------
   26. MOBIIL
   375px on turuleti standardseade. Seda ei kontrollita „ka mobiilis" —
   siin see leht ELAB.
   ------------------------------------------------------------------------ */
@media (max-width:1000px){
  .checkout-layout{grid-template-columns:1fr}
  /* Kokkuvõte läheb vormi ETTE, sest telefonis peab ostja enne sisestamist
     nägema, mille eest ta maksab. */
  .order-summary{position:static;order:-1}
  .checkout-layout{display:flex;flex-direction:column}
}

/* Hero laguneb varem kui muu leht: kaks veergu 900px peal tähendaks 14ch
   pealkirja umbes 380px laiuses tulbas ja see on lugemiseks liiga kitsas. */
@media (max-width:900px){
  .hero{grid-template-columns:1fr;padding:32px 20px 56px;gap:30px}
  .hero>.hero-art{grid-row:1;max-height:290px}
  .hero h1{max-width:none}
}

@media (max-width:820px){
  .landing-nav nav>a:not(.button){display:none}
  .sitebar{padding:14px 18px}
  .steps,.feature-grid,.audiences{grid-template-columns:1fr}
  .steps article,.feature-grid article{padding:26px 24px 28px}
  .pricing-section{grid-template-columns:1fr;gap:30px}
  .banks{grid-template-columns:1fr}
  .receipt{margin:0;border-radius:0;box-shadow:none}
  .receipt::before{display:none}
  .receipt-head{gap:16px}
}

@media (max-width:660px){
  /* Korvirida laguneb telefonis kolmeks reaks: mis, kui palju, kui kallis. */
  .cart-row{
    grid-template-columns:minmax(0,1fr) auto;
    grid-template-areas:"main main" "qty total" "remove remove";
    row-gap:14px;
  }
  .cart-row-form{justify-content:flex-start}
  .cart-row-total{align-self:end}
  .cart-row-remove{justify-self:start}
}

.mobile-primary{display:none}

@media (max-width:620px){
  /* Lai sammunäidik ei mahu 375px peale loetavalt — tekstirida mahub.
     🔴 `inline-flex` oli VIGA: näidiku ees seisab `.backlink`, mis on samuti
     inline-tasandil, nii et kaks kapslit jäid 375px peal ÜHELE reale nulli
     vahega ja nägid välja nagu kokku jooksnud element. `flex` on
     ploki-tasandi kast → oma rida; `width:max-content` hoiab kapsli teksti
     ümber, mitte üle terve laiuse. */
  .checkout-steps{display:none}
  .checkout-progress{
    display:flex;width:max-content;max-width:100%;
    margin:16px 0 22px;
  }
}

@media (max-width:560px){
  /* Telefonis on kaks kõrvutist nuppu alati liiga kitsad — üksteise all ja
     täislaiuses on need pöidlaga tabatavad. */
  .actions{flex-direction:column;align-items:stretch}
  .cart-banner .button{width:100%}
  /* 🔴 SIIN OLI 96 px KAHEREALINE TOOTEPLAAT oma `grid-column`-paigutustega.
     Kui rida sai uue kuju (nupp `.pos-product-add` on nüüd ISE ruudustik),
     jäid vanad reeglid alles — ja kuna `.pos-product strong` on JÄRGLAS-
     selektor, tabas ta edasi sama `<strong>`-i uue nupu sees ning surus hinna
     `grid-column:1;grid-row:2` peale. Teine veerg jäi 0 px laiaks ja hind
     murdus nime alla 64 px ritta, kust `overflow:hidden` ta pooleks lõikas.
     Surnud reegel ei ole kahjutu, kui ta selektor uut markup'i endiselt tabab.
     Rea päris kuju on all osas 44. */
  .success-mark{width:96px;height:96px;font-size:3.2rem}
  .cart-total{flex-direction:column;align-items:flex-start;gap:4px}
  .checkout-company,.field-group{padding-left:16px;padding-right:16px}
  .checkout-company summary{margin:0 -16px;padding:0 16px}
  .table-wrap th,.table-wrap td{padding:14px}
  .trust-chip{font-size:var(--t-micro)}
}


/* ---------------------------------------------------------------------------
   39. MAKSESEADED (`src/routes/haldus-makse.ts`)

   Oodatud kuju: `.payment-settings` sees on aktiivse valiku plokk,
   `.payment-grid` ning selle sees mitu `article.payment-credential` elementi.
   Iga kaardi `.payment-actions` sisaldab eraldi POST-vorme; vorme ei pesastata.
   ------------------------------------------------------------------------ */
.order-line-discount{grid-column:1/-1;color:var(--ink-3);font-size:var(--t-micro)}
.receipt-price-list,.receipt-price-difference{display:block;color:var(--ink-3);font-size:var(--t-micro);white-space:nowrap}

.payment-settings{gap:24px}
.payment-active,.payment-credential{
  padding:clamp(20px,3vw,28px);border-radius:var(--r-lg);
  background:var(--card);box-shadow:var(--hair),var(--shadow-1);
}
.payment-active h2,.payment-credential h2{margin:.2em 0 .5em}
.payment-active p:last-child{margin-bottom:0}
.payment-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr));gap:18px}
.payment-credential dl{display:grid;gap:10px;margin:18px 0}
.payment-credential dl div{display:grid;grid-template-columns:minmax(100px,.7fr) 1.3fr;gap:12px}
.payment-credential dt{color:var(--ink-3);font-size:var(--t-small);font-weight:750}
.payment-credential dd{margin:0;overflow-wrap:anywhere;font-weight:750}
.payment-actions{display:grid;gap:10px}
.payment-actions form{margin:0}
/* Vormide iga tegevus on letiseadmel terve 88px puuteala. */
.payment-actions .button,.payment-form>.button{width:100%;min-height:88px}
.payment-form{padding-block:10px 28px}

/* ---------------------------------------------------------------------------
   27. PRINT
   ------------------------------------------------------------------------ */
@media print{
  .sitebar,.identity,.print-button,.demo-banner,.landing-nav,.checkout-steps,.checkout-progress{display:none}
  html,body{background:#fff}
  body::before{display:none}
  .receipt{border:0;box-shadow:none;margin:0;max-width:none;padding:0;border-radius:0}
  .receipt::before{display:none}
  .receipt a{color:inherit;text-decoration:none}
  .brand::before{print-color-adjust:exact;-webkit-print-color-adjust:exact}
}

/* ---------------------------------------------------------------------------
   28. VÄHENDATUD LIIKUMINE — KOHUSTUSLIK (docs/DISAIN.md)
   ------------------------------------------------------------------------ */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;
    animation-iteration-count:1!important;
    transition-duration:.01ms!important;
  }
  html{scroll-behavior:auto}
}

/* ═══════════════════════════════════════════════════════════════════════════
   OSAD 29–37 — TOOTELEHT, ARVUSTUSED, SOODUSKOOD, MÜÜJA APP-KEST
   ═══════════════════════════════════════════════════════════════════════════

   Need stiilid on kirjutatud ETTE, kolme paralleelse agendi markupile.
   Sellest tuleneb üks reegel, mis kehtib kogu selle ploki kohta:

   🔴 ÜKSKI SELECTOR EI TOHI EELDADA TÄPSET ELEMENDIPUUD, mida ma ei näinud.
   Iga komponent on kirjutatud nii, et ta talub kahte-kolme mõistlikku
   markupikuju (`ul>li` VÕI `dl>dt+dd` VÕI `div>div`), ja tundmatu kuju korral
   kukub ta LOETAVAKS, mitte katkiseks. Kus kuju on paratamatult siduv, on
   leping kirjutatud kommentaari kohe reegli kohale.

   Uued abiklassid, mille ma siin KASUTUSELE VÕTAN (doktriin lubab lisada,
   mitte ümber nimetada):
     .vh              ekraanilugejale nähtav, silmale mitte
     .star .is-on     arvustuse tärn (svg või tekstiglüüf)
     .rating-value    number tärnide kõrval („4,6")
     .rating-star     .rating-input üksik tärninupp (kui ei ole <label>)
     .rating-bars     .rating-bar-ide mähis, annab kahe veeru paigutuse
     .rating-bar-track  riba täitesoon, kui ei taheta ::before'i
     .pct-0 … .pct-100  .rating-bar täitumus 5% sammuga (CSP ei luba style=)
     .app-head        päis .app-shell-is, kui ei kasutata <header>-it
     .pos-tape-row    lindirida, kui ei kasutata <li>-d
     .tape-name .tape-sum   lindirea väljad
   ------------------------------------------------------------------------ */

/* Ligipääsetav, aga nähtamatu tekst. Vajalik `.rating-input` juures (tärn on
   pseudoelement, seega päris nimi PEAB olema HTML-is) ja kassa otsingul.

   🔴 NIMI ON `sr-only`, MITTE `vh`. Utiliit kandis nime `.vh`, aga kogu markup
   kirjutab `class="sr-only"` — nii et ükski peitmine ei kehtinud. Kassas
   tähendas see, et ekraanilugeja silt „Otsi toodet" ja peidetud „Otsi" nupp
   renderdusid päris tekstina ja paisutasid 44 px otsinguriba 105 px-ni,
   surudes sisestusvälja 28 px laiuseks. Klass, mida CSS ei tunne, ei anna
   veateadet — ta lihtsalt ei tee midagi. Vana nime pole alles hoitud: grep
   kinnitab, et `class="vh"` ei esine üheski mallis. */
.sr-only{
  position:absolute;width:1px;height:1px;
  margin:-1px;padding:0;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0;
}

/* ---------------------------------------------------------------------------
   29. TOOTELEHT
   Poekaart müüb pilguga, tooteleht müüb TÕENDIGA. Seepärast on siin hind,
   laoseis, tarne ja taganemisõigus ÜHEL ekraanil — ostja ei pea otsima.
   ------------------------------------------------------------------------ */
/* Töötab nii `<main class="page toode-page">` kui `<main class="toode-page">`
   korral. Polster on sama, mis `.page`-l, nii et kombineerimine ei muuda midagi. */
.toode-page{
  max-width:var(--wrap);margin-inline:auto;
  padding:clamp(28px,4vw,48px) var(--gutter) clamp(64px,8vw,104px);
}

.product-hero{
  display:grid;grid-template-columns:minmax(0,1.02fr) minmax(0,.98fr);
  gap:clamp(24px,4vw,54px);align-items:start;
}

/* Vitriin. Sama retsept, mis `.product-art` poekaardil — tooteleht ei tohi
   näida teise disaineri tehtuna. `aspect-ratio` hoiab pesa stabiilsena ka
   siis, kui SVG on veel laadimata: null paigutushüpet. */
.product-media{
  --art-tint:var(--green-mist);
  --art-deep:#E9F1E6;
  position:relative;overflow:hidden;
  display:grid;place-items:center;
  aspect-ratio:4/3;
  margin:0;padding:clamp(18px,4vw,44px);
  border-radius:var(--r-xl);
  color:var(--green-3);
  background:
    radial-gradient(115% 88% at 26% 6%, rgba(255,255,255,.96), rgba(255,255,255,0) 58%),
    linear-gradient(158deg,var(--art-tint) 0%,var(--art-deep) 54%,var(--paper-3) 100%);
  box-shadow:var(--hair),var(--shadow-2),var(--edge);
}
/* Kontaktvari: ese SEISAB pinnal. Üks ellips teeb rohkem kui raam. */
.product-media::after{
  content:"";position:absolute;left:50%;bottom:11%;
  width:44%;height:18px;margin-left:-22%;border-radius:50%;
  background:radial-gradient(closest-side,rgba(10,52,28,.20),rgba(10,52,28,0));
  pointer-events:none;
}
.product-media>*{position:relative;z-index:1}
.product-media svg{width:min(74%,340px);height:auto;filter:drop-shadow(0 10px 18px rgba(10,52,28,.12))}
.product-media svg :is(path,circle,ellipse,line,polyline,polygon,rect){
  fill:none;stroke:currentColor;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;
}
.product-media img{width:100%;height:100%;object-fit:contain;border-radius:var(--r-lg)}

.product-info{display:grid;gap:16px;align-content:start;min-width:0}
.product-info h1{font-size:clamp(1.8rem,3.4vw,2.6rem);margin:0}
.product-info .price{margin:0;font-size:clamp(2rem,4.4vw,2.7rem)}
.product-info .stock{
  display:flex;align-items:center;gap:8px;
  margin:0;font-size:var(--t-small);font-weight:750;
}
.product-info .stock::before{content:"";flex:none;width:7px;height:7px;border-radius:50%;background:currentColor}
.product-info .lead,.product-info>p{color:var(--ink-2);margin:0;max-width:54ch}
.product-info form{display:grid;gap:12px}
.product-info .button{width:100%;min-height:88px;font-size:1.08rem}
/* Vitriin jääb kerimisel nähtavaks — ostja loeb tarnetingimusi ja näeb ikka,
   mida ta ostab. Ainult lauaarvutis: telefonis on pilt niikuinii eespool. */
@media (min-width:901px){
  .product-media{position:sticky;top:22px}
}

/* Faktiplokk. Kolm kuju korraga:
     <dl class="product-meta"><div><dt>…<dd>…</div></dl>   ← eelistatud
     <ul class="product-meta"><li><span>…<b>…</b></li></ul>
     <dl class="product-meta"><dt>…<dd>…</dl>              ← paljas dl */
.product-meta{
  list-style:none;
  margin:6px 0 0;padding:16px 0 0;
  border-top:1px solid var(--line);
  font-size:var(--t-small);
}
.product-meta>:is(div,li){
  display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;
  gap:4px 20px;padding:9px 0;
  border-bottom:1px solid var(--line);
}
.product-meta>:is(div,li):last-child{border-bottom:0}
.product-meta :is(dt,.meta-key)  {color:var(--ink-3);font-weight:700}
.product-meta :is(dd,.meta-value){
  margin:0;color:var(--ink);font-weight:800;text-align:right;
  font-variant-numeric:tabular-nums;overflow-wrap:anywhere;
}
/* Paljas `dl` — dt/dd otseste lastena. Ilma selleta laoks ta kaks veergu üksteise
   otsa ja faktiplokk näeks välja nagu poolik tabel. */
.product-meta:not(:has(>div,>li)){
  display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px 20px;align-items:baseline;
}
.product-meta:not(:has(>div,>li))>dd{text-align:right}

/* TARNE ja TAGANEMINE on eri kaalu infot ja neid EI TOHI kokku sulatada.
   Tarne on lubadus (roheline). Taganemine on ÕIGUS — VÕS §52, 14 päeva
   (vt docs/SPETSI-PARANDUSED.md rida 19/19b) — ja ta kannab neutraalset
   tinti, sest juriidiline tekst ei tohi näida müügiargumendina. */
.delivery-summary,.returns-summary{
  padding:clamp(16px,2.2vw,22px) clamp(18px,2.4vw,24px);
  border-radius:var(--r-lg);
  background:var(--card);
  box-shadow:var(--hair),var(--shadow-1),var(--edge);
}
.delivery-summary{background:linear-gradient(180deg,#fff,var(--green-mist))}
/* 🔴 `>` ON KOHUSTUSLIK ja `strong:first-child` peab olema OTSENE laps.
   `:first-child` loeb ELEMENTE, mitte tekstisõlmi — lauses
   „Veebist ostes on sul <strong>14 päeva</strong> …" on see `<strong>` oma
   lõigu esimene ELEMENT ja ilma `>`-ta sai temast versaalne pealkiri, mis
   murdis lause kolmeks reaks. */
.delivery-summary>:is(h2,h3),.delivery-summary>strong:first-child,
.returns-summary>:is(h2,h3),.returns-summary>strong:first-child{
  display:flex;align-items:center;gap:9px;
  margin:0 0 10px;
  font-size:var(--t-micro);font-weight:900;letter-spacing:.13em;text-transform:uppercase;
}
.delivery-summary>:is(h2,h3),.delivery-summary>strong:first-child{color:var(--green-3)}
.returns-summary>:is(h2,h3),.returns-summary>strong:first-child{color:var(--ink-3)}
.delivery-summary .ico{color:var(--green);width:18px;height:18px}
.returns-summary  .ico{color:var(--ink-3);width:18px;height:18px}
.delivery-summary p,.returns-summary p{margin:0 0 8px;color:var(--ink-2);font-size:var(--t-small);line-height:1.55}
.delivery-summary p:last-child,.returns-summary p:last-child{margin-bottom:0}
.delivery-summary strong,.returns-summary strong{color:var(--ink);font-weight:800}
.delivery-summary :is(ul,dl),.returns-summary :is(ul,dl){
  list-style:none;margin:0;padding:0;
  display:grid;gap:7px;
  font-size:var(--t-small);color:var(--ink-2);
}
.delivery-summary li,.returns-summary li{
  display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:4px 16px;
}
.delivery-summary li>:last-child,.returns-summary li>:last-child{
  color:var(--ink);font-weight:800;font-variant-numeric:tabular-nums;
}
.delivery-summary a,.returns-summary a{font-weight:750}

/* ---------------------------------------------------------------------------
   30. ARVUSTUSED
   🔴 VÄRVIPIMEDUS: hinnang ei tohi KUNAGI olla ainult värv. Siin kannab
   infot KOLM teineteisest sõltumatut kanalit:
     1. KUJU  — täidetud ★ vs õõnes ☆ (eri siluett, mitte eri toon)
     2. TEKST — number tärnide kõrval („4,6") ja `.rating-input`-is number
                iga tärni all
     3. HELEDUS — täidetud on tume tint, õõnes hall; erinevus jääb ka
                halltoonis trükituna alles
   Roheline on siin AINULT valitud oleku taust, mitte teabekandja.
   ------------------------------------------------------------------------ */
.reviews{
  max-width:var(--wrap);margin:clamp(40px,6vw,72px) auto 0;
  padding-top:clamp(28px,4vw,44px);
  border-top:1px solid var(--line);
}
.reviews>h2{font-size:var(--t-h2)}
.reviews>:is(ul,ol){list-style:none;margin:0;padding:0}

/* --- Koondhinnang ------------------------------------------------------- */
/* Eelistatud kuju:
     <div class="reviews-summary">
       <div class="reviews-score">…suur number + tärnid + arv…</div>
       <div class="rating-bars"><div class="rating-bar pct-60">…</div>…</div>
     </div>
   Kui `.rating-bar`-id on OTSESED lapsed, läheb iga riba omale reale — kitsam
   paigutus, aga mitte katki. */
.reviews-summary{
  display:flex;flex-wrap:wrap;align-items:center;
  gap:clamp(16px,3vw,38px);
  padding:clamp(20px,3vw,28px);margin:0 0 24px;
  border-radius:var(--r-xl);
  background:linear-gradient(180deg,var(--card),var(--green-mist));
  box-shadow:var(--hair),var(--shadow-1),var(--edge);
}
.reviews-summary>*{min-width:0}
.reviews-summary>:first-child{flex:0 0 auto}
.reviews-summary .reviews-score{display:grid;justify-items:center;gap:6px;text-align:center}
.reviews-summary .rating-value{
  padding:0;background:none;
  font-size:clamp(2.6rem,7vw,3.4rem);font-weight:900;
  letter-spacing:-.045em;line-height:1;color:var(--ink);
}
.reviews-summary .review-stars{font-size:1.28rem}
.reviews-summary .micro{margin:0}
.rating-bars{flex:1 1 260px;display:grid;gap:2px;min-width:0}
.reviews-summary>.rating-bar{flex:1 1 100%}

/* Riba täitumus tuleb KLASSIST, mitte `style`-atribuudist — CSP `style-src
   'self'` ei luba inline-stiili (doktriin §1). Server ümardab protsendi 5
   sammuni ja lisab `.pct-N`. `data-pct="N"` teeb sama.
   Riba ISE on `::before`, seega markupis on ainult silt ja arv. */
.rating-bar{
  --pct:0;
  display:grid;grid-template-columns:3.6em minmax(0,1fr) 3.2em;
  align-items:center;gap:12px;
  min-height:32px;
  color:var(--ink-2);font-size:var(--t-small);font-weight:750;
  font-variant-numeric:tabular-nums;
}
/* 🔴 IGA lahter on määratud KÄSITSI. Võre automaatpaigutus ei liigu kunagi
   tagasi: kui `::before` võtab veeru 2, jääb kursor veergu 3 ja esimene
   `<span>` lendaks riba PAREMALE poole, teine kukuks uude ritta. Mõõdetud
   ja parandatud, mitte teoreetiline. */
.rating-bar>:first-child{grid-column:1;grid-row:1;text-align:left}
.rating-bar>:last-child{grid-column:3;grid-row:1;text-align:right;color:var(--ink-3)}
.rating-bar::before{
  content:"";grid-column:2;grid-row:1;
  height:10px;border-radius:var(--r-full);
  background:
    linear-gradient(90deg,var(--green-3),var(--green-2)) left center/calc(var(--pct)*1%) 100% no-repeat,
    var(--paper-3);
  box-shadow:inset 0 0 0 1px rgba(10,52,28,.07);
}
/* Kui eelistatakse päris elementi pseudoelemendi asemel. Reegel peab tulema
   PÄRAST `:first-child`/`:last-child` omi — kaal on sama ja järjekord otsustab. */
.rating-bar>.rating-bar-track{
  grid-column:2;grid-row:1;
  height:10px;border-radius:var(--r-full);
  background:
    linear-gradient(90deg,var(--green-3),var(--green-2)) left center/calc(var(--pct)*1%) 100% no-repeat,
    var(--paper-3);
  box-shadow:inset 0 0 0 1px rgba(10,52,28,.07);
}
.rating-bar:has(>.rating-bar-track)::before{content:none}
.rating-bar.pct-0,.rating-bar[data-pct="0"]{--pct:0}
.rating-bar.pct-5,.rating-bar[data-pct="5"]{--pct:5}
.rating-bar.pct-10,.rating-bar[data-pct="10"]{--pct:10}
.rating-bar.pct-15,.rating-bar[data-pct="15"]{--pct:15}
.rating-bar.pct-20,.rating-bar[data-pct="20"]{--pct:20}
.rating-bar.pct-25,.rating-bar[data-pct="25"]{--pct:25}
.rating-bar.pct-30,.rating-bar[data-pct="30"]{--pct:30}
.rating-bar.pct-35,.rating-bar[data-pct="35"]{--pct:35}
.rating-bar.pct-40,.rating-bar[data-pct="40"]{--pct:40}
.rating-bar.pct-45,.rating-bar[data-pct="45"]{--pct:45}
.rating-bar.pct-50,.rating-bar[data-pct="50"]{--pct:50}
.rating-bar.pct-55,.rating-bar[data-pct="55"]{--pct:55}
.rating-bar.pct-60,.rating-bar[data-pct="60"]{--pct:60}
.rating-bar.pct-65,.rating-bar[data-pct="65"]{--pct:65}
.rating-bar.pct-70,.rating-bar[data-pct="70"]{--pct:70}
.rating-bar.pct-75,.rating-bar[data-pct="75"]{--pct:75}
.rating-bar.pct-80,.rating-bar[data-pct="80"]{--pct:80}
.rating-bar.pct-85,.rating-bar[data-pct="85"]{--pct:85}
.rating-bar.pct-90,.rating-bar[data-pct="90"]{--pct:90}
.rating-bar.pct-95,.rating-bar[data-pct="95"]{--pct:95}
.rating-bar.pct-100,.rating-bar[data-pct="100"]{--pct:100}

/* --- Tärnide KUVA -------------------------------------------------------- */
/* Leping (kumb tahes töötab):
     <span class="review-stars" data-rating="4,0">
       <span aria-hidden="true">★★★★☆</span></span>
     <span class="review-stars"><svg class="star is-on">…  <b class="rating-value">4,0</b></span>
   Number on KOHUSTUSLIK. Kui `.rating-value` puudub, joonistab CSS ta
   `data-rating`-ust — nii ei saa hinnang kunagi jääda ainult glüüfideks. */
.review-stars{
  display:inline-flex;align-items:center;gap:3px;
  color:var(--ink);
  font-size:1.06rem;line-height:1;letter-spacing:.08em;white-space:nowrap;
}
.review-stars>span[aria-hidden]{letter-spacing:.08em}
.review-stars :is(.rating-value,b,strong),
.review-stars[data-rating]:not(:has(.rating-value,b,strong))::after{
  margin-left:9px;padding:3px 9px;border-radius:var(--r-full);
  background:var(--paper-2);color:var(--ink);
  font-size:var(--t-small);font-weight:850;letter-spacing:0;
  font-variant-numeric:tabular-nums;
}
.review-stars[data-rating]:not(:has(.rating-value,b,strong))::after{content:attr(data-rating) " / 5"}
/* Tärn eraldi elemendina (svg või span). Täidetud = tume silueti, õõnes =
   ainult kontuur. Kuju erineb, mitte ainult toon. */
.review-stars .star{flex:none;width:18px;height:18px}
.review-stars svg.star{fill:none;stroke:var(--ink-3);stroke-width:1.8;stroke-linejoin:round}
.review-stars svg.star.is-on{fill:var(--ink);stroke:var(--ink)}
.review-stars span.star::before{content:"☆";color:var(--ink-3);font-size:1.06rem;line-height:1}
.review-stars span.star.is-on::before{content:"★";color:var(--ink)}

/* --- Üksik arvustus ------------------------------------------------------ */
.review{
  padding:20px clamp(18px,2.4vw,24px);margin:0 0 12px;
  border-radius:var(--r-lg);
  background:var(--card);
  box-shadow:var(--hair),var(--shadow-1);
}
.review:last-child{margin-bottom:0}
.review-head{
  display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px;
  margin-bottom:10px;
}
.review-head :is(.review-author,cite),
.review-head>strong{
  font-style:normal;font-weight:850;letter-spacing:-.012em;color:var(--ink);
}
.review-head :is(time,.review-date){
  color:var(--ink-3);font-size:var(--t-small);font-variant-numeric:tabular-nums;
}
/* Ostutõend on USALDUSSIGNAAL ja ta peab olema eristatav ka siis, kui roheline
   kaob (trükk, halltoon): tal on linnuke, mitte ainult roheline taust. */
.review-verified{
  display:inline-flex;align-items:center;gap:6px;
  padding:4px 11px;border-radius:var(--r-full);
  background:var(--green-pale);color:var(--green-3);
  font-size:var(--t-micro);font-weight:850;letter-spacing:.02em;white-space:nowrap;
  box-shadow:inset 0 0 0 1px rgba(11,107,46,.18);
}
.review-verified:not(:has(svg,.ico))::before{content:"✓";font-weight:900;line-height:1}
.review-verified .ico{width:14px;height:14px;color:var(--green-2)}

.review-body{
  margin:0;max-width:72ch;
  color:var(--ink-2);line-height:1.6;overflow-wrap:anywhere;
}
.review-body p{margin:0 0 .7em}
.review-body p:last-child{margin-bottom:0}

/* Müüja vastus on ALLUV element, mitte teine arvustus: taandes, oma taustaga
   ja nimeliselt märgistatud. Ilma märgistuseta loeks ostja seda arvustusena
   ja see oleks eksitav kaubandustava. */
.review-reply{
  position:relative;
  margin:14px 0 0;padding:13px 16px;
  border-radius:var(--r-md);
  background:var(--green-mist);
  color:var(--ink-2);font-size:var(--t-small);line-height:1.55;
  box-shadow:inset 3px 0 0 var(--green-2),inset 0 0 0 1px rgba(11,107,46,.10);
}
.review-reply>:is(strong,b,.review-reply-who):first-child{
  display:block;margin-bottom:5px;
  color:var(--green-3);font-size:var(--t-micro);font-weight:900;
  letter-spacing:.11em;text-transform:uppercase;
}
.review-reply p{margin:0 0 .6em}
.review-reply p:last-child{margin-bottom:0}

/* Läbipaistvusteade. EL 2005/29 art 7 lg 6 (Omnibus) nõuab, et pood ÜTLEKS,
   kas ja kuidas arvustuste päritolu kontrollitakse. See ei ole peenkiri, mille
   võib ära jätta — ta on eeldus, et arvustusi tohib üldse näidata. */
.review-disclosure{
  margin:0 0 20px;padding:13px 18px;
  border-radius:var(--r-md);
  background:var(--paper-2);
  color:var(--ink-2);font-size:var(--t-small);line-height:1.55;
  box-shadow:inset 0 0 0 1px var(--line);
}
.review-disclosure>summary{
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  min-height:44px;margin:-13px -18px;padding:0 18px;
  color:var(--ink);font-weight:800;cursor:pointer;list-style:none;
}
.review-disclosure[open]>summary{margin-bottom:5px}
.review-disclosure>summary::-webkit-details-marker{display:none}
.review-disclosure>summary::after{
  content:"+";flex:none;display:grid;place-items:center;
  width:28px;height:28px;border-radius:50%;
  background:#fff;color:var(--ink-2);
  font-size:1.25rem;font-weight:400;line-height:0;
  box-shadow:inset 0 0 0 1px var(--line-2);
  transition:transform var(--base) var(--ease);
}
.review-disclosure[open]>summary::after{transform:rotate(45deg)}
.review-disclosure p{margin:8px 0 0;max-width:72ch}
.review-disclosure p:first-of-type{margin-top:0}
.review-disclosure a{font-weight:750}

/* --- Arvustuse VORM (kviitungil) ---------------------------------------- */
.review-form{
  display:grid;gap:16px;
  padding:clamp(20px,3vw,26px);
  border-radius:var(--r-xl);
  background:linear-gradient(180deg,var(--card),var(--green-mist));
  box-shadow:var(--hair),var(--shadow-1),var(--edge);
}
.review-form :is(h2,h3){margin:0;font-size:1.15rem}
.review-form>p{margin:0;color:var(--ink-2);font-size:var(--t-small);line-height:1.55}
.review-form textarea{
  display:block;width:100%;min-height:132px;padding:16px 18px;
  border:1px solid var(--line-2);border-radius:var(--r-md);
  background:#fff;font-family:var(--sans);font-size:1.02rem;line-height:1.55;
  resize:vertical;
  box-shadow:inset 0 1px 2px rgba(10,52,28,.05);
  transition:border-color var(--fast),box-shadow var(--fast);
}
.review-form textarea:hover{border-color:var(--line)}
.review-form textarea:focus{
  border-color:var(--green);
  box-shadow:inset 0 1px 2px rgba(10,52,28,.04),0 0 0 4px var(--green-pale);
}
.review-form .button{width:100%;min-height:88px;font-size:1.06rem}

/* --- Hinde SISESTUS ------------------------------------------------------ */
/* 🔴 TÖÖTAB ILMA JS-ITA. Viis raadionuppu, null skripti.
   Leping:
     <fieldset class="rating-input">
       <legend>Kui rahul olid?</legend>
       <label><input type="radio" name="hinne" value="1"><span class="vh">1 tärn viiest</span></label>
       … kokku VIIS <label>-it, järjekorras 1→5 …
     </fieldset>
   Tärn ja number tulevad CSS-ist (`::before` / `counter`), seega markup jääb
   puhtaks ja number on ALATI olemas — ka siis, kui keegi unustab ta kirjutada.
   `:nth-of-type` (mitte `:nth-child`) on TEADLIK: <legend> on esimene laps ja
   nihutaks `:nth-child` numeratsiooni ühe võrra. */
.rating-input{
  counter-reset:star;
  display:flex;flex-wrap:wrap;gap:8px;
  margin:0;padding:0;border:0;min-width:0;
}
.rating-input>legend{
  float:none;width:100%;flex:1 0 100%;
  padding:0;margin-bottom:10px;
  font-weight:800;font-size:1.05rem;color:var(--ink);
}
.rating-input>:is(label,.rating-star){
  counter-increment:star;
  position:relative;
  flex:1 1 0;min-width:56px;min-height:88px;
  display:grid;place-content:center;justify-items:center;gap:3px;
  border-radius:var(--r-md);
  background:#fff;
  cursor:pointer;
  box-shadow:inset 0 0 0 1.5px var(--line);
  transition:background var(--fast) var(--ease),box-shadow var(--fast) var(--ease);
}
/* KUJU: valimata = õõnes tärn. */
.rating-input>:is(label,.rating-star)::before{
  content:"☆";font-size:1.9rem;line-height:1;color:var(--ink-3);
}
/* TEKST: number iga tärni all. Loendurist, mitte atribuudist — nii ei saa ta
   markupist puududa. */
.rating-input>:is(label,.rating-star)::after{
  content:counter(star);
  font-size:var(--t-micro);font-weight:850;color:var(--ink-3);
  font-variant-numeric:tabular-nums;line-height:1;
}
/* Raadionupp katab terve kaardi, aga on nähtamatu — puuteala on kogu 88px. */
.rating-input input{
  position:absolute;inset:0;width:100%;height:100%;
  margin:0;padding:0;border:0;
  opacity:0;cursor:pointer;
}
.rating-input>:is(label,.rating-star):hover{background:var(--green-mist);box-shadow:inset 0 0 0 1.5px var(--line-2)}
.rating-input>:is(label,.rating-star):has(input:focus-visible){outline:3px solid var(--ring);outline-offset:2px}

/* Valitud olek: KÕIK tärnid kuni valitud numbrini muutuvad täidetuks. */
.rating-input:has(>label:nth-of-type(1) input:checked)>label:nth-of-type(-n+1),
.rating-input:has(>label:nth-of-type(2) input:checked)>label:nth-of-type(-n+2),
.rating-input:has(>label:nth-of-type(3) input:checked)>label:nth-of-type(-n+3),
.rating-input:has(>label:nth-of-type(4) input:checked)>label:nth-of-type(-n+4),
.rating-input:has(>label:nth-of-type(5) input:checked)>label:nth-of-type(-n+5),
.rating-input:has(>.rating-star:nth-of-type(1) input:checked)>.rating-star:nth-of-type(-n+1),
.rating-input:has(>.rating-star:nth-of-type(2) input:checked)>.rating-star:nth-of-type(-n+2),
.rating-input:has(>.rating-star:nth-of-type(3) input:checked)>.rating-star:nth-of-type(-n+3),
.rating-input:has(>.rating-star:nth-of-type(4) input:checked)>.rating-star:nth-of-type(-n+4),
.rating-input:has(>.rating-star:nth-of-type(5) input:checked)>.rating-star:nth-of-type(-n+5){
  background:var(--green-pale);
  box-shadow:inset 0 0 0 2px var(--green);
}
.rating-input:has(>label:nth-of-type(1) input:checked)>label:nth-of-type(-n+1)::before,
.rating-input:has(>label:nth-of-type(2) input:checked)>label:nth-of-type(-n+2)::before,
.rating-input:has(>label:nth-of-type(3) input:checked)>label:nth-of-type(-n+3)::before,
.rating-input:has(>label:nth-of-type(4) input:checked)>label:nth-of-type(-n+4)::before,
.rating-input:has(>label:nth-of-type(5) input:checked)>label:nth-of-type(-n+5)::before,
.rating-input:has(>.rating-star:nth-of-type(1) input:checked)>.rating-star:nth-of-type(-n+1)::before,
.rating-input:has(>.rating-star:nth-of-type(2) input:checked)>.rating-star:nth-of-type(-n+2)::before,
.rating-input:has(>.rating-star:nth-of-type(3) input:checked)>.rating-star:nth-of-type(-n+3)::before,
.rating-input:has(>.rating-star:nth-of-type(4) input:checked)>.rating-star:nth-of-type(-n+4)::before,
.rating-input:has(>.rating-star:nth-of-type(5) input:checked)>.rating-star:nth-of-type(-n+5)::before{
  content:"★";color:var(--green-3);
}
.rating-input:has(>label:nth-of-type(1) input:checked)>label:nth-of-type(-n+1)::after,
.rating-input:has(>label:nth-of-type(2) input:checked)>label:nth-of-type(-n+2)::after,
.rating-input:has(>label:nth-of-type(3) input:checked)>label:nth-of-type(-n+3)::after,
.rating-input:has(>label:nth-of-type(4) input:checked)>label:nth-of-type(-n+4)::after,
.rating-input:has(>label:nth-of-type(5) input:checked)>label:nth-of-type(-n+5)::after,
.rating-input:has(>.rating-star:nth-of-type(1) input:checked)>.rating-star:nth-of-type(-n+1)::after,
.rating-input:has(>.rating-star:nth-of-type(2) input:checked)>.rating-star:nth-of-type(-n+2)::after,
.rating-input:has(>.rating-star:nth-of-type(3) input:checked)>.rating-star:nth-of-type(-n+3)::after,
.rating-input:has(>.rating-star:nth-of-type(4) input:checked)>.rating-star:nth-of-type(-n+4)::after,
.rating-input:has(>.rating-star:nth-of-type(5) input:checked)>.rating-star:nth-of-type(-n+5)::after{
  color:var(--green-3);
}
/* Varulahendus brauserile ilma `:has()`-ita: valitud tärn saab vähemalt ISE
   rohelise raami ja täidetud kuju. Info ei kao, ainult „kuni siia" ei värvu. */
.rating-input>:is(label,.rating-star):focus-within{box-shadow:inset 0 0 0 2px var(--green-2)}

/* ---------------------------------------------------------------------------
   31. NÕUSOLEK JA SOODUSKOOD
   ------------------------------------------------------------------------ */
/* Nõusolek on KAART, mitte 20-pikslise ruudu kõrval seisev tekst. Vaikimisi
   valimata — eeltäidetud linnuke ei ole nõusolek (GDPR art 4 p 11). */
.consent-box{
  display:flex;align-items:flex-start;gap:14px;
  min-height:88px;padding:16px 18px;
  border-radius:var(--r-md);
  background:#fff;
  cursor:pointer;
  box-shadow:inset 0 0 0 1.5px var(--line);
  transition:background var(--fast) var(--ease),box-shadow var(--fast) var(--ease);
}
.consent-box input[type=checkbox]{
  flex:none;width:26px;height:26px;margin:2px 0 0;
  accent-color:var(--green);cursor:pointer;
}
.consent-box>:is(span,div,p){
  display:grid;gap:3px;margin:0;min-width:0;
  color:var(--ink-2);font-size:var(--t-small);line-height:1.5;
}
.consent-box strong{color:var(--ink);font-weight:800;font-size:var(--t-body)}
.consent-box a{font-weight:750}
.consent-box:hover{background:var(--green-mist);box-shadow:inset 0 0 0 1.5px var(--line-2)}
.consent-box:has(input:checked){background:var(--green-pale);box-shadow:inset 0 0 0 2px var(--green)}
.consent-box:focus-within{outline:3px solid var(--ring);outline-offset:2px}
.consent-box+.consent-box{margin-top:10px}

/* Sooduskood. Kaks kuju ühes klassis: NÄITAMINE (kupong koodiga) ja
   SISESTAMINE (väli + nupp). */
.discount-code{
  display:flex;flex-wrap:wrap;align-items:center;gap:12px 16px;
  padding:16px 18px;
  border-radius:var(--r-md);
  background:linear-gradient(180deg,#fff,var(--green-mist));
  box-shadow:inset 0 0 0 1px rgba(11,107,46,.16),var(--shadow-1);
}
.discount-code>p,.discount-code>span:not([class]){
  margin:0;flex:1 1 190px;min-width:0;
  color:var(--ink-2);font-size:var(--t-small);line-height:1.5;
}
.discount-code strong{color:var(--ink);font-weight:800}
/* Kood ISE on katkendlikus raamis — see on ainus koht failis, kus `dashed` on
   õige: katkendjoon TÄHENDAB kupongi, ta ei ole kaunistus. `user-select:all`
   annab ühe puutega terve koodi, ilma JS-i kopeerimisnuputa. */
.discount-code :is(code,samp,.discount-code-value){
  flex:0 0 auto;
  padding:10px 16px;border-radius:var(--r-sm);
  border:1.5px dashed rgba(11,107,46,.45);
  background:#fff;color:var(--green-3);
  font-family:var(--mono);font-size:1.14rem;font-weight:800;
  letter-spacing:.14em;text-transform:uppercase;white-space:nowrap;
  -webkit-user-select:all;user-select:all;
}
.discount-code input{
  flex:1 1 180px;min-width:0;min-height:56px;padding:12px 16px;
  border:1px solid var(--line-2);border-radius:var(--r-sm);
  background:#fff;
  font-family:var(--mono);font-size:1.05rem;font-weight:750;
  letter-spacing:.1em;text-transform:uppercase;
  box-shadow:inset 0 1px 2px rgba(10,52,28,.05);
  transition:border-color var(--fast),box-shadow var(--fast);
}
.discount-code input:hover{border-color:var(--line)}
.discount-code input:focus{border-color:var(--green);box-shadow:inset 0 1px 2px rgba(10,52,28,.04),0 0 0 4px var(--green-pale)}
.discount-code .button{flex:0 0 auto;min-height:56px}
/* Kassas kehtib 88px doktriin ka siin — märgade kätega turuletil. */
.checkout .discount-code input,.checkout .discount-code .button,
.app-shell .discount-code input,.app-shell .discount-code .button{min-height:88px}

/* Rakendatud soodustuse märgis. Roheline taust + valge tekst on ekraanil;
   trükis muutub ta raamiks (vt osa 36) — must ristkülik valge kirjaga on
   laserprinteris loetamatu. */
.discount-badge{
  display:inline-flex;align-items:center;gap:6px;
  padding:4px 11px;border-radius:var(--r-full);
  background:var(--green);color:#fff;
  font-size:var(--t-micro);font-weight:900;letter-spacing:.04em;
  white-space:nowrap;line-height:1.5;
  print-color-adjust:exact;-webkit-print-color-adjust:exact;
}
.discount-badge.is-off{background:var(--paper-2);color:var(--ink-3);box-shadow:inset 0 0 0 1px var(--line-2)}

/* ---------------------------------------------------------------------------
   32. MÜÜJA APP-KEST
   🔴 AUDITI PEAMINE ETTEHEIDE: sisu lõppes 570px peal ja alla jäi tühi taust.
   Parandus on STRUKTUURNE, mitte kosmeetiline: `.app-shell` on 100dvh võre,
   mille KESKMINE rida on `1fr`. Ükskõik kui vähe sisu on, jalus on ekraani
   põhjas ja külgpaneel ulatub sinnani välja.

   Laste leping (kõik VABATAHTLIKUD, järjekord vaba):
     .testmode-strip          → rida 1, üle laiuse
     <header> / .app-head     → rida 2, üle laiuse
     .testmode-banner         → rida 3, üle laiuse
     .app-main                → rida 4  (VENIB — siin on `1fr`)
     .app-side                → rida 5 mobiilis, veerg 2 lauaarvutis
     .app-foot                → viimane rida, üle laiuse
   ------------------------------------------------------------------------ */
.app-shell{
  min-height:100vh;
  min-height:100svh;
  min-height:100dvh;
  display:grid;gap:0;
  grid-template-columns:minmax(0,1fr);
  grid-template-rows:auto auto auto minmax(0,1fr) auto auto;
  background:linear-gradient(180deg,rgba(242,245,240,0) 62%,rgba(232,238,231,.55) 100%);
}
.app-shell>.testmode-strip{grid-row:1;grid-column:1/-1}
.app-shell>:is(header,.app-head){grid-row:2;grid-column:1/-1}
.app-shell>.testmode-banner{grid-row:3;grid-column:1/-1;margin:14px var(--gutter) 0}
.app-main{grid-row:4;grid-column:1}
.app-side{grid-row:5;grid-column:1}
.app-foot{grid-row:6;grid-column:1/-1}

/* Päis kestas: sama rütm mis `.sitebar`, aga ta ei keri ära. */
.app-shell>:is(header,.app-head){
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:12px 20px;
  padding:14px var(--gutter);
  background:rgba(251,251,248,.86);
  backdrop-filter:blur(14px) saturate(1.5);
  -webkit-backdrop-filter:blur(14px) saturate(1.5);
  box-shadow:inset 0 -1px 0 var(--line);
}
.app-shell>:is(header,.app-head) .eyebrow{margin:0}

.app-main{
  display:flex;flex-direction:column;gap:clamp(14px,2vw,20px);
  min-width:0;min-height:0;
  padding:clamp(18px,2.6vw,28px) var(--gutter) clamp(24px,3vw,36px);
}
.app-main>*{min-width:0}
/* Ainus koht, kus tühi ruum täidetakse: peategelane venib, kaunistus mitte. */
.app-main>:is(.empty-first-step,.pos-tape){flex:1 1 auto}
/* Ootekaart EI veni — ta on kapsel. Ta hõljub ülejääva ruumi keskel, sest
   QR-ekraanil ei ole tema all midagi, mille poole ta peaks venima. */
.app-main>.waiting{align-self:center;margin-block:auto}

.app-side{
  display:flex;flex-direction:column;gap:14px;
  min-width:0;
  padding:clamp(18px,2.4vw,26px) clamp(16px,2.2vw,26px) clamp(22px,3vw,30px);
  background:linear-gradient(180deg,var(--card),var(--paper-2));
  box-shadow:inset 1px 0 0 var(--line);
}
/* Päeva kokkuvõte vajub külgpaneeli PÕHJA — ta on taust, mitte tegevus. */
.app-side>.pos-day{margin-top:auto}
.app-side .button{width:100%;min-height:88px}

.app-foot{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:6px 22px;
  padding:10px var(--gutter);
  border-top:1px solid var(--line);
  background:rgba(255,255,255,.72);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  color:var(--ink-3);font-size:var(--t-small);line-height:1.5;
}
.app-foot p{margin:0}
.app-foot strong{color:var(--ink-2);font-weight:800}
.app-foot a{
  display:inline-flex;align-items:center;min-height:44px;
  color:var(--ink-2);text-decoration:none;font-weight:700;
}
.app-foot a:hover{color:var(--green)}
.app-foot nav{display:flex;flex-wrap:wrap;gap:2px 18px}

/* Kaks veergu ainult siis, kui külgpaneel on OLEMAS. Ilma `:has()`-ita
   (või ilma paneelita) jääb kest üheveeruliseks ja täidab ekraani ikka. */
@media (min-width:981px){
  .app-shell:has(.app-side){
    /* 🔴 26vw OLI 13 PIKSLIT LIIGA PALJU TÄPSELT SEAL, KUS ENAMIK MÜÜJAID ON.
       1280 px sülearvutis jäi põhiveergu 659 px, tootetabeli põrand on 680 px
       (osa 38) — ehk „Muuda" ja „Eemalda poest" jäid horisontaalse kerimise
       taha kõige tavalisemal ekraanil. 23vw annab samal laiusel 698 px ja
       tabel mahub. Külgpaneel on kokkuvõte; põhiveerg on TÖÖ. Kui kaks
       võistlevad piksli pärast, võidab töö. */
    grid-template-columns:minmax(0,1fr) clamp(288px,23vw,368px);
    grid-template-rows:auto auto auto minmax(0,1fr) auto;
  }
  .app-shell:has(.app-side) .app-main{grid-row:4;grid-column:1}
  .app-shell:has(.app-side) .app-side{grid-row:4;grid-column:2}
  .app-shell:has(.app-side) .app-foot{grid-row:5}
}

/* --- Kassalint ----------------------------------------------------------- */
/* Lint on müügi ELAV ajalugu, mitte tabel. Ta on valge, tal on read ja ta
   lõpeb katkendjoonega — täpselt nagu rullipaber, mille müüja ära rebib.
   Rea kõrgus 88px on doktriin (märjad käed, kindad), mitte maitse. */
.pos-tape{
  list-style:none;margin:0;padding:0;
  border-radius:var(--r-lg) var(--r-lg) 0 0;
  border-bottom:2px dashed var(--line-2);
  background:#fff;
  /* Read eraldab rea OMA vari, mitte taustale joonistatud jooned. Katsetatud
     mustri kujul `repeating-linear-gradient` 88px sammuga — kahereäline
     tootenimi teeb reast 104px ja jooned nihkuvad rea SISSE. Rippuv joon
     keset rida loeb renderdusveana. */
  box-shadow:var(--hair),var(--shadow-1),var(--edge);
  overflow:hidden;
}
.pos-tape:empty{display:none}
.pos-tape>:is(li,.pos-tape-row){
  display:grid;grid-template-columns:minmax(0,1fr) auto auto;
  align-items:center;column-gap:12px;row-gap:2px;
  min-height:88px;padding:8px 14px;
  box-shadow:inset 0 -1px 0 var(--line);
}
.pos-tape>:is(li,.pos-tape-row):last-child{box-shadow:none}
/* Kaks eraldi selektorit, MITTE `:is(.tape-name,>li>span…)` — `:is()` on
   andestav loend ja kombinaatoriga algav liige visatakse vaikselt minema. */
.pos-tape .tape-name,
.pos-tape>li>span:first-child{
  grid-column:1;min-width:0;
  font-weight:750;letter-spacing:-.01em;overflow-wrap:anywhere;
}
.pos-tape small,.pos-tape .tape-note{
  grid-column:1;grid-row:2;
  color:var(--ink-3);font-size:var(--t-small);font-variant-numeric:tabular-nums;
}
.pos-tape :is(.tape-sum,strong){
  font-weight:900;letter-spacing:-.022em;white-space:nowrap;text-align:right;
  font-variant-numeric:tabular-nums;color:var(--ink);
}
/* Koguse muutmine ja rea kustutamine. 88px KÕRGUST (doktriin), 52px laiust —
   viis rida peab mahtuma telefoni ekraanile, muidu müüja kerib müügi ajal. */

/* --- Päeva ribakokkuvõte ------------------------------------------------- */
/* Eelistatud kuju: `<ul class="pos-day"><li><span>silt</span><strong>arv</strong></li>…`
   Paljas `<dl>` töötab ka — sildid ja arvud lähevad paarikaupa kõrvuti. */
.pos-day{
  display:flex;flex-wrap:wrap;
  list-style:none;margin:0;padding:0;
  border-radius:var(--r-lg);
  background:var(--card);
  box-shadow:var(--hair),var(--shadow-1),var(--edge);
  overflow:hidden;
}
.pos-day>:is(li,div){
  display:grid;align-content:center;gap:3px;
  flex:1 1 106px;min-width:0;
  padding:13px 16px;
  box-shadow:inset 1px 0 0 var(--line);
}
.pos-day>:is(li,div):first-child{box-shadow:none}
/* 🔴 SILT ON VAIKNE, ARV ON VALI — ja siin oli täpselt vastupidi.
   Versaal + .12em tähevahe + 800 kaal tegi 12-pikslisest sildist plakati, mis
   kandis rohkem tinti kui arv tema all. Ja `overflow-wrap:anywhere` (rida ~3096,
   mõeldud makselinkide ja tokenite jaoks) murdis selle plakati SÕNA KESKELT:
   „KESKMIN / E OSTUKOR / V" — kaks sõna kolmel real, oma arvu kohal.
   Nüüd: tavaline kirjapilt, tavaline tähevahe, ja silt EI MURDU üldse.
   Tekst ise on HTML-is juba lausekirjas („Täna laekunud"), seega versaali
   kustutamine annab õige kirjapildi ilma markupita. */
/* 🔴 KAAL JA SUURUS TULEVAD MUUTUJAST, MITTE SELEKTORIST.
   Peamine lahter peab olema teistest suurem. Kui suurus oleks selektoris,
   tuleks iga sisereegel (`silt`, `arv`, `märkus`) peamise lahtri jaoks
   kaskaadis üle kirjutada ja iga uus kuju tekitaks uue spetsiifilisusvõistluse.
   Muutuja PÄRANDUB — üks deklaratsioon lahtri peal muudab kogu tema sisu.
   Varuväärtus on igal ühel olemas, sest `.stat-label` võib elada ka väljaspool
   `.pos-day`-d, ja määramata muutuja tapaks terve deklaratsiooni (vt --mint). */
.pos-day{
  --stat-size:var(--t-stat);
  --stat-ink:var(--ink);
  --label-ink:var(--ink-4);
  --label-size:var(--t-label);
}
.pos-day :is(span,dt,.pos-day-label,.stat-label){
  color:var(--label-ink,var(--ink-4));font-size:var(--label-size,var(--t-label));
  font-weight:650;letter-spacing:0;text-transform:none;line-height:1.32;
  overflow-wrap:normal;word-break:normal;hyphens:none;text-wrap:balance;
}
.pos-day :is(strong,dd,.pos-day-value,.stat-value){
  margin:0;color:var(--stat-ink,var(--ink));
  font-size:var(--stat-size,var(--t-stat));
  font-weight:900;letter-spacing:-.032em;line-height:1.06;
  font-variant-numeric:tabular-nums;
}

/* ---------------------------------------------------------------------------
   33. OOTAMINE JA ESIMENE SAMM
   ------------------------------------------------------------------------ */
/* 🔴 MITTE SPINNER. Spinner tähendab „arvuti töötab" ja ta kiirendab pulssi.
   Siin ei tööta arvuti — siin OOTAB INIMENE teist inimest, kes just avas
   pangarakenduse. Rahulik hingamine (2,6 s tsükkel, kolm punkti järjest)
   ütleb „kõik on korras, ma kuulan". Ja `.elapsed` annab ainsa asja, mis
   ootamise talutavaks teeb: teadmise, kui kaua on juba läinud. */
.waiting{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:10px 16px;
  width:fit-content;max-width:100%;margin-inline:auto;
  padding:18px 26px;
  border-radius:var(--r-lg);
  background:linear-gradient(180deg,#fff,var(--green-mist));
  color:var(--green-3);
  font-size:var(--t-body);font-weight:800;letter-spacing:-.01em;text-align:center;
  box-shadow:inset 0 0 0 1px rgba(11,107,46,.16),var(--shadow-1);
}
.app-main>.waiting{align-self:center;place-content:center}
.waiting-dot{
  flex:none;width:9px;height:9px;border-radius:50%;
  background:var(--green-2);
  box-shadow:0 0 0 3px rgba(18,161,80,.14);
}
/* Staatiline vaikeväärtus. Vähendatud liikumise korral EI kao info: kolm eri
   heledusega punkti loevad ikka „…" ehk pooleliolekuna. */
.waiting-dot{opacity:.9}
.waiting-dot+.waiting-dot{opacity:.55}
.waiting-dot+.waiting-dot+.waiting-dot{opacity:.28}
@media (prefers-reduced-motion:no-preference){
  .waiting-dot{animation:waiting-breath 2600ms var(--ease) infinite}
  .waiting-dot+.waiting-dot{animation-delay:330ms}
  .waiting-dot+.waiting-dot+.waiting-dot{animation-delay:660ms}
}
@keyframes waiting-breath{
  0%,100%{opacity:.26;scale:.82}
  46%    {opacity:1;  scale:1.14}
}

.elapsed{
  display:inline-flex;align-items:center;gap:8px;
  padding:5px 13px;border-radius:var(--r-full);
  background:rgba(255,255,255,.78);
  color:var(--ink-3);
  font-family:var(--mono);font-size:var(--t-small);font-weight:650;
  font-variant-numeric:tabular-nums;letter-spacing:.02em;white-space:nowrap;
  box-shadow:inset 0 0 0 1px var(--line);
}
.elapsed::before{
  content:"";flex:none;width:7px;height:7px;border-radius:50%;
  background:var(--ink-3);opacity:.6;
}

/* --- Müüja ESIMENE ekraan ------------------------------------------------ */
/* Siin teeb disain kõige rohkem tööd. Tühi ekraan tähendab „ma ei tea, mida
   teha" ja see on ainus hetk, kus müüja võib toote sulgeda ja mitte naasta.
   Seepärast: üks suur pind, üks selge lause, ÜKS nupp ja kolm sammu, mis
   ütlevad, kui vähe on veel teha. */
.empty-first-step{
  position:relative;overflow:hidden;
  display:grid;place-content:center;justify-items:center;
  gap:4px;
  min-height:min(72vh,600px);
  padding:clamp(34px,6vw,68px) clamp(22px,5vw,48px);
  border-radius:var(--r-xl);
  text-align:center;
  background:
    radial-gradient(118% 92% at 50% -12%, rgba(18,161,80,.13), transparent 62%),
    linear-gradient(180deg,var(--card) 0%,var(--green-mist) 100%);
  box-shadow:var(--hair),var(--shadow-2),var(--edge);
}
/* Pehme rohevälja hõõg illustratsiooni taga — sügavus, mitte muster. */
.empty-first-step::before{
  content:"";position:absolute;top:-16%;left:50%;
  width:min(560px,92%);aspect-ratio:1;
  translate:-50% 0;border-radius:50%;
  background:radial-gradient(closest-side,rgba(18,161,80,.16),transparent 72%);
  pointer-events:none;
}
.empty-first-step>*{position:relative;z-index:1;max-width:100%}
.empty-first-step svg{
  width:min(238px,64%);height:auto;margin-bottom:10px;
  filter:drop-shadow(0 18px 30px rgba(10,52,28,.14));
}
.empty-first-step svg :is(path,circle,ellipse,line,polyline,polygon,rect){
  fill:none;stroke:var(--green-3);stroke-width:4;stroke-linecap:round;stroke-linejoin:round;
}
.empty-first-step .eyebrow{margin-inline:auto}
.empty-first-step :is(h1,h2){font-size:var(--t-h2);max-width:18ch;margin-bottom:.34em}
.empty-first-step p{color:var(--ink-2);max-width:44ch;margin:0 0 1em}
.empty-first-step .lead{max-width:40ch}
.empty-first-step .actions{justify-content:center;margin:20px 0 0}
.empty-first-step .button{min-height:88px;padding-inline:38px;font-size:1.1rem}
/* „Kolm sammu" — vasakule joondatud loend keskjoondatud plokis. Keskjoondatud
   loend on loetamatu; kast ise jääb keskele. */
.empty-first-step ol{
  counter-reset:fs;
  list-style:none;margin:26px 0 0;padding:0;
  display:grid;gap:10px;justify-items:start;text-align:left;max-width:36ch;
}
.empty-first-step ol>li{
  counter-increment:fs;
  display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:12px;
  color:var(--ink-2);font-size:var(--t-small);line-height:1.45;
}
.empty-first-step ol>li::before{
  content:counter(fs);
  display:grid;place-items:center;width:28px;height:28px;border-radius:50%;
  background:#fff;color:var(--green-3);
  font-size:.85rem;font-weight:900;line-height:1;
  box-shadow:inset 0 0 0 1.5px rgba(11,107,46,.22);
}
.empty-first-step ol>li.is-done{color:var(--green-3)}
.empty-first-step ol>li.is-done::before{content:"✓";background:var(--green);color:#fff;box-shadow:none}
@media (prefers-reduced-motion:no-preference){
  .empty-first-step>*{animation:rise var(--slow) var(--ease) both}
  .empty-first-step>*:nth-child(2){animation-delay:60ms}
  .empty-first-step>*:nth-child(3){animation-delay:120ms}
  .empty-first-step>*:nth-child(4){animation-delay:180ms}
  .empty-first-step>*:nth-child(5){animation-delay:240ms}
}

/* ---------------------------------------------------------------------------
   34. TESTREŽIIM
   🔴 TESTREŽIIM EI OLE VIGA. Ta on pakkuja onboardingu KOHUSTUSLIK etapp
   (otsus #27, docs/SPETSI-PARANDUSED.md): EveryPay `igw-demo`, Maksekeskuse
   testkonto — live-lepingut ei tule enne, kui voog on testvõtmetega läbi
   käidud. Ehk iga müüja elab siin mõnda aega, KUI tema pood on juba avalik.

   Sellest tulenevad kaks vastandlikku nõuet, mille lahendab merevaik:
     1. VÕIMATU MITTE MÄRGATA — muidu müüja usub, et raha laekub, ja annab
        kauba tasuta ära (otsuse #27 halvim juhtum).
     2. EI TOHI NÄIDA VEANA — punane riba ütleks „sinu pood on katki" ja
        müüja lõpetaks õigel hetkel valel põhjusel.
   Punane on `--red`. Siin on `--amber` ja diagonaaltriip: „pooleli", mitte
   „katki". Sama keel, mida kasutavad teetööde märgid.
   ------------------------------------------------------------------------ */
.testmode-strip{
  position:sticky;top:0;z-index:60;
  display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:8px 12px;
  min-height:38px;padding:8px 16px;
  color:#4A2C05;
  font-size:var(--t-small);font-weight:800;line-height:1.4;text-align:center;
  background:
    repeating-linear-gradient(135deg,rgba(180,83,9,.15) 0 10px,rgba(180,83,9,0) 10px 20px),
    var(--amber-pale);
  box-shadow:inset 0 -1px 0 var(--amber-line),0 8px 18px -14px rgba(180,83,9,.7);
  print-color-adjust:exact;-webkit-print-color-adjust:exact;
}
.testmode-strip strong{
  padding:3px 9px;border-radius:var(--r-sm);
  background:var(--amber);color:#fff;
  font-size:var(--t-micro);font-weight:900;letter-spacing:.11em;text-transform:uppercase;
  print-color-adjust:exact;-webkit-print-color-adjust:exact;
}
.testmode-strip a{
  color:#7A3D06;font-weight:850;
  text-underline-offset:3px;text-decoration-thickness:1.5px;
}
.testmode-strip a:hover{color:#4A2C05}

.testmode-banner{
  position:relative;overflow:hidden;
  display:grid;grid-template-columns:auto minmax(0,1fr);
  align-items:start;column-gap:16px;row-gap:8px;
  padding:20px 22px 20px 28px;margin:0 0 22px;
  border-radius:var(--r-lg);
  background:linear-gradient(180deg,#FFFCF5,var(--amber-pale));
  color:#5C3A0C;
  box-shadow:inset 0 0 0 1px var(--amber-line),var(--shadow-1);
}
/* Vasak triibuline serv. Ühtlane riba loeks „viga"; diagonaaltriip loeb
   „töö käib". */
.testmode-banner::before{
  content:"";position:absolute;left:0;top:0;bottom:0;width:7px;
  background:repeating-linear-gradient(135deg,var(--amber) 0 7px,#DD8A2C 7px 14px);
  print-color-adjust:exact;-webkit-print-color-adjust:exact;
}
.testmode-banner>strong{
  grid-column:1;grid-row:1;align-self:center;
  padding:6px 12px;border-radius:var(--r-full);
  background:var(--amber);color:#fff;
  font-size:var(--t-micro);font-weight:900;letter-spacing:.12em;text-transform:uppercase;
  white-space:nowrap;
  box-shadow:0 2px 6px -2px rgba(180,83,9,.5);
  print-color-adjust:exact;-webkit-print-color-adjust:exact;
}
/* Kõik ülejäänud lapsed lähevad TEISE veergu — nii ei satu nupp sildi alla
   ega tekst sildi kõrvale valesse tulpa, ükskõik mis järjekorras nad on. */
.testmode-banner>:not(strong){grid-column:2;margin:0}
.testmode-banner p{font-size:var(--t-small);line-height:1.55}
.testmode-banner p:first-of-type{font-size:var(--t-body);font-weight:800;color:#3E2404}
.testmode-banner ul{margin:0;padding-left:20px;font-size:var(--t-small);line-height:1.55}
.testmode-banner a:not(.button){color:#7A3D06;font-weight:800}
.testmode-banner .button{justify-self:start;min-height:56px;margin-top:2px}
.testmode-banner .button.secondary{
  --btn-bg:#fff;color:#7A3D06;
  box-shadow:inset 0 0 0 1.5px var(--amber-line),var(--shadow-1);
}
.testmode-banner .button.secondary:hover{color:#4A2C05;box-shadow:inset 0 0 0 1.5px var(--amber),var(--shadow-2)}
/* Aeglane hingav rõngas sildi ümber: 4,4 s on liiga aeglane, et olla ärev,
   ja liiga elus, et jääda märkamata. */
@media (prefers-reduced-motion:no-preference){
  .testmode-banner>strong{animation:testmode-glow 4400ms var(--ease) infinite}
}
@keyframes testmode-glow{
  0%,100%{box-shadow:0 2px 6px -2px rgba(180,83,9,.5),0 0 0 0 rgba(180,83,9,.34)}
  55%    {box-shadow:0 2px 6px -2px rgba(180,83,9,.5),0 0 0 8px rgba(180,83,9,0)}
}

/* ---------------------------------------------------------------------------
   35. UUTE OSADE MOBIIL
   375px on turuleti standardseade ja kassa peab olema ÜHE KÄEGA kasutatav:
   kõik, mida müüja vajutab, on ekraani ALUMISES kolmandikus.
   ------------------------------------------------------------------------ */
@media (max-width:980px){
  /* Adminnis on üks kerimisala: leht ise. Sisemine kerimiskast võib peita sisu,
     mis pole ekraanil ega lehe kerimisribaga kättesaadav, ning telefonis
     varastab see lehelt kerimisliigutuse. Seepärast pole `.app-side`-il
     kõrguse lage ega overflow'd — üks leht, üks kerimisriba. */
  .app-side{
    gap:10px;
    padding:12px var(--gutter) max(12px,env(safe-area-inset-bottom));
    background:linear-gradient(180deg,rgba(255,255,255,.94),#fff);
    backdrop-filter:blur(12px) saturate(1.4);
    -webkit-backdrop-filter:blur(12px) saturate(1.4);
    box-shadow:0 -16px 34px -22px rgba(10,52,28,.55),inset 0 1px 0 var(--line);
  }
  /* Kassa ainus kleepuv osa on püsivalt madal summa ja maksenupp.
     ----------------------------------------------------------------------
     🔴 SEE OLI SIIN JUBA KIRJAS, AGA KOOD TEGI MUUD: kleepuv oli KOGU
     `<aside>` koos korviridadega. Korvirida on ~74 px ja neid tuleb juurde,
     nii et „püsivalt madal" paneel kasvas 375×812 ekraanil 450 px-ni ehk 55%
     ekraanist — tootenimekirjast paistis üks rida.

     Piiratud kõrgusega saaks kleepuva paneeli ainult sisemise kerimiskastiga,
     ja seda ei tohi (vt kommentaar ülal). Seega KLEEPUB AINULT SUMMARIBA:
     korviread jäävad `<aside>`-i sisse tavalisse voogu ja kerivad koos lehega,
     riba ise on 64 px ja ei kasva kunagi.

     `backdrop-filter` PEAB siin kaduma, mitte ilu pärast: ta loob
     `position:fixed` järglasele oma sisalduskasti, nii et riba paikneks
     `<aside>`-i, mitte vaateava suhtes. (Sama lõks on osas 41 nav'i juures
     kirjas.) Mittekleepuval paneelil pole matiklaasil niikuinii mõtet — selle
     alt ei keri midagi läbi. */
  .app-side>.pos-day{margin-top:0}
  .app-main{padding-inline:clamp(16px,4vw,24px)}
  .app-shell>.testmode-banner{margin-inline:clamp(16px,4vw,24px)}
}

@media (max-width:900px){
  .product-hero{grid-template-columns:1fr;gap:22px}
  .product-media{aspect-ratio:5/4}
}

@media (max-width:620px){
  .reviews-summary{gap:14px}
  .reviews-summary .reviews-score{justify-items:start;text-align:left}
  .rating-bar{grid-template-columns:3.2em minmax(0,1fr) 2.8em;gap:10px}
  .review{padding:16px 16px}
  .review-head{gap:6px 10px}
  .testmode-banner{
    grid-template-columns:minmax(0,1fr);
    padding:16px 18px 18px 24px;
  }
  .testmode-banner>strong{grid-column:1;justify-self:start}
  .testmode-banner>:not(strong){grid-column:1}
  /* Viis tärni 375px peal: 88px kõrgust ei ohverdata, laius kokku. */
  .rating-input{gap:6px}
  .rating-input>:is(label,.rating-star){min-width:0}
  .rating-input>:is(label,.rating-star)::before{font-size:1.7rem}
  .discount-code{padding:14px 16px}
  .discount-code :is(code,samp,.discount-code-value){flex:1 1 100%;text-align:center}
  .pos-day>:is(li,div){flex:1 1 50%}
  .empty-first-step{min-height:min(64vh,500px);border-radius:var(--r-lg)}
  .empty-first-step svg{width:min(180px,58%)}
  .app-foot{justify-content:center;text-align:center;gap:4px 16px}
  /* Lindirida telefonis: nimi ja summa ühel real, nupud teisel — kaks 52px
     nuppu ja summa ei mahu 375px peale kõrvuti loetavalt. */
  .pos-tape>:is(li,.pos-tape-row){column-gap:8px;padding:8px 10px}
}

/* ---------------------------------------------------------------------------
   36. UUTE OSADE PRINT
   🔴 Kviitung on RAAMATUPIDAMISDOKUMENT. Arvustus, arvustusvorm, nõusoleku
   kastid ja rakenduse kroom ei ole selle dokumendi osa ja nad ei tohi paberit
   süüa.
   ------------------------------------------------------------------------ */
@media print{
  .testmode-strip,
  .testmode-banner,
  .reviews,.reviews-summary,.review,.review-form,.rating-input,.review-disclosure,
  .consent-box,
  .waiting,.elapsed,
  .app-side,.app-foot,.pos-tape,.pos-day,.empty-first-step{display:none}
  .app-shell{display:block;min-height:0;background:none}
  .app-main{display:block;padding:0}

  /* 🔴 ERAND, mis on otsus #27, mitte stiilivalik: „testrežiimis tehtud
     tellimuse kviitung kannab NÄHTAVAT märget". Ekraanil kannab seda merevaik;
     paberil kannab seda must raam, sest laserprinteris muutub merevaik
     halliks ja märge kaoks — täpselt see kviitung, mille pealt keegi hiljem
     küsib, miks raha ei laekunud. */
  .receipt .testmode-banner,.receipt .demo-banner{
    display:block;
    padding:8px 12px;margin:0 0 16px;
    border:2px solid #000;border-radius:0;
    background:none;color:#000;
    box-shadow:none;
    font-size:11pt;font-weight:800;line-height:1.4;
  }
  .receipt .testmode-banner::before,.receipt .demo-banner::before{display:none}
  .receipt .testmode-banner>strong,.receipt .demo-banner-tag{
    display:inline;padding:0;border-radius:0;
    background:none;color:#000;box-shadow:none;animation:none;
    letter-spacing:.08em;
  }
  /* Soodustus on kviitungil SUMMA, mitte kaunistus: ta jääb alles, aga
     roheline täidis muutub raamiks. Valge tekst rohelisel taustal tuleb
     mustvalgest printerist välja loetamatu. */
  .discount-badge{
    background:none;color:#000;
    box-shadow:inset 0 0 0 1px #000;
    font-weight:800;
  }
  .discount-code{background:none;box-shadow:inset 0 0 0 1px #000;padding:8px 12px}
  .discount-code :is(code,samp,.discount-code-value){border-color:#000;color:#000;background:none}
  .delivery-summary,.returns-summary{background:none;box-shadow:none;padding:0}
}

/* ---------------------------------------------------------------------------
   37. UUTE OSADE VÄHENDATUD LIIKUMINE
   Osa 28 üldplokk katab kestuse. See plokk katab NIMED — kordumatu
   animatsioon `.01ms` kestusega ikka JOOKSEB ja jätab elemendi viimasesse
   kaadrisse. Iga siin lisatud animatsioon on nimeliselt kirjas ja igal ühel
   on määratud, mis temast alles jääb.
   ------------------------------------------------------------------------ */
@media (prefers-reduced-motion:reduce){
  /* waiting-breath → kolm eri heledusega punkti, staatiliselt. Info („ootab")
     jääb alles, pulss kaob. */
  .waiting-dot{animation:none;scale:none}
  .waiting-dot{opacity:.9}
  .waiting-dot+.waiting-dot{opacity:.55}
  .waiting-dot+.waiting-dot+.waiting-dot{opacity:.28}
  /* testmode-glow → silt jääb täisvärvi ja täisvarjuga. Merevaik + versaal +
     triibuline serv kannavad märgatavuse ka täiesti liikumatult. */
  .testmode-banner>strong{animation:none;box-shadow:0 2px 6px -2px rgba(180,83,9,.5)}
  /* rise (.empty-first-step) → sisu on kohe kohal ja täies läbipaistmatuses. */
  .empty-first-step>*{animation:none;opacity:1;translate:none}
  /* Ülejäänud uued üleminekud on värvi- ja varjumuutused, mille osa 28
     üldplokk nullib kestuselt — nad ei peida ega nihuta midagi. */
}

/* ---------------------------------------------------------------------------
   38. MÜÜJA ARVUSTUSTE LEHT  (`/haldus/arvustused`)
   Leping failiga `src/routes/haldus-arvustused.ts`.

   🔴 SEE OSA EI TOHI ANDA ÜHTEGI KUJU, MIDA MÜÜJAL EI OLE. Kustutus- ja
   peitmisnuppu ei ole olemas, seega ei ole siin ka `.review-delete`-i ega
   ühtegi punast destruktiivset varianti, mida keegi hiljem "juba olemas"
   argumendiga markupisse tõmbaks. Osa 30 (`.review`, `.review-head`,
   `.review-body`, `.review-reply`, `.review-flag`) kehtib siin muutmata
   kujul — sama arvustus peab müüjale ja ostjale ühtemoodi välja nägema.

   Puuteala: iga nupp ja tekstiväli on >= 88px. Müüja teeb seda tööd
   telefonis, sageli ühe käega ja letile toetudes.
   ------------------------------------------------------------------------ */
.seller-reviews{margin:24px 0 34px}

/* Toote nimi arvustuse päises. Ta on LINK, sest müüja esimene küsimus on
   "kus see täpselt paistab" ja vastus peab olema ühe puute kaugusel. */
.review-product{
  display:inline-flex;align-items:center;
  min-height:44px;padding:0 2px;
  color:var(--ink-2);font-size:var(--t-small);font-weight:750;
  text-decoration:none;
  border-bottom:1.5px solid var(--line-2);
}
.review-product:hover{color:var(--green-3);border-bottom-color:var(--green-2)}

/* Kinnitusteade pärast POST → 303 → GET. `role="status"` ütleb ta ette ka
   ekraanilugejale; värv üksi ei ole teade. */
.review-flash{
  margin:0 0 20px;padding:14px 18px;
  border-radius:var(--r-md);
  background:var(--green-mist);color:var(--ink-2);
  font-size:var(--t-small);line-height:1.55;font-weight:600;
  box-shadow:inset 3px 0 0 var(--green-2),inset 0 0 0 1px rgba(11,107,46,.10);
}

/* Teod on arvustuse SEES ja tema all — nad kuuluvad selle rea juurde, mitte
   lehe põhja. Ülemine joon eraldab ostja teksti müüja omast. */
.review-actions{
  margin:16px 0 0;padding:16px 0 0;
  border-top:1px solid var(--line-2);
  display:grid;gap:14px;
}
.review-action{display:grid;gap:8px}
.review-action .field-hint{margin-top:0}
.review-action textarea.field-input{
  min-height:112px;padding:16px 18px;
  font-family:var(--sans);font-size:1.02rem;line-height:1.55;
  resize:vertical;
}
.review-action .button{width:100%;min-height:88px}

/* Teatamine on kokku pandud ja kitsam kui vastamine. See EI OLE kaunistus:
   esimene tegu, mida müüja halva arvustuse peale näeb, peab olema "vasta",
   mitte "kaeba". Sama põhjus, mille pärast siin ei ole punast nuppu. */
.review-report{margin:0}
.review-report>summary{
  display:flex;align-items:center;gap:10px;
  min-height:44px;
  color:var(--ink-3);font-size:var(--t-small);font-weight:750;
  cursor:pointer;list-style:none;
}
.review-report>summary::-webkit-details-marker{display:none}
.review-report>summary::before{
  content:"⚑";flex:none;font-size:.95rem;line-height:1;
}
.review-report>summary:hover{color:var(--ink-2)}
.review-report[open]>summary{color:var(--ink-2);margin-bottom:10px}
.review-report .micro{margin:0 0 4px;line-height:1.55}

/* Piiride plokk. Ta on TEKST, mitte hoiatuskast: müüja peab ta läbi lugema,
   mitte üle vaatama. Kollane hoiatusriba õpetaks ta seda ignoreerima. */
.review-limits{
  margin:34px 0 0;padding:clamp(20px,3vw,26px);
  border-radius:var(--r-lg);
  background:var(--paper-2);
  color:var(--ink-2);line-height:1.6;
  box-shadow:inset 0 0 0 1px var(--line);
}
.review-limits h2{margin:0 0 12px;font-size:1.15rem}
.review-limits ul{margin:0 0 12px;padding-left:22px}
.review-limits li{margin:0 0 8px;max-width:72ch}
.review-limits li:last-child{margin-bottom:0}
.review-limits p{margin:0 0 10px;max-width:72ch}
.review-limits p:last-child{margin-bottom:0}
.review-limits strong{color:var(--ink)}

@media (max-width:640px){
  .review-actions{gap:12px}
  .review-product{width:100%}
}

/* Müüja tööleht ei ole dokument — paberile ta ei kuulu. */
@media print{
  .review-actions,.review-report,.review-limits,.review-flash{display:none}
}

/* ---------------------------------------------------------------------------
   38. SISSELOGIMINE JA TÖÖLAUA PÄISE TEGEVUSED
   Sisselogimine on ainus ekraan, mille müüja näeb ENNE kui ta midagi omab.
   Ta ei tohi olla vorm tühjal lehel: `.app-shell` annab talle 100dvh kesta,
   jaluse ekraani põhjas ja kaardi täpselt keskele. Sama kest, mis töölaual —
   müüja ei õpi kahte paigutust, ta õpib ühe.
   ------------------------------------------------------------------------ */
.auth-card{
  width:min(460px,100%);
  margin-inline:auto;
  padding:clamp(26px,4vw,38px);
  border-radius:var(--r-xl);
  background:linear-gradient(180deg,var(--card),var(--green-mist));
  box-shadow:var(--hair),var(--shadow-2),var(--edge);
}
/* Kaart EI VENI — ta on kapsel, nagu `.waiting`. Ta hõljub ülejääva ruumi
   keskel, sest tema all ei ole midagi, mille poole ta peaks venima. */
.app-main>.auth-card{align-self:center;margin-block:auto}
.auth-card h1{font-size:var(--t-h2);margin-bottom:.32em}
.auth-card>.lead{margin:0 0 22px}
.auth-card .error{margin-bottom:20px}
.auth-card .field+.field{margin-top:16px}
/* 88px doktriin: müüja logib sisse turuletil, märgade või kinnastatud kätega.
   `.field-input` on juba 88px; nupp peab olema sama. */
.auth-card .button{width:100%;min-height:88px;margin-top:22px;font-size:1.08rem}
.auth-card .micro{margin:18px 0 0}

/* --- Paroolita sisselogimine -----------------------------------------------
   E-posti link on ESIMENE tee ja parool on teine, sest 16.08.2026 alates ei
   ole uuel müüjal parooli üldse. Virn hoiab mõlemad ühe kapsli laiuses; ilma
   temata neelaks `.auth-card` `margin-block:auto` ülejääva ruumi ja lükkaks
   paroolituba ekraani põhja. */
.auth-stack{display:grid;gap:14px;width:min(460px,100%);margin-inline:auto}
.app-main>.auth-stack{align-self:center;margin-block:auto}
.auth-stack>.auth-card{width:100%}

/* `<details>` on natiivne ja töötab ILMA JS-ita (doktriin §1). Ta on
   tahtlikult vaikne: paroolitee on pärand, mitte pakkumine. */
.auth-alt{border-radius:var(--r-lg);background:var(--paper-2);box-shadow:var(--hair)}
.auth-alt>summary{
  display:flex;align-items:center;gap:8px;
  min-height:56px;padding:0 18px;
  font-size:var(--t-small);font-weight:700;color:var(--ink-2);
  cursor:pointer;list-style:none;
}
.auth-alt>summary::-webkit-details-marker{display:none}
/* Kolmnurk on ISE joonistatud, sest natiivne marker ei ole värvitav ega
   pööratav ühtmoodi üle brauserite. */
.auth-alt>summary::before{
  content:"";width:0;height:0;flex:0 0 auto;
  border-left:6px solid currentColor;
  border-block:5px solid transparent;
  transition:transform var(--fast) var(--ease);
}
.auth-alt[open]>summary::before{transform:rotate(90deg)}
.auth-alt>summary:focus-visible{outline:3px solid var(--green);outline-offset:-3px;border-radius:var(--r-lg)}
.auth-alt .auth-card{background:none;box-shadow:none;padding:0 18px 18px}
.auth-alt .auth-card .button{min-height:64px}

/* --- Kuuekohaline kood -----------------------------------------------------
   Kood tuleb kirjast ja käib käsitsi sisse: turul avab link sageli VALE
   brauseri (`UX-SPETS.md` §3.4). Suur samm ja hõre kiri teevad numbrite
   kontrollimise võimalikuks ilma kirja uuesti avamata. `text-security` ei ole
   siin midagi — kood ei ole saladus, ta on ühekordne. */
.kood-input{
  font-size:1.6rem;font-weight:800;
  letter-spacing:.34em;text-indent:.34em;
  text-align:center;
  font-variant-numeric:tabular-nums;
}

/* Päise tegevused: navigatsioonilingid ja väljalogimisvorm ühel real.
   Väljalogimine on `<form method=post>`, mitte link — CSRF-mudel on
   `SameSite=Lax`, ehk ristsaidi GET kannab küpsist kaasa ja ükski GET ei tohi
   olekut muuta. Vorm vajab mähist, et ta ei tekitaks päises omaette rida. */
.app-bar-actions{display:flex;flex-wrap:wrap;align-items:center;gap:10px}

/* Müüja põhitee on telefonis pöidla all ja töölaual püsivalt vasakul. Nav on
   igas halduse päises sama, et ükski ekraan ei muutuks tupikteeks. */
.admin-nav{
  /* Hoia nav otse `.app-shell`-i all: transform/filter/backdrop-filter,
     perspective, will-change või contain:paint/layout esivanem teeks sellest
     fixed-elemendi tugiraami ja tõstaks menüü telefonis keset lehte. */
  position:fixed;left:0;right:0;bottom:0;z-index:80;
  display:grid;grid-template-columns:repeat(5,minmax(0,1fr));
  padding:0 0 env(safe-area-inset-bottom);
  background:rgba(251,251,248,.96);box-shadow:0 -1px 0 var(--line),0 -12px 28px -24px #0A341C;
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
}
.admin-nav a{
  position:relative;
  display:grid;place-content:center;justify-items:center;gap:5px;
  min-width:0;min-height:88px;padding:7px 2px;
  color:var(--ink);text-decoration:none;font-size:var(--t-micro);font-weight:850;
  transition:color var(--fast) var(--ease);
}
/* 🔴 PIND ON PSEUDOELEMENT, MITTE LAHTRI TAUST — JA SEE EI OLE VORMISTUS.
   Puutesihtmärk peab jääma 88 px (doktriin: märjad käed turuletil). Kui pinna
   teeks `margin`-iga väiksemaks, kahaneks KOOS TEMAGA sihtmärk. Pseudoelement
   joonistab ümara pinna 88 px lahtri SISSE, ilma et lahter ise liiguks:
   nähtav on 68 px, puutuda saab 88 px. */
/* 🔴 PIND ON LAHTRI LAIUNE JA SEE ON ARITMEETIKA, MITTE MAITSE.
   Mõõdetud 375 px: viis võrdset veergu = 75 px, „Tellimused" on 12 px juures
   66 px. Pillile, mis silti HAARAB, jääks külgedele 4 px — ja 10 px polstriga
   pill oleks 86 px ehk laiem kui lahter ise. Horisontaalset ruumi EI OLE ja
   ükski font-size ei tekita seda juurde ilma silti loetamatuks tegemata.
   Seetõttu on pind lahtri laiune (segmentnupu kuju) ja kitsikust kompenseerib
   VERTIKAALNE heldus: 19 px tekst 70 px pinna sees hingab, kuigi külgedel on
   kaks pikslit. Sama trikk, mis trükikojas — ridade vahe päästab kitsa veeru. */
.admin-nav a::after{
  content:"";position:absolute;inset:9px 2px;z-index:0;
  border-radius:16px;
  transition:background-color var(--fast) var(--ease),transform var(--fast) var(--ease);
}
.admin-nav a>*{position:relative;z-index:1}
.admin-nav a:not([aria-current="page"]):active::after{background:var(--green-pale);transform:scale(.94)}
/* 🔴 TELEFONI RIBAL EI OLE IKOONE. Martti 15.08.2026: „alumises menüüs ei ole
   isegi need iconid vajalikud, kuna hetkel need ei näe proffesionaalsed välja."
   Ikoon 88 px ribal ei kandnud tähendust, mida silt juba ei kandnud — ta oli
   teine asi, mida vaadata, seal kus valik on niikuinii viie sõna vahel. Silt
   saab nüüd kogu ruumi ja rida loeb nagu vahekaardiriba, mitte nagu
   emotikonide rida. SVG jääb DOM-i, sest lauaarvuti kokkuvolditud riba ON
   ainult ikoonid. */
.admin-nav .nav-ico,.admin-nav .nav-brand,.admin-nav .nav-collapse{display:none}
/* 🔴 SILT ON NÜÜD AINUS SISU — JA TA PEAB OLEMA LOETAV, MITTE MAHTUV.
   Martti 15.08.2026: „need menüü tekstid on liiga väikesed, neid ei ole näha
   korralikult." 12 px oli ikooni ALLKIRI; ilma ikoonita on ta pealkiri.

   Suurust piirab AINULT telefoni veerulaius: 375 px / 5 = 75 px, miinus polster
   71 px, ja „Tellimused" on 12 px juures 67 px. Ehk telefonis EI OLE ruumi
   kasvada — aga tahvlis (768 px) on veerg 153 px ja seal seisis sama 12 px
   tekst nagu iPhone SE-l. `clamp` seob suuruse laiusega, mitte seadmega:
     375 px → 12 px (geomeetria lagi)   768 px → 15,4 px   980 px → 17 px
   Värv läheb `--ink-2` → `--ink`: silt on nüüd riba peategelane, mitte
   kaassõna. Aktiivne punkt jääb roheliseks, seega hierarhia ei kao. */
.admin-nav .nav-label{font-size:clamp(.75rem,2vw,1.0625rem);letter-spacing:-.02em}
/* ═══ AKTIIVNE PUNKT — MIS OLI VALESTI JA MIS ON NÜÜD ══════════════════════
   Vana kuju oli `background:var(--green-pale); box-shadow:inset 0 3px 0` —
   ehk KANDILINE kahvaturoheline täisplokk, mis ulatus riba ülaservast
   alumise servani, ja tema kohal 3 px tume triip. Kolm mõõdetavat viga:

     1. Ta oli ainus TERAVANURGELINE pind lehel, kus iga kaart, nupp ja
        märgis on ümar. Silm loeb võõrast nurka veaks, mitte rõhutuseks.
     2. 3 px triip ülaservas on brauseri VAHEKAARDI keel, mitte rakenduse
        oma — ta ütleb „dokument", seal kus me ütleme „tööriist".
     3. Ta täitis kogu 88 px lahtri, seega aktiivne punkt oli kõige SUUREM
        asi ribal. Rõhutus peab olema kõige SELGEM, mitte kõige suurem.

   Uus kuju on ümar pind, mis HÕLJUB ribas: 18 px raadius, roheline gradient
   (sama perekond, mis maksenupul — bränd on üks värv, mitte kaks), valge
   tekst, pehme roheline vari all. Ta ilmub vetruva animatsiooniga, sest
   navigeerimine on lehe VAHETUS ja liikumine ütleb „sa maandusid siia" ilma
   ühegi sõnata. `prefers-reduced-motion` võtab liikumise ära, pinna mitte. */
.admin-nav a[aria-current="page"]{color:#fff;background:none;box-shadow:none;cursor:default;pointer-events:none}
.admin-nav a[aria-current="page"]::after{
  background:linear-gradient(180deg,var(--green-2) 0%,var(--green) 58%,var(--green-3) 100%);
  box-shadow:
    0 8px 18px -10px rgba(6,58,26,.85),
    inset 0 1px 0 rgba(255,255,255,.28);
}
@keyframes nav-pill-in{
  from{transform:scale(.82);opacity:0}
  60%{transform:scale(1.04)}
  to{transform:scale(1);opacity:1}
}
@media (prefers-reduced-motion:no-preference){
  .admin-nav a[aria-current="page"]::after{animation:nav-pill-in var(--base) var(--ease) both}
}
/* Telefonis on viis igapäevast tööd ühel 88px real. Harvemad teed elavad
   „Rohkem” all; nii ei söö nav veerandit ekraanist. Reserv peab olema jaluse
   JÄREL dokumendivoos: shell'i padding võib CSS Gridis minna veniva 1fr rea
   arvestusse ega tõesta, et jaluse serv jõuab fixed-menüü kohale. Grid-item'i
   margin ei kollabeeru ja teeb navikõrguse päriselt keritavaks lõpuruumiks. */
.admin-nav a:is([data-nav="arvustused"],[data-nav="makse"]){display:none}
/* „Rohkem" teise taseme lehel EI OLE aktiivne leht — ta on aktiivse leht VANEM.
   Seetõttu saab ta sama kuju VAIKSEMAS registris: kahvatu pind, roheline tekst,
   null varju. Sama tugev rõhutus kui pärisel muudaks ribal kaks punkti
   võrdseks ja müüja ei teaks, kummal ta seisab. */
.admin-nav a[data-parent-current="true"]{color:var(--green-3);background:none;box-shadow:none}
.admin-nav a[data-parent-current="true"]::after{background:var(--green-pale)}
.app-shell:has(.admin-nav)>.app-foot{margin-bottom:calc(88px + env(safe-area-inset-bottom))}
.dashboard-till{display:grid;gap:8px;margin-bottom:6px}
.dashboard-till .button{min-height:88px;font-size:1.18rem}
.dashboard-till p{margin:0}
.dashboard-onboarding{align-content:start;padding:clamp(18px,2.5vw,26px);border-radius:var(--r-lg);background:var(--card);box-shadow:var(--hair),var(--shadow-1)}
.dashboard-onboarding h2{margin:0;font-size:var(--t-h3)}
.dashboard-onboarding .actions{margin:8px 0 0}
.app-side .dashboard-onboarding .button{width:auto;padding-inline:28px}

/* Töölaud algab telefonis päeva arvudega, mitte tellimuslindiga. Kokkuvõte
   kasutab lehe enda tausta ja eraldusjooni: see on infohierarhia, mitte eraldi
   hõljuv kaart. Teiste ekraanide `.app-side` paigutus ei muutu. */
.dashboard-summary{background:transparent;box-shadow:none}
/* 🔴 JOONED VÄLJA. Kolm veergu × kaks rida juuksekarva-jooni luges
   ARVUTUSTABELINA: iga lahter sama raamiga, sama kaaluga, ükski arv teisest
   tähtsam. Eraldust kannab nüüd VAHE ja pinnavalgus — peamine arv on oma pind,
   ülejäänud on tema ümber vaikne kontekst ilma ühegi jooneta.
   `overflow:visible` on siin nõue, mitte maitse: osa 40 scroll-ilmumine ei
   tohi joosta ühegi kerimiskonteineri sees (vt sealset punast märkust). */
.dashboard-summary>.pos-day{
  margin-top:0;gap:8px;
  border-radius:0;background:transparent;box-shadow:none;overflow:visible;
}
/* 🔴 KONTEKSTILAHTRI SELEKTOR ON PEAMISE TÄPNE TÄIEND, mitte „kõik peale
   klassiga lahtri" — ja see vahe on mõõdetud viga, mitte teooria.
   Peamine lahter tekib KAHEL viisil (osa 40.3): kas `.stat-lead` klassiga, VÕI
   `.dashboard-summary` esimese lahtrina ilma klassita. `:not(.stat-lead)` üksi
   jättis TEISE juhu kontekstilahtrite hulka: peamine arv sai õige pinna (kõrgem
   spetsiifilisus), aga päris ka kontekstilahtri paigutuse, ja päevakäive kukkus
   lauaarvutis ühele reale sildiga kõrvu. Kaks selektorit katavad täpselt selle,
   mida peamine EI KATA:
     1. iga lahter, mis ei ole esimene   → kehtib mõlemal juhul
     2. esimene lahter SIIS, kui `.stat-lead` on mujal → peamine on juba olemas */
.dashboard-summary>.pos-day>:is(li,div):not(.stat-lead):not(:first-child),
.dashboard-summary>.pos-day:has(>.stat-lead)>:is(li,div):not(.stat-lead){
  flex:1 1 130px;
  padding:12px 15px;
  border-radius:var(--r-md);
  background:linear-gradient(180deg,rgba(255,255,255,.88),rgba(255,255,255,.52));
  box-shadow:var(--hair);
}
@media (max-width:980px){
  .app-shell:has(.dashboard-summary){grid-template-rows:auto auto auto auto minmax(0,1fr) auto}
  .app-shell:has(.dashboard-summary)>.dashboard-summary{grid-row:3}
  .app-shell:has(.dashboard-summary)>.testmode-banner{grid-row:4}
  .app-shell:has(.dashboard-summary)>.app-main{grid-row:5}
}

/* ═══════════════════════════════════════════════════════════════════════════
   41. LAUAARVUTI KÜLGRIBA — JA TEMA NURGATAHA VOLTIMINE
   ═══════════════════════════════════════════════════════════════════════════
   Martti 15.08.2026: „see kõrval menüü tuleb ülesse pimpida ehk disain tuleb
   teha palju ilusamaks ja paremaks… ja seda peab saama ära ka peita nurga
   taha, et kassale rohkem ruumi teha."

   MIS VANAS OLI VALESTI, MÕÕDETULT:
     1. Read olid `minmax(88px,auto)`. Seitse rida × 88 px = 616 px menüüd,
        millest 340 px oli tühi vahe — telefoni riba kõrgus lauaarvuti külge
        keeratud. 88 px on UX-SPETS §5.1 PRIMAARNE klass (maksenupp); menüü on
        „harv" klass ja tema põrand on 44 px. 56 px on selle kohal.
     2. Ikoonid olid Unicode'i glüüfid — vt `src/lib/admin-shell.ts` punane
        märkus. `≡` oli sõna otseses mõttes burgerinupp „Tellimuste" ees.
     3. Riba ei öelnud MITTE KUSAGIL, mis toode see on. Kassaekraanil ei ole
        päist, seega 220 px tumedat pinda algas eimillestki.
     4. Aktiivne rida oli `rgba(255,255,255,.16)` — sama kaal, mis hover.

   MIKS KOKKUVOLDITUD RIBA JÄÄB 76 px PEALE, MITTE NULLI: müüja peab teadma,
   kus ta on, ka siis kui ta on ruumi ära andnud, ja tagasitee peab olema üks
   puude. Täiesti kadunud menüü nõuaks hõljuvat nuppu, mis ei kuulu kuhugi.

   MÕÕDETUD VÕIT (1440×900, tootmise demokassa): kataloog 744 → 888 px, ehk
   +144. See EI OLE uus veerg — `auto-fill` hoiab kolme veergu ja teeb nad
   laiemaks, sest tehingute rööbas kasvab kaasa. Uus veerg tuleb alles siis,
   kui vaba laius ületab `clamp(132px,22vw,236px)` + vahe. Plaadi laius on
   turuletil omaette väärtus (pikk tootenimi mahub ühele reale), aga kes ootab
   neljandat veergu, ei tohi seda siit lugeda.
   ------------------------------------------------------------------------ */
@media (min-width:981px){
  :root{--nav-w:220px}
  html.nav-peidus{--nav-w:76px}

  .app-shell:has(.admin-nav){padding-left:var(--nav-w);min-height:100dvh}
  .app-shell:has(.admin-nav)>.app-foot{margin-bottom:0}
  html.nav-animeerib .app-shell:has(.admin-nav){transition:padding-left var(--base) var(--ease)}

  /* 🔴 VÕRE → FLEX. Voltimislüliti peab seisma riba PÕHJAS ja `margin-top:auto`
     töötab flex-konteineris; `align-content:start` võres pakib read kokku ja
     jätab nupu seitsmenda lingi külge kinni. */
  .admin-nav{
    top:0;right:auto;width:var(--nav-w);padding:16px 12px 14px;
    display:flex;flex-direction:column;gap:3px;
    background:
      radial-gradient(120% 44% at 50% 0,rgba(111,231,163,.10),transparent 62%),
      linear-gradient(180deg,#17291D 0%,#0D1C12 44%,#07120C 100%);
    box-shadow:inset -1px 0 rgba(255,255,255,.07),14px 0 44px -38px #030C06;
  }
  html.nav-animeerib .admin-nav{transition:width var(--base) var(--ease)}
  /* 🔴 ÜLEMINEK ON KAUNISTUS, MITTE VÄÄRTUSE KIRJUTAJA — ja siin on selle
     reegli TÕEND. Mõõdetud tootmises: peidetud vahekaardis seisis `width`
     ülemineku `currentTime` 0 juures `playState:"running"`, ehk riba jäi
     220 px peale, kuigi `--nav-w` oli juba 76 px. Brauser peatab ülemineku
     nähtamatus vahekaardis (sama pere, mis rAF). Õige väärtuse kirjutab
     `width:var(--nav-w)` deklaratsioon ise ja ta jõuab kohale niipea, kui
     vahekaart on jälle nähtav. Kes liikumist ei taha, saab kohe õige laiuse. */
  @media (prefers-reduced-motion:reduce){
    html.nav-animeerib .admin-nav,
    html.nav-animeerib .pos-shell.has-nav,
    html.nav-animeerib .app-shell:has(.admin-nav){transition:none}
  }

  /* --- riba pea: toode ütleb oma nime ------------------------------------ */
  /* 🔴 SELEKTOR ON `.admin-nav .nav-brand`, MITTE `.nav-brand`. Telefoni reegel
     peidab ta kujul `.admin-nav .nav-brand` (0,2,0) ja meediapäring EI LISA
     spetsiifilisust — paljas `.nav-brand` (0,1,0) kaotaks talle ja riba pea
     jääks lauaarvutis nähtamatuks. Mõõdetud: esimene versioon oligi selline. */
  .admin-nav .nav-brand{
    display:flex;align-items:center;gap:10px;
    margin:0 0 14px;padding:6px 6px 0;
    color:#fff;font-weight:800;letter-spacing:-.02em;
  }
  .nav-brand-mark{
    display:grid;place-items:center;flex:0 0 auto;
    width:30px;height:30px;border-radius:9px;
    background:linear-gradient(158deg,var(--mint),var(--green-2));
    color:#04220F;font-size:1.05rem;font-weight:900;line-height:1;
  }
  .nav-brand-word{font-size:1.02rem;white-space:nowrap}
  .nav-brand-word span{color:var(--mint);font-weight:700}

  /* --- lingid ------------------------------------------------------------- */
  .admin-nav a:is([data-nav="arvustused"],[data-nav="makse"]){display:grid}
  .admin-nav a[data-nav="rohkem"]{display:none}
  /* Telefoni hõljuv roheline pind EI TULE külgribale kaasa. Tume riiul on juba
     oma pind ja tema aktiivne rida kannab mündirohelist märki (`::before`
     allpool) — kaks eri rõhutust ühel real võitleksid teineteisega. */
  .admin-nav a::after{display:none}
  .admin-nav .nav-ico{display:block;width:20px;height:20px;flex:0 0 auto}
  .admin-nav a{
    position:relative;
    grid-template-columns:20px 1fr auto;gap:12px;
    justify-items:start;align-items:center;place-content:center start;
    min-height:56px;padding:0 12px;
    border-radius:11px;
    color:rgba(255,255,255,.78);text-align:left;
    font-size:1rem;font-weight:700;letter-spacing:-.012em;
    transition:background-color var(--fast) var(--ease),color var(--fast) var(--ease);
  }
  .admin-nav .nav-label{font-size:inherit;letter-spacing:inherit}
  .admin-nav a:hover{background:rgba(255,255,255,.07);color:#fff}
  .admin-nav a:not([aria-current="page"]):active{background:rgba(255,255,255,.14);transform:none}

  /* Aktiivne rida ei ole „veidi heledam hover" — tal on OMA pind, oma värv ja
     mündiroheline vertikaalne märk. `::before`, mitte `inset box-shadow`:
     ümardatud nurgaga kast lõikaks 4 px inset-riba ülevalt ja alt ära. */
  .admin-nav a[aria-current="page"]{
    background:linear-gradient(90deg,rgba(111,231,163,.20),rgba(111,231,163,.07));
    color:#fff;box-shadow:none;
  }
  .admin-nav a[aria-current="page"]::before{
    content:"";position:absolute;left:0;top:50%;transform:translateY(-50%);
    width:3px;height:22px;border-radius:0 3px 3px 0;background:var(--mint);
  }
  .admin-nav a[aria-current="page"] .nav-ico{color:var(--mint)}
  .admin-nav a[data-parent-current="true"]{background:rgba(255,255,255,.10);color:#fff;box-shadow:none}

  /* Harvemad sihid on OMA rühm. Juuksekarva joon ütleb „siit algab teine
     sagedus" ilma pealkirjata, mida keegi lugema ei hakka. */
  .admin-nav a[data-nav="arvustused"]{
    margin-top:9px;padding-top:9px;
    border-top:1px solid rgba(255,255,255,.09);border-radius:11px;
  }

  /* --- voltimislüliti ----------------------------------------------------- */
  /* 🔴 `[hidden]` PEAB VÕITMA. Nupp sünnib `hidden`-ina (ilma JS-ita ta ei tee
     midagi) ja `display:grid` siin kustutaks selle lipu ära — täpselt sama
     lõks, mis tappis kassa otsingufiltri. */
  .admin-nav .nav-collapse[hidden]{display:none}
  .admin-nav .nav-collapse{
    display:grid;grid-template-columns:20px 1fr;gap:12px;align-items:center;
    margin-top:auto;min-height:48px;padding:0 12px;
    border:0;border-radius:11px;background:transparent;
    color:rgba(255,255,255,.55);font:inherit;font-size:var(--t-small);font-weight:700;
    text-align:left;cursor:pointer;
    transition:background-color var(--fast) var(--ease),color var(--fast) var(--ease);
  }
  .admin-nav .nav-collapse:hover{background:rgba(255,255,255,.07);color:#fff}
  .admin-nav .nav-collapse .nav-ico{transition:transform var(--base) var(--ease)}
  .admin-nav .nav-collapse-label{white-space:nowrap;overflow:hidden}

  /* --- kokkuvolditud ------------------------------------------------------ */
  /* Silt ei tohi minna `display:none` alla: see kustutaks lingi ligipääsetava
     NIME ja ekraanilugeja loeks seitset nimetut linki. `.sr-only` tehnika hoiab
     nime alles ja võtab ainult pikslid. */
  html.nav-peidus .admin-nav .nav-label,
  html.nav-peidus .admin-nav .nav-brand-word,
  html.nav-peidus .admin-nav .nav-collapse-label{
    position:absolute;width:1px;height:1px;
    margin:-1px;padding:0;overflow:hidden;
    clip-path:inset(50%);white-space:nowrap;border:0;
  }
  html.nav-peidus .admin-nav a,
  html.nav-peidus .admin-nav .nav-collapse{
    grid-template-columns:20px;justify-content:center;justify-items:center;padding-inline:0;
  }
  html.nav-peidus .nav-brand{justify-content:center;padding-inline:0}
  html.nav-peidus .admin-nav .nav-collapse .nav-ico{transform:rotate(180deg)}
  /* Lukk on kokkuvolditud ribal üleliigne: `.is-teaser` hägusus ütleb sama ja
     kaks 20 px märki 76 px real ei mahu kõrvuti loetavalt. */
  html.nav-peidus .admin-nav .nav-lock{display:none}
}

/* Telefonis on tabel endiselt semantiline, kuid mitte visuaalselt pööratud
   tabel. Müüja otsib toodet nime järgi ja tellimust numbri/ostja järgi; hind,
   laoseis, summa, aeg ja olek on ühe pilguga loetav metarida. */
@media (max-width:620px){
  .table-wrap{overflow:visible;background:none;box-shadow:none}
  .table-wrap table,.table-wrap .admin-products{display:block;min-width:0;width:100%}
  .table-wrap thead{display:none}
  .table-wrap tbody{display:grid;gap:12px}
  .table-wrap tr{position:relative;display:grid;min-height:132px;padding:14px 16px;border-radius:var(--r-lg);background:#fff;box-shadow:var(--hair),var(--shadow-1)}
  .table-wrap td{min-width:0;padding:0!important;text-align:left!important;border:0!important}
  .table-wrap td,.table-wrap td *{min-width:0}

  /* Tellimus: viide + ostja on pealkiri, summa ja aeg üks metarida, olek chip.
     132px mahutab kaks nime/e-posti rida ilma, et üks tellimus täidaks ekraani. */
  .admin .table-wrap tr{grid-template-columns:minmax(0,1fr) auto;grid-template-rows:auto auto 44px;column-gap:10px}
  .admin .table-wrap td:nth-child(1){grid-column:1;grid-row:1;font-size:var(--t-small)}
  .admin .table-wrap td:nth-child(1) a::after{content:"";position:absolute;inset:0;border-radius:var(--r-lg)}
  .admin .table-wrap td:nth-child(2){grid-column:1/3;grid-row:2;font-weight:800;line-height:1.35;overflow:hidden}
  .admin .table-wrap td:nth-child(2) .micro{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .admin .table-wrap td:nth-child(3){grid-column:1;grid-row:3;display:flex!important;align-items:center}
  .admin .table-wrap td:nth-child(4){grid-column:2;grid-row:1;color:var(--ink-3);font-size:var(--t-small)}
  .admin .table-wrap td:nth-child(5){grid-column:2;grid-row:3;align-self:center;font-size:1.08rem}

  /* Toode: kogu kaart avab muutmise. Eemaldamine jääb oma 44px puutealaks
     lingi peale, slug on telefonis peidus, sest ta ei aita kiiret lao-/hinnatööd. */
  .admin-products tr{grid-template-columns:minmax(0,1fr) auto;grid-template-rows:minmax(44px,auto) 32px 44px}
  .admin-products td:nth-child(1){grid-column:1/3;grid-row:1;overflow:hidden;padding-right:26px}
  .admin-products .admin-name{display:-webkit-box;overflow:hidden;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-height:1.35}
  .admin-products .admin-name::after{content:"";position:absolute;inset:0;border-radius:var(--r-lg)}
  /* Kogu kaart avab muutmise, aga MITTE MIDAGI seda ei ütle: telefonis on
     „Muuda" `display:none` (all) ja nimi on must rasvane tekst ilma joone või
     värvita. Nool on ainus märk, et rida viib kuhugi. Ta on `::before`, sest
     `::after` on juba venitatud kate; kumbki ei ole positsioneeritud, seega
     paiknevad mõlemad SAMA `tr`-i suhtes — `td`-le `position` andmine oleks
     katte 343×148 pealt 311×44 peale kokku tõmmanud ja puuteala ära rikkunud.
     `td` sai `padding-right`-i, et kaherealine nimi noole alla ei jookseks. */
  .admin-products .admin-name::before{
    content:"›";position:absolute;top:16px;right:14px;
    color:var(--ink-3);font-size:1.45rem;font-weight:700;line-height:1;
  }
  .admin-products .product-slug{display:none}
  .admin-products td:nth-child(2){grid-column:1;grid-row:2;align-self:center}
  .admin-products td:nth-child(3){grid-column:2;grid-row:2;align-self:center;color:var(--ink-2)}
  .admin-products td:nth-child(4){grid-column:1;grid-row:3;display:flex!important;align-items:center}
  .admin-products td:nth-child(5){grid-column:2;grid-row:3;position:relative;z-index:1;align-self:center}
  .admin-products .barlink{display:none}
  .admin-products .linkbutton{min-height:44px;padding-inline:8px}
}

/* Tokenid, e-postid, slug'id ja makselingid ei tohi 375px vaateakent laiaks
   suruda. Kerib ainult dokument; tekst murdub oma veeru sees. */
.app-shell :is(.micro,.admin-name,.review-product,.lead,p,li){overflow-wrap:anywhere}

/* Tellimuste tabel on kesta PEATEGELANE — ta venib, nagu kassalint ja tühja
   seisundi ekraan. Ilma selleta lõpeb sisu tabeli viimasel real ja tema ja
   jaluse vahele jääb täpselt see tühi taust, mille disainiaudit 13.08.2026
   ette heitis. `overflow-x` jääb tabelile alles, kõrgust ta ei piira. */
.app-main>.table-wrap{flex:1 1 auto}

@media (max-width:620px){
  .auth-card{padding:22px 18px;border-radius:var(--r-lg)}
  /* Telefonis ei ole konto lõpetamine lehe põhitöö. Väljalogimine on Rohkem
     lehel; lehe tegevus jääb kompaktseks ning sisuga samasse vaatevälja. */
  .app-bar-actions{display:none}
  .mobile-primary{display:flex;margin:0 0 12px}
  .mobile-primary .button{min-height:44px;padding:8px 18px}
}

/* Rohkem-lehel on iga sihtkoht terve 64px puuteala. Selle ekraani üks töö on
   valida teisene sihtkoht; kirjeldus ennetab proovimise teel navigeerimist. */
.more-menu{display:grid;gap:10px;max-width:680px}
.more-menu>a{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:64px;padding:10px 18px;border-radius:var(--r-md);background:#fff;box-shadow:var(--hair),var(--shadow-1);color:var(--ink);text-decoration:none}
.more-menu span{display:grid;gap:2px}.more-menu small{color:var(--ink-3)}.more-menu b{font-size:1.6rem;color:var(--green)}
.more-logout{margin-top:20px}.more-logout .button{min-height:44px}

/* ---------------------------------------------------------------------------
   38. TOOTEHALDUS  (`src/routes/haldus-tooted.ts`)

   Uus osa, mitte olemasolevate ümbernimetamine. Kõik siinsed nimed on UUED:
   `.admin-products` ei ole `.admin`, sest veerud on teised. `.admin` kannab
   TELLIMUSTE tabeli veerureegleid (raha viiendas veerus) ja tema kasutamine
   toodete peal tõmbaks raha valesse veergu — täpselt see viga, mis osas 25
   juba üks kord parandati.
   ------------------------------------------------------------------------ */

/* --- Vorm ---------------------------------------------------------------- */
/* Üks veerg, suured väljad, null kaarti kaardi sees. Müüja täidab selle vormi
   telefonis, sageli ühe käega — iga vahepealne raam on üks kerimine juurde. */
.admin-form{
  display:grid;gap:20px;align-content:start;
  width:100%;max-width:640px;
}
.admin-form .actions{margin:10px 0 0}

/* Hind ja kogus on ÜKS otsus kahes lahtris ja nad kuuluvad kõrvuti. Telefonis
   nad virnastuvad, sest 88px väli 187px laiuses veerus ei ole väli. */
.field-row{display:grid;gap:20px}
@media (min-width:600px){
  .field-row{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* Tekstiala ja valik pärivad `.field-input` pinna, aga mitte tema kõrgust:
   `min-height:88px` on PUUTEALA nõue ühereaslisele väljale (doktriin 9), mitte
   nelja rea kõrgus. */
.field-area{
  min-height:132px;padding:16px 20px;
  line-height:1.55;resize:vertical;
}
/* Natiivne noolekast erineb igas brauseris. `appearance:none` + oma nool teeb
   valikust sama keha, mis tekstiväljal. Nool on data-URI SVG: CSP `img-src`
   lubab `data:` ja väline fail oleks võrgupäring kehva leviga turuletil. */
.field-select{
  appearance:none;-webkit-appearance:none;
  padding-right:56px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%236E7F76' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 8 5 5 5-5'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right 20px center;
  background-size:20px 20px;
  cursor:pointer;
}

/* --- Kinnitusteade ------------------------------------------------------- */
/* Roheline riba on KINNITUS, mitte hoiatus: sama vasak värviriba kui `.error`
   osas 19, ainult teise tähendusega. Ta on `role="status"`, ehk ekraanilugeja
   loeb ta ette ilma fookust varastamata. */
.notice-line{
  position:relative;
  margin:0 0 4px;padding:14px 20px 14px 22px;
  border-radius:var(--r-md);
  background:var(--green-pale);color:var(--green-3);
  font-weight:750;line-height:1.5;
  box-shadow:inset 0 0 0 1px rgba(11,107,46,.16);
}
.notice-line::before{
  content:"";position:absolute;left:0;top:10px;bottom:10px;width:4px;
  border-radius:0 4px 4px 0;background:currentColor;
}

/* --- Toodete tabel ------------------------------------------------------- */
/* Veerud: Toode · Hind · Laos · Olek · Tegevus.
   Raha on teises veerus ja ta on paremal, ühelaiuste numbritega — hinnakiri
   loetakse ÜLALT ALLA ja vasakule joondatud numbrid ei ole veerg, vaid müra. */
/* `.table-wrap table` on (0,1,1) ja võidaks paljast `.admin-products`-i (0,1,0).
   Kaks klassi teevad (0,2,0) — viis veergu ei mahu 640px sisse ilma, et
   tegevuste veerg nimele otsa jookseks. */
.table-wrap .admin-products{min-width:680px}
.admin-products th:nth-child(2),.admin-products td:nth-child(2),
.admin-products th:nth-child(3),.admin-products td:nth-child(3){
  text-align:right;white-space:nowrap;font-variant-numeric:tabular-nums;
}
.admin-products td:nth-child(2){font-weight:800;color:var(--ink);font-size:1.05rem}
.admin-products th:last-child,.admin-products td:last-child{text-align:right}

/* Nimi on LINK ja ta on rea peategelane. Aadress tema all on hall pisitekst,
   sest teda loetakse harva, aga ta peab olema olemas: ta ei muutu enam kunagi
   ja müüja trükib ta sildile. */
.admin-name{
  display:inline-flex;align-items:center;min-height:44px;
  color:var(--ink);font-weight:800;letter-spacing:-.012em;text-decoration:none;
}
.admin-name:hover{color:var(--green)}
.admin-products td:first-child .micro{display:block;overflow-wrap:anywhere}

/* Tegevused virnas, mitte reas: „Muuda" ja „Eemalda poest" kõrvuti tähendab
   turuletil, et sõrm tabab valet. Vertikaalne vahe on odavam kui vale puude. */
.admin-row-actions{white-space:nowrap}
.admin-row-actions>*{display:block}
.admin-row-actions form{margin:0}
.admin-row-actions .barlink{min-height:44px}
.admin-row-actions .linkbutton{margin-left:auto}

/* Olekumärgis. `.status` baaskuju on osas 25; siin on ainult kaks uut tooni.
   Peidus toode EI OLE viga, seega ta ei ole punane — ta on hall. */
.status.active{background:var(--green-pale);color:var(--green-3)}
.status.inactive{background:var(--paper-2);color:var(--ink-3)}
.status.inactive::before{background:var(--ink-3)}

/* Laoseis on OTSUS, mitte number: „Otsas" on müüja jaoks tegevus, mitte null.
   Sama kolmene loogika, mis poelehe `.stock` juures (osa 15) — teine kuju,
   sest tabelireal ei ole ruumi märgisele. */
.stock-out{color:var(--red);font-weight:850}
.stock-low{color:var(--amber);font-weight:850}

/* --- Mobiil -------------------------------------------------------------- */
@media (max-width:560px){
  .admin-form .actions{flex-direction:column;align-items:stretch}
  .admin-form .actions .button{width:100%}
  .admin-row-actions .linkbutton{margin-left:0}
}

/* See reegel peab olema toote desktop-min-width reeglist HILJEM. Muidu võidab
   680px tabel 375px telefonis kaskaadi ja dokument hakkab paremale kerima. */
@media (max-width:620px){
  .table-wrap .admin-products{min-width:0;width:100%}
}

/* Slug on desktopil kasulik püsiva aadressina, kuid telefonis on kaardi ainus
   töö toote leidmine ja muutmine. See hiline, täpsem reegel peab võitma
   desktopi `.admin-products td:first-child .micro {display:block}` lepingu. */
@media (max-width:980px){
  .admin-products td:first-child .product-slug{display:none}
}

/* ═══════════════════════════════════════════════════════════════════════════
   40. VIIMISTLUS — HIERARHIA, PIND, SEISUND, LIIKUMINE
   Martti 13.08.2026: „see peab olema high-end teenus, mida inimene tahaks
   kasutada oma e-poena ja mis tekitab usaldust."

   Neli ettekannet ekraanidelt ja neli vastust:
     1. Statistikal PUUDUS hierarhia  → üks arv juhib, ülejäänud on kontekst.
     2. Sildid KARJUSID               → silt vaikne, arv vali (osa 32 parandus).
     3. Võre nägi välja nagu TABEL    → jooned välja, valgus sisse.
     4. Päis SÕI PÜSTRUUMI            → logo kõrvale, mitte kolm rida kohakuti.

   🔴 ÜHTEGI OLEMASOLEVAT KLASSI EI OLE ÜMBER NIMETATUD. Kõik siinsed nimed on
   uued ja iga uus nimi on VABATAHTLIK: leht, mis neid ei kasuta, näeb ikka
   parem välja, sest osa parandustest on tehtud olemasolevate klasside sees.
   ------------------------------------------------------------------------ */

/* --- 40.1 PÄIS: püstruum on telefonis kallis ----------------------------- */
/* Enne: bränd, eelpealkiri ja H1 kolmes reas kohakuti = ~155 px enne esimest
   päris andmerida 812 px ekraanil. Logo ei vaja oma rida — ta on 26 px kõrge
   märk 44 px real. Kõrvale tõstetuna kaob üks rida ja pealkiri tõuseb ekraani
   ülaserva. `.app-bar-id` oli seni ILMA ühegi reeglita, seega see plokk ei
   kirjuta midagi üle; ta annab kujule esimest korda kuju. */
.app-bar-id{
  display:grid;
  grid-template-columns:auto minmax(0,1fr);
  grid-template-rows:auto auto;
  align-items:center;
  column-gap:13px;
  min-width:0;
}
.app-bar-id>*{grid-column:2;min-width:0;margin:0}
.app-bar-id>.brand{grid-column:1;grid-row:1/span 2}
.app-bar-id>.eyebrow{grid-row:1}
.app-bar-id>:is(h1,h2,.app-bar-title){grid-row:2}

/* Rakenduse pealkiri EI OLE müügilehe pealkiri. `--t-h1` on 50 px lauaarvutis
   — see on hero-suurus, mis ütleb „see leht müüb sulle midagi". Töölaud ei müü;
   ta annab aru. Väiksem, tihedam pealkiri jätab suurima kirja PÄEVAKÄIBELE,
   mis ongi lehe ainus peategelane. */
.app-shell>:is(header,.app-head) :is(h1,h2){
  font-size:clamp(1.5rem,3.2vw,2rem);
  line-height:1.04;letter-spacing:-.032em;
}
/* Päise nupud on TEISENE tee (tellimused, väljalogimine). 56 px pill kõrval
   pealkirjal loeb sama valjult kui pealkiri ise. 44 px on doktriin 8 miinimum
   mitte-kassa elemendile ja siin on ta ka õige kaal. */
.app-shell>:is(header,.app-head) .button{
  min-height:44px;padding:11px 20px;font-size:var(--t-small);
}

/* --- 40.2 SILDID: vaikne kirjapilt --------------------------------------- */
/* 🔴 EELPEALKIRI ON MÜÜGILEHE RIIST, MITTE TÖÖRIISTA OMA.
   Versaal + .15em tähevahe annab ajakirjarütmi lehele, mida loetakse üks kord.
   Töölauda loetakse iga päev ja seal loeb sama kuju karjumisena — pealegi seisis
   „VIIMASED TELLIMUSED · 13.08.2026" täpselt sama valjult kui kõik muu.
   Tekst on HTML-is JUBA lausekirjas („Täna", „Sinu pood", „Viimased tellimused"),
   seega versaali kustutamine annab õige kirjapildi ILMA markupita.
   Kriips jääb ja ta jääb roheliseks — see on ainus koht, kus bränd peab siin
   nähtav olema. */
.app-shell .eyebrow{
  text-transform:none;
  letter-spacing:.01em;
  font-size:var(--t-small);
  font-weight:700;
  color:var(--ink-3);
  gap:9px;
  margin:0 0 10px;
}
.app-shell .eyebrow::before{width:18px;background:var(--green-2);opacity:.7}

/* Mitmesõnaline nupusilt („Ühenda makselahendus") murdub ilma selleta 4+1
   sõnaks. `balance` jagab read ühtlaseks; ta ei muuda laiust ega kõrgust,
   ainult murdekohta. */
.app-shell .button{text-wrap:balance}

/* --- 40.3 STATISTIKA: üks arv juhib -------------------------------------- */
/* Leping kolme agendi jaoks, KOLM TEED ühe kujuni:
     a) MARKUPITA — `.dashboard-summary` esimene lahter saab peamise kuju
        automaatselt. Praegune töölaud saab hierarhia ilma ühegi muudatuseta.
     b) `.stat-lead` klass ükskõik millise `.pos-day` lapse peal, kui peamine arv
        EI OLE esimene. Kui `.stat-lead` on olemas, lülitub (a) välja — muidu
        oleks lehel kaks peategelast.
     c) `<ul class="stat-grid">` + `<li class="stat-tile">` seal, kus `.pos-day`
        ei sobi (nt aruandeleht ilma päevakokkuvõtte tähenduseta).

   Oodatud kuju kõigil kolmel juhul on SAMA:
     <li class="stat-lead">
       <span class="stat-label">Täna laekunud</span>
       <strong class="stat-value">128,40 €</strong>
       <span class="stat-note">12 makstud tellimust</span>   ← vabatahtlik
     </li>
   Paljas `<span>` + `<strong>` (klassideta) töötab täpselt sama hästi —
   praegune töölaud teebki nii. */
.stat-grid{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));
  gap:8px;margin:0;padding:0;list-style:none;
  --stat-size:var(--t-stat);
  --stat-ink:var(--ink);
  --label-ink:var(--ink-4);
  --label-size:var(--t-label);
}
.stat-tile{
  display:grid;align-content:center;gap:4px;
  min-width:0;padding:12px 15px;
  border-radius:var(--r-md);
  background:linear-gradient(180deg,rgba(255,255,255,.88),rgba(255,255,255,.52));
  box-shadow:var(--hair);
}
.stat-tile :is(span,dt,.stat-label){
  color:var(--label-ink,var(--ink-4));font-size:var(--label-size,var(--t-label));
  font-weight:650;letter-spacing:0;text-transform:none;line-height:1.32;
  overflow-wrap:normal;word-break:normal;hyphens:none;text-wrap:balance;
}
.stat-tile :is(strong,dd,.stat-value){
  margin:0;color:var(--stat-ink,var(--ink));
  font-size:var(--stat-size,var(--t-stat));
  font-weight:900;letter-spacing:-.032em;line-height:1.06;
  font-variant-numeric:tabular-nums;
}

/* PEAMINE LAHTER. Ta ei ole „sama lahter, aga paksem" — ta on OMA PIND:
   terve laius, oma valgusväli, oma aste skaalast ja roheline tint, sest laekunud
   raha ongi see värv (UX-SPETS, makse kinnitus). Kolm selektorit kannavad ühte
   kuju; deklaratsioonid ise on muutujates, seega sisu ei vaja eraldi reegleid. */
.pos-day>.stat-lead,
.stat-grid>.stat-lead,
.dashboard-summary>.pos-day:not(:has(>.stat-lead))>:is(li,div):first-child{
  --stat-size:var(--t-stat-hero);
  --stat-ink:var(--green-4);
  --label-ink:var(--green-3);
  --label-size:var(--t-small);
  position:relative;overflow:hidden;
  grid-column:1/-1;flex:1 1 100%;
  display:grid;align-content:center;gap:5px;
  min-height:116px;
  padding:18px 20px 19px;
  border-radius:var(--r-lg);
  background:
    var(--grain),
    var(--field-green),
    linear-gradient(176deg,#fff 0%,var(--green-mist) 76%,#E3F1E9 100%);
  box-shadow:var(--hair-2),var(--shadow-2),var(--edge);
}
/* Valgusväli nurgas. ÜKS pehme ring annab sügavuse, mille jaoks mujal
   joonistatakse raam — ja ta on `overflow:hidden` all, ehk ta ei lekiks
   kunagi naaberlahtrisse. */
.pos-day>.stat-lead::after,
.stat-grid>.stat-lead::after,
.dashboard-summary>.pos-day:not(:has(>.stat-lead))>:is(li,div):first-child::after{
  content:"";position:absolute;right:-46px;top:-66px;
  width:210px;aspect-ratio:1;border-radius:50%;
  background:radial-gradient(closest-side,rgba(18,161,80,.22),transparent 70%);
  pointer-events:none;
}

/* Märkus arvu all — kontekst, mis teeb arvust loo („12 makstud tellimust").
   (0,2,0) on siin nõue: `.pos-day :is(span,…)` on (0,1,1) ja võidaks paljast
   `.stat-note`-i, ehk märkus päriks sildi suuruse ja kaoks tema sisse. */
.pos-day .stat-note,
.stat-tile .stat-note,
.stat-lead .stat-note{
  color:var(--ink-3);font-size:var(--t-micro);font-weight:650;
  letter-spacing:0;line-height:1.4;
}

/* Muutuse märgis. Kolmnurk on `border`-itest, mitte tekstist: nool tekstina
   loetakse ekraanilugejas ette ja tähendus on juba arvus. */
.stat-trend{
  display:inline-flex;align-items:center;gap:6px;width:fit-content;
  margin-top:2px;padding:3px 10px 3px 9px;border-radius:var(--r-full);
  background:var(--paper-2);color:var(--ink-3);
  font-size:var(--t-micro);font-weight:800;letter-spacing:0;
  font-variant-numeric:tabular-nums;white-space:nowrap;
}
.stat-trend::before{
  content:"";flex:none;width:0;height:0;
  border-inline:5px solid transparent;
  border-block-end:6px solid currentColor;
}
.stat-trend.is-up{background:var(--green-pale);color:var(--green-3)}
.stat-trend.is-down{background:var(--amber-pale);color:var(--amber)}
.stat-trend.is-down::before{rotate:180deg}
/* Muutuseta EI OLE nool alla. Kriips ütleb „sama", nool ütleks „langes". */
.stat-trend.is-flat::before{
  width:9px;height:2px;border:0;border-radius:2px;background:currentColor;
}

/* Täitumusriba (päevaeesmärk, laoseis). Täitumus tuleb KLASSIST, mitte
   `style`-atribuudist — CSP `style-src 'self'` (doktriin §1). Sama leping, mis
   `.rating-bar`-il osas 30: server ümardab 5 sammuni ja lisab `.pct-N`;
   `data-pct="N"` teeb sama. */
.stat-meter{
  --pct:0;
  display:block;height:8px;margin-top:9px;border-radius:var(--r-full);
  background:
    linear-gradient(90deg,var(--green-3),var(--green-2)) left center/calc(var(--pct)*1%) 100% no-repeat,
    var(--paper-3);
  box-shadow:inset 0 0 0 1px rgba(10,52,28,.07);
}
.stat-meter.pct-0,.stat-meter[data-pct="0"]{--pct:0}
.stat-meter.pct-5,.stat-meter[data-pct="5"]{--pct:5}
.stat-meter.pct-10,.stat-meter[data-pct="10"]{--pct:10}
.stat-meter.pct-15,.stat-meter[data-pct="15"]{--pct:15}
.stat-meter.pct-20,.stat-meter[data-pct="20"]{--pct:20}
.stat-meter.pct-25,.stat-meter[data-pct="25"]{--pct:25}
.stat-meter.pct-30,.stat-meter[data-pct="30"]{--pct:30}
.stat-meter.pct-35,.stat-meter[data-pct="35"]{--pct:35}
.stat-meter.pct-40,.stat-meter[data-pct="40"]{--pct:40}
.stat-meter.pct-45,.stat-meter[data-pct="45"]{--pct:45}
.stat-meter.pct-50,.stat-meter[data-pct="50"]{--pct:50}
.stat-meter.pct-55,.stat-meter[data-pct="55"]{--pct:55}
.stat-meter.pct-60,.stat-meter[data-pct="60"]{--pct:60}
.stat-meter.pct-65,.stat-meter[data-pct="65"]{--pct:65}
.stat-meter.pct-70,.stat-meter[data-pct="70"]{--pct:70}
.stat-meter.pct-75,.stat-meter[data-pct="75"]{--pct:75}
.stat-meter.pct-80,.stat-meter[data-pct="80"]{--pct:80}
.stat-meter.pct-85,.stat-meter[data-pct="85"]{--pct:85}
.stat-meter.pct-90,.stat-meter[data-pct="90"]{--pct:90}
.stat-meter.pct-95,.stat-meter[data-pct="95"]{--pct:95}
.stat-meter.pct-100,.stat-meter[data-pct="100"]{--pct:100}

/* --- 40.4 PINNAD: sügavus valgusest, mitte joonest ----------------------- */
/* Külgpaneel oli lame gradient. Üks rohekas valgusväli ülaservas annab talle
   suuna (valgus tuleb ülalt, nagu `body::before`-il) ja eraldab ta põhiveerust
   ilma teist joont lisamata. */
@media (min-width:981px){
  .app-side{
    background:
      var(--field-green),
      linear-gradient(180deg,var(--card),var(--paper-2));
  }
  /* Peamine arv 340 px veerus ei tohi olla 56 px — „1 234,56 €" jookseks üle
     serva. Token, mitte uus reegel: piirang elab seal, kus suurus tekib. */
  .app-side{--t-stat-hero:clamp(2rem,2.6vw,2.55rem)}

  /* 🔴 KITSAS VEERG EI KANNA PLAATE. 355 px sees on kaks plaati 170 px laiused
     ja „2 · 51,60 €" murdus neis KAHELE REALE, euromärk üksinda teisel — täpselt
     see kuju, mis loeb renderdusveana. Rida (silt vasakul, arv paremal) mahutab
     sama info poole väiksemasse kõrgusesse ja teeb kontekstist VAIKSE PEAKIRJA,
     mitte neli võistlevat kasti peamise arvu all. Raha joondub paremale veergu,
     nagu igal pool mujal failis. */
  .dashboard-summary>.pos-day>:is(li,div):not(.stat-lead):not(:first-child),
  .dashboard-summary>.pos-day:has(>.stat-lead)>:is(li,div):not(.stat-lead){
    flex:1 1 100%;
    grid-template-columns:minmax(0,1fr) auto;
    /* `baseline` on ilus KUNI sildini, mis murdub kahele reale („Keskmine
       ostukorv" 288 px paneelis) — siis joondub arv sildi ESIMESE reaga ja
       ripub rea ülaservas. `center` peab mõlemal juhul. */
    align-items:center;
    column-gap:14px;
    padding:10px 15px;
    /* Reas ei ole plaadi kaalu vaja: pind kannab, vari mitte. */
    box-shadow:none;
  }
  .dashboard-summary>.pos-day>:is(li,div):not(.stat-lead):not(:first-child)>:is(strong,dd,.stat-value),
  .dashboard-summary>.pos-day:has(>.stat-lead)>:is(li,div):not(.stat-lead)>:is(strong,dd,.stat-value){
    text-align:right;
  }
  .dashboard-summary>.pos-day>:is(li,div):not(.stat-lead):not(:first-child):hover,
  .dashboard-summary>.pos-day:has(>.stat-lead)>:is(li,div):not(.stat-lead):hover{
    box-shadow:var(--hair);
  }
}

/* Kassalindi tühi saba on VALGE VÄLI, mille disainiaudit ette heitis. Ta ei
   ole viga (lint venib taotluslikult ekraani põhjani), aga puhas valge loeb
   „siin lõppes leht". Sama tera, mis lehe taustal, teeb temast PABERI. */
.pos-tape{
  background-image:var(--grain);
  background-color:#fff;
}
/* 🔴 KOLM RIDA EI VENI EKRAANI PÕHJANI. Osa 32 andis lindile `flex:1 1 auto`,
   et kest täidaks ekraani — õige otsus TÄIS lindi kohta, aga kolme reaga tekitas
   ta 300 px valge kasti, mille sees ei ole midagi, ja lükkas „Kõik tellimused"
   lingi lindist kaugele alla. Kest täidab ekraani ikka (`.app-main` on shell'i
   võres `1fr`), seega jalus jääb põhja — venib ainult see, millel on sisu venida.
   Kuuendast reast alates on venimine jälle õige ja ta lülitub ise tagasi sisse. */
.app-main>.pos-tape:not(:has(>:nth-child(6))){flex:0 0 auto}

/* Ühenduskaart on müüja esimene tegevus ja seni oli ta ilma pinnata valge
   ristkülik. Roheline valgusväli tõstab ta paneelis esile, ilma et ta muutuks
   hoiatuseks — kollane/punane oleks vale, sest midagi ei ole katki. */
.dashboard-onboarding{
  background:
    var(--field-green),
    linear-gradient(180deg,var(--card),var(--green-mist));
  box-shadow:var(--hair-2),var(--shadow-2),var(--edge);
}
.dashboard-onboarding h2{letter-spacing:-.022em}
.dashboard-onboarding p{color:var(--ink-2)}

/* Tabelipäis on RIBA, mitte rida allajoonega. Pehme pind eraldab päise
   andmetest ka siis, kui joont ei ole — ja andmeread jäävad ainsaks kohaks
   lehel, kus on valge. */
.table-wrap thead th{
  background:linear-gradient(180deg,var(--paper-2),var(--paper-3));
  border-bottom:0;
  box-shadow:inset 0 -1px 0 var(--line-2);
}

/* --- 40.5 SEISUNDID ------------------------------------------------------ */
/* 🔴 IGAL PUUDUTATAVAL ASJAL ON NELI SEISUNDIT. Kui mõni puudub, ei tundu asi
   lihtne — ta tundub katki. `:focus-visible` on siin NÕUE, mitte viisakus:
   müüja, kes navigeerib klaviatuuriga, peab nägema, kus ta on. */

/* Telefonis oli navil ainult `:active`. Hover puudus (õigustatult — puuteekraan),
   aga hübriidseadmel ja lauaarvuti kitsas aknas ta on.
   🔴 PIIRITLUS ON `max-width:980px` JA SEE EI OLE VORMISTUS. See reegel seisab
   failis osa 41 JÄREL, seega ta võitis ilma piirdeta lauaarvuti tumeda riba
   hoveri: hele `--green-mist` pind ja tume roheline tekst mustal külgribal.
   Kaks reeglit, kaks pinda — kumbki oma laiusel. */
@media (max-width:980px){
  .admin-nav a:hover{background:var(--green-mist);color:var(--green-3)}
}
/* Rõngas läheb SISSEPOOLE. Vaikimisi `outline-offset:3px` joonistaks rõnga
   fikseeritud riba servast VÄLJA, ekraani alla — nähtamatu fookus on sama, mis
   fookuse puudumine. */
.admin-nav a:focus-visible{outline-offset:-4px;border-radius:var(--r-sm)}

.more-menu>a{
  transition:box-shadow var(--base) var(--ease),translate var(--fast) var(--ease),
             background var(--fast) var(--ease);
}
.more-menu>a:hover{background:var(--card);box-shadow:var(--hair-2),var(--shadow-2);translate:0 -1px}
.more-menu>a:active{translate:0 1px;box-shadow:var(--hair-2),0 1px 2px rgba(10,52,28,.14)}
.more-menu>a:hover b{color:var(--green-2)}

/* Tabelirida saab sama tooni ka siis, kui fookus jõuab tema SISSE — muidu
   kaob klaviatuuriga liikujal rea ja lingi seos ära. */
.table-wrap tbody tr:focus-within{background:var(--green-mist)}
.pos-tape>:is(li,.pos-tape-row){transition:background var(--fast) var(--ease)}
.pos-tape>:is(li,.pos-tape-row):hover{background:var(--green-mist)}

.barlink{transition:color var(--fast) var(--ease)}
.barlink:active{color:var(--green-3)}
.barlink:focus-visible{outline-offset:2px;border-radius:var(--r-sm)}
.linkbutton:focus-visible{outline-offset:1px;border-radius:var(--r-sm)}
.admin-name:active{color:var(--green-3)}
.app-foot a:focus-visible,.app-bar-id .brand:focus-visible{outline-offset:2px;border-radius:var(--r-sm)}

/* Kontekstilahter reageerib kursorile vaikselt — ta EI OLE nupp ja ei tohi
   selliseks näida, aga täiesti surnud pind loeb pildina. */
.dashboard-summary>.pos-day>:is(li,div),
.stat-tile{
  transition:box-shadow var(--base) var(--ease),background var(--base) var(--ease);
}
.dashboard-summary>.pos-day>:is(li,div):not(.stat-lead):not(:first-child):hover,
.dashboard-summary>.pos-day:has(>.stat-lead)>:is(li,div):not(.stat-lead):hover,
.stat-tile:not(.stat-lead):hover{background:var(--card);box-shadow:var(--hair-2),var(--shadow-1)}

/* --- 40.6 LIIKUMINE: ilmumine kerimisel, null JS ------------------------- */
/* 🔴 KUS SEE TÖÖTAB JA KUS MITTE — see loend on mõõdetud, mitte arvatud.
   `view()` ajajoon otsib elemendi lähima KERIMISKONTEINERIST esivanema. Iga
   element, millel on `overflow` midagi muud kui `visible`, ON kerimiskonteiner
   (ka `overflow:hidden`), ja tema sees oleva elemendi ajajoon jääks nulliseks
   → element jääks IGAVESEKS `opacity:0` peale. Seepärast:
     ✔ `.app-main>*`        — `.app-main` on flex ilma overflow'ta
     ✔ `.dashboard-summary` lapsed — tema `.pos-day` on `overflow:visible`
     ✘ `.pos-tape>li`       — `.pos-tape` on `overflow:hidden`
     ✘ `.table-wrap tr`     — `overflow-x:auto` teeb ka Y-telje kerimiskonteineriks
   Animeeritud on seega KONTEINER (`.table-wrap` ise), mitte tema read.

   Ja teine punane: `translate`-animatsioon teeb elemendist fixed-elementide
   tugiraami. `.admin-nav` on `.app-shell`-i OTSENE laps ega satu ühegi siinse
   selektori alla — muidu hüppaks menüü telefonis keset lehte (vt osa 38). */
@media (prefers-reduced-motion:no-preference){
  @supports (animation-timeline:view()){
    .app-main>*,
    .dashboard-summary>:not(.pos-day),
    .dashboard-summary>.pos-day>:is(li,div),
    .stat-grid>*,
    .more-menu>a{
      animation:app-rise both;
      animation-timeline:view();
      animation-range:entry 0% entry 26%;
    }
    /* Astmeline viivitus tuleb VAHEMIKUST ja `:nth-child()`-ist, mitte
       inline-stiilist — CSP ei luba `style="..."` atribuuti. */
    .dashboard-summary>.pos-day>:is(li,div):nth-child(2n){animation-range:entry 0% entry 34%}
    .dashboard-summary>.pos-day>:is(li,div):nth-child(3n){animation-range:entry 0% entry 42%}
    .stat-grid>:nth-child(2n){animation-range:entry 0% entry 34%}
    .stat-grid>:nth-child(3n){animation-range:entry 0% entry 42%}
    .more-menu>a:nth-child(2n){animation-range:entry 0% entry 34%}
  }
}
/* Lühem tõus kui `rise` (osa 12): tööriist ei tohi liikuda nii palju kui
   müügileht. 10 px on märgatav, 20 px oleks etendus. */
@keyframes app-rise{from{opacity:0;translate:0 10px}to{opacity:1;translate:none}}

/* --- 40.7 TELEFON ON ESIMENE SEADE --------------------------------------- */
@media (max-width:620px){
  /* Peamine arv saab telefonis kogu laiuse ja tema ümber tekib hingamisruum.
     Kontekstilahtrid lähevad kahekaupa — kolm 375 px peal teeks igast sildist
     jälle kaherealise. */
  .dashboard-summary>.pos-day{gap:7px}
  .dashboard-summary>.pos-day>:is(li,div):not(.stat-lead):not(:first-child),
  .dashboard-summary>.pos-day:has(>.stat-lead)>:is(li,div):not(.stat-lead){
    flex:1 1 calc(50% - 4px);padding:11px 13px;
  }
  .stat-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .stat-grid>.stat-lead{grid-column:1/-1}
  /* Bränd võtab telefonis 26 px märgi + ~90 px teksti. Pealkirja veerg jääks
     alla 240 px ja „Tellimused" murduks. Märk üksi ütleb sama. */
  .app-bar-id{column-gap:11px}
  .app-shell>:is(header,.app-head){padding:11px var(--gutter) 12px}
}
@media (max-width:400px){
  /* 375 px: pealkiri on tähtsam kui sõnamärk. Märk jääb, sõna kaob — sama
     otsus, mis poeriba `.cart-link`-il osas 14. */
  .app-bar-id>.brand{font-size:0}
  .app-bar-id>.brand span{font-size:0}
  .app-bar-id>.brand::before{margin-right:0}
}

/* --- 40.8 PRINT ---------------------------------------------------------- */
/* Statistika ei ole kviitungi osa (vt osa 36 põhjendus). */
@media print{
  .stat-grid,.stat-tile,.stat-trend,.stat-meter{display:none}
}

/* --- 40.9 VÄHENDATUD LIIKUMINE ------------------------------------------- */
/* Osa 28 üldplokk nullib KESTUSE, aga nimeline animatsioon `.01ms` kestusega
   ikka JOOKSEB ja jätab elemendi viimasesse kaadrisse. Osa 37 leping: iga uus
   animatsioon on siin nimeliselt kirjas ja igal ühel on määratud, mis alles
   jääb. `app-rise` → sisu on kohe kohal, täies läbipaistmatuses. */
@media (prefers-reduced-motion:reduce){
  .app-main>*,
  .dashboard-summary>:not(.pos-day),
  .dashboard-summary>.pos-day>:is(li,div),
  .stat-grid>*,
  .more-menu>a{animation:none;opacity:1;translate:none}
}

/* --- 40.10 TOOTETABEL: rida on rida, mitte lõik ------------------------- */
/* Slug murdus `overflow-wrap:anywhere` tõttu („…/hommikurah / u") ja tegi
   kaherealisest nimest NELJAREALISE lahtri. Reegel ise on õige — ta hoiab
   makselingid ja tokenid 375 px vaateaknast sees — aga slug on VIIDE, mitte
   loetav tekst: teda vaadatakse, kui sildile trükkida, ja siis loetakse ta
   tootelehelt terveni. Üks rida kolmikpunktiga annab tabelile rütmi tagasi. */
.admin-products .product-slug{
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  overflow-wrap:normal;
}

/* Telefoni tootekaardil on kogu kaart puuteala (`.admin-name::after` katab rea).
   Puuteala ilma tagasisideta tundub katki — vajutus peab olema FÜÜSILINE, nagu
   nupul osas 5: pind läheb alla ja vari läheb väiksemaks. */
@media (max-width:620px){
  .table-wrap tr{
    transition:box-shadow var(--fast) var(--ease),translate var(--fast) var(--ease);
  }
  .table-wrap tbody tr:hover{background:#fff;box-shadow:var(--hair-2),var(--shadow-2)}
  .table-wrap tbody tr:active{translate:0 1px;box-shadow:var(--hair-2),0 1px 2px rgba(10,52,28,.14)}
  /* Fookus jõuab kaardile lingi kaudu; rõngas peab siis ümbritsema KAARTI,
     mitte lingi nähtamatut katteala. */
  .table-wrap tbody tr:focus-within{box-shadow:var(--hair-2),var(--shadow-2),0 0 0 3px var(--green-pale)}
  /* Hind on kaardi teine peategelane nime järel — laoseis on tema kõrval
     kontekst, mitte võrdne partner. */
  .admin-products td:nth-child(2){font-size:1.12rem}
  .mobile-primary{margin:0 0 4px}
}

/* --- 40.11 RIBAKUJUL KOKKUVÕTE (`.app-main>.pos-day`) ------------------- */
/* Demo töölaud ja kassa panevad päevakokkuvõtte PÕHIVEERGU ühe reana, mitte
   külgpaneeli. Seal ei ole ruumi omaette peamisele lahtrile — aga hierarhia
   peab olema ka seal, muidu on jälle neli võrdset arvu kõrvuti.
   Esimene arv saab ühe astme ja brändivärvi. Täpselt nii palju, et pilk teaks,
   kust alustada; ja täpselt nii vähe, et ta ei hakkaks kassas võistlema
   `.pos-total`-iga, mis on selle ekraani päris peategelane. */
.app-main>.pos-day>:is(li,div):first-child{
  --stat-size:calc(var(--t-stat) * 1.2);
  --stat-ink:var(--green-3);
}
/* Riba pind: sama valgus, mis mujal. Vertikaalsed vahejooned jäävad — üherealises
   ribas nad LOEVAD veergudena, mitte tabelina (see oli mitmerealise võre viga). */
.pos-day{
  background:
    var(--field-warm),
    linear-gradient(180deg,#fff,var(--paper-2));
}

/* 🔴 KAKS KAARTI ÜKSTEISE SEES ON ALATI VIGA.
   `.pos-day` on vaikimisi ÜKS kaart (`overflow:hidden`, oma raadius, oma vari)
   ja lahtrid on tema sees. Peamine lahter on aga ISE pind — kui ta tekib
   `.stat-lead`-iga suvalisel lehel, jäi ta kaardi sisse ja tema ümar nurk lõigati
   ära. Niipea kui ribas ON peamine lahter, ei ole riba enam kaart: ta on
   PAIGUTUS. Sama kuju, mille `.dashboard-summary` sai käsitsi — nüüd saab ta iga
   agent ilma seda konteksti teadmata. */
.pos-day:has(>.stat-lead){
  gap:8px;
  border-radius:0;background:none;box-shadow:none;overflow:visible;
}
.pos-day:has(>.stat-lead)>:is(li,div):not(.stat-lead){
  padding:12px 15px;
  border-radius:var(--r-md);
  background:linear-gradient(180deg,rgba(255,255,255,.88),rgba(255,255,255,.52));
  box-shadow:var(--hair);
}

/* --- 40.12 TESTMÜÜGI MÄRGE REAL (`.row-mode`) --------------------------- */
/* `src/routes/demo.ts` ütleb selle klassi juures sõnaselgelt: „ainult haak, kui
   keegi tahab talle hiljem oma kuju anda." Siin ta on.
   🔴 TA EI LÄHE VÄIKSEMAKS. Otsus #27 järgi peab testrežiim olema võimatu MITTE
   märgata, ja rea märge on viimane koht, kus müüja seda enne käibearvutust näeb.
   Ta läheb ÄRATUNTAVAKS: merevaik on sama keel, mis ribal ja bänneril (osa 34),
   ja ta lahutab kaks halli kõrvutist teksti — olekumärgis ja režiim ei ole enam
   üks hall mass. */
.row-mode{color:var(--amber);font-weight:750}

/* --- 40.13 SILT EI MURDU KUNAGI SÕNA KESKELT ---------------------------- */
/* 🔴 MÕÕDETUD 1000 px juures: nupul seisis „Ühenda makselahendu / s".
   Süüdlane ei ole nupp. `.app-shell :is(.micro,.admin-name,…,p,li)` paneb
   `overflow-wrap:anywhere` — õige ja vajalik reegel, sest makselink ja token
   peavad 375 px vaateaknas murduma — aga ta PÄRANDUB `<p class="actions">`-ist
   nupu sisse. Üksik täht nupu teisel real loeb katkise renderdusena, mitte
   kitsa veeruna, ja usaldust ehitaval lehel on see kallim viga kui ülevool.
   Nimekiri on TÄPNE: siin on ainult elemendid, mille sisu on SILT (lühike,
   toimetatud tekst). Andmeväljad — `.micro`, `.admin-name`,
   `.product-slug` — jäävad murdvaks, sest nende sisu tuleb andmebaasist ega
   mahu lubadusse. */
.app-shell :is(.button,.status,.stat-trend,.linkbutton,.barlink,.admin-nav a,.eyebrow){
  overflow-wrap:normal;word-break:normal;hyphens:none;
}

/* ═══════════════════════════════════════════════════════════════════════════
   41. TÖÖLAUA LINDI PÄEVAVAHEREA  (`li.tape-day`)
   Lisatud töölauaagendi poolt — `src/routes/haldus.ts` `tapeDay()`.
   Osa 32 (`.pos-tape`) ja osa 40 jäävad puutumata; siin on AINULT uus klass.

   Martti 13.08.2026: „tellimuste lint peab lugema nimekirjana, mitte tabelina."

   🔴 KAARDI JOONISTAMINE EI TEE TABELIST NIMEKIRJA. Kaheksa ühesugust rida,
   igaühel neli ühesugust välja, ON tabel ka valgel paberil ümarate nurkadega.
   Nimekirja teeb RÜTM: rühmad, mille vahel on pealkiri, ja rühma sees read,
   mis enam kuupäeva ei korda (`clock()` asendas `stamp()`). Täpselt nii loeb
   müüja päris kassalinti, mille ta õhtul letilt ära rebib.

   Vaherida on `<li>`, sest `.pos-tape` on `<ul>` ja ainus lubatud otsene laps
   on `<li>`. Ta EI OLE tellimus, seega temalt võetakse KOLM asja, mis rea
   tellimuseks teevad: 88 px puuteala kõrgus, võrepaigutus ja rea alljoon.
   ------------------------------------------------------------------------ */
.pos-tape>li.tape-day{
  /* `display:block` tühistab osa 32 võre — kolm veergu ühe sildi jaoks
     tekitaksid kaks tühja rada ja 24 px surnud ruumi paremasse serva. */
  display:block;
  min-height:0;
  padding:14px 14px 6px;
  /* Alljoon kuulub tellimusele. Vaherida ERALDAB rühmi, ta ei ole rühm ise. */
  box-shadow:none;
  /* Pind kustub sissepoole: rühma pealkiri on lindi PEAL, mitte tema sees
     eraldi kastis. Ühtegi joont juurde — sama otsus, mis osas 40.4. */
  background:linear-gradient(180deg,var(--paper-2),rgba(243,245,241,0));
  color:var(--ink-3);
  font-size:var(--t-label);font-weight:750;letter-spacing:.01em;line-height:1.3;
}
/* Lindi esimene laps istub ümaral ülaserval — ilma lisapadinguta lõikaks
   tekst nurgast läbi (`.pos-tape` on `overflow:hidden`). */
.pos-tape>li.tape-day:first-child{padding-top:16px}
/* 🔴 HOVER KUULUB TELLIMUSELE. Osa 40.5 andis `.pos-tape>li:hover` rohelise
   udu — puutetagasiside real, mida saab avada. Vaherida ei ava midagi ja
   roheliseks minev pealkiri lubaks klikki, mida ei tule. */
.pos-tape>li.tape-day:hover{background:linear-gradient(180deg,var(--paper-2),rgba(243,245,241,0))}

/* --- 41.1 OLEKUMÄRGIS: TÜHISTATUD JA TAGASTATUD -------------------------- */
/* 🔴 KAKS OLEKUT VIIEST OLID ILMA PINNATA. `STATUS_LABEL` (haldus.ts) tunneb
   viit olekut; osal 25 olid reeglid ainult `paid`-il ja `pending`-il. Ülejäänud
   kolm said `.status` põhikuju — pilli kuju, punkt ees — ILMA taustata ja
   päritud tekstivärviga. Mõõdetud töölaual: „Tühistatud" seisis paljalt lehe
   taustal, punkt musta täpina. See ei loe olekuna, see loeb laadimata stiilina,
   ja usaldust ehitaval lehel on see kallim kui vale värv.

   Toon kannab tähendust, mitte kaunistust:
     tühistatud  → HALL. Midagi ei juhtunud, raha ei liikunud, tegevust pole.
     tagastatud  → MEREVAIK. Raha LIIKUS ja liikus tagasi — sama keel, mis
                   `pending`-il ja testrežiimil (osa 34): „vaata siia". */
.status.cancelled{background:var(--paper-2);color:var(--ink-3)}
.status.refunded,.status.part_refunded{background:var(--amber-pale);color:var(--amber)}

/* ═══════════════════════════════════════════════════════════════════════════
   41. AVALEHT JA STAATILISED LEHED  (`scripts/build-static.ts`)

   🔴 SEE PLOKK KUULUB STAATILISE LEHE AGENDILE. Kõik siin on UUS klass —
   ühtegi olemasolevat reeglit siin üle ei kirjutata ja ühtegi olemasolevat
   klassi ümber ei nimetata. Kolm uut klassi (`.hero-proof`, `.price-hero`,
   `.price-examples`), kaks olemasoleva klassi TÄPSUSTUST oma uues kontekstis
   (`.audiences .line-icon`, hero viienda lapse viivitus) ja mitte midagi muud.

   Miks nad on siin, mitte markupis: CSP `style-src 'self'` — `style="..."`
   atribuuti ei ole olemas ja astmelised viivitused tulevad `:nth-child()`-ist.
   ══════════════════════════════════════════════════════════════════════════ */

/* --- 41.1 HERO TÕENDIREA ------------------------------------------------- */
/* Kolm rida hero nupupaari all: kus raha on, mis maksab null, mis ei ole
   lepinguga kinni. Nad on `<ul>`, mitte kolm `<p>`-d, sest tegu on LOETELUGA
   ja ekraanilugeja peab ütlema „kolm kirjet" — see on kogu mõte. */
.hero-proof{list-style:none;margin:28px 0 0;padding:0;display:grid;gap:11px;max-width:44ch}
.hero-proof li{
  display:flex;align-items:flex-start;gap:11px;
  color:var(--ink-2);font-size:var(--t-small);font-weight:650;line-height:1.45;
}
/* `.ico` on olemasolev klass ja tal EI OLE `stroke-width`-i — vaikimisi 1px
   linnuke näeb 19px juures välja nagu renderdusviga, mitte nagu märk.
   Paksus antakse siin, mitte `.ico` enda juures, et teised `.ico` kasutuskohad
   (poe- ja kassavaated) jääksid täpselt endiseks. */
.hero-proof .ico{width:19px;height:19px;margin-top:2px;stroke:var(--green-2);stroke-width:2.7;stroke-linecap:round;stroke-linejoin:round}

/* Hero sissetulek jätkub viienda lapsega. Ilma selleta ilmuks tõendirida
   nupupaariga SAMAL hetkel ja rütm katkeks just viimase sammu peal. */
@media (prefers-reduced-motion:no-preference){
  .hero>div>*:nth-child(5){animation-delay:280ms}
}

/* --- 41.2 HINNAKAARDI PEAMINE ARV ---------------------------------------- */
/* Hinnakiri ilma numbrita on nimekiri; number ilma ühikuta on kaunistus.
   `1,5` ja `%` on kaks eraldi elementi, sest nad ei ole ühesuurused ega ühte
   värvi — protsendimärk peab olema väiksem, muidu loeb silm „viisteist". */
.price-hero{
  /* 🔴 FLEX, MITTE GRID. Grid-is oli `small` `grid-column:1/-1` ja tema
     max-content laius (üks lause) jagati MÕLEMA veeru vahel laiali — number ja
     protsendimärk kandusid teineteisest ~60 px kaugusele ja lugesid kahe eraldi
     asjana. Flexis mõõdab rida ainult oma enda sisu ja `flex-basis:100%` viib
     allkirja järgmisele reale ilma veerulaiust puutumata. */
  display:flex;flex-wrap:wrap;align-items:baseline;
  column-gap:5px;margin:0 0 20px;padding-bottom:22px;
  border-bottom:1px solid var(--line);
}
.price-hero strong{
  font-size:clamp(3.1rem,6.4vw,4.2rem);font-weight:900;line-height:.88;
  letter-spacing:-.055em;color:var(--green-3);
  font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1;
}
.price-hero span{
  font-size:clamp(1.5rem,2.6vw,2rem);font-weight:850;letter-spacing:-.03em;
  color:var(--green-2);
}
.price-hero small{
  flex:0 0 100%;margin-top:10px;
  font-size:var(--t-small);font-weight:700;line-height:1.45;color:var(--ink-2);
}

/* --- 41.3 ARVUTATUD NÄITED ----------------------------------------------- */
/* „20 € müügist jääb sulle 19,70 €" oli enne üks lause halli väiketeksti sees.
   Neli rida tabelnumbritega teevad samast väitest KONTROLLITAVA arvutuse —
   ja neljas rida (kuu ilma müügita) on ainus koht, kus 0 € on tõestus. */
.price-examples{list-style:none;margin:22px 0 0;padding:0;display:grid;gap:6px;max-width:46ch}
.price-examples li{
  display:flex;align-items:center;justify-content:space-between;gap:18px;
  min-height:46px;padding:9px 18px;
  border-radius:var(--r-md);
  background:linear-gradient(180deg,var(--card),#FBFCF9);
  box-shadow:var(--hair),var(--shadow-1);
  font-size:var(--t-small);
}
.price-examples span{color:var(--ink-2);font-weight:650}
.price-examples strong{
  flex:none;font-weight:850;color:var(--green-3);letter-spacing:-.012em;
  font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1;
}

/* --- 41.4 SIHTRÜHMA KAARDI IKOON ----------------------------------------- */
/* `.line-icon` hover-ümberpööramine oli defineeritud ainult `.steps` ja
   `.feature-grid` sees. Sihtrühmakaardil oli ikoon seetõttu AINUS element,
   mis hoveril paigale jäi — kaart tõusis, ikoon mitte, ja see luges katkise
   üleminekuna. Ikoon on siin ka väiksem: kaart kannab pealkirja ja tõendit,
   mitte joonistust. */
.audiences .line-icon{width:52px;height:52px;margin:0 0 6px}
.audiences span:hover .line-icon rect{fill:var(--green-2)}
.audiences span:hover .line-icon path{stroke:#fff}

/* --- 41.5 TELEFON -------------------------------------------------------- */
@media (max-width:560px){
  /* Kaks veergu 375px juures tähendaks „Müüd 20 € pangalingiga" kahel real ja
     summat kolmandal. Rida on siis LÕIK, mitte rida — ja arvutus kaob ära. */
  .price-examples li{flex-direction:column;align-items:flex-start;gap:2px;padding:12px 16px}
  .price-examples strong{font-size:1.05rem}
}

/* ═══════════════════════════════════════════════════════════════════════════
   41. OSTJA TEEKOND — POOD → TOODE → KORV → KASSA → MAKSE → KINNITUS → KVIITUNG

   🔴 SEE PLOKK KUULUB OSTUVOO AGENDILE (`src/routes/shop.ts`,
      `src/routes/product.ts`, `src/routes/commerce.ts`). Ta on faili LÕPUS ja
      ta EI MUUDA ühtegi olemasolevat reeglit — iga siinne selektor on kas uus
      klass või olemasoleva klassi täiendus uues kontekstis.

   Neli asja, mida ta parandab, ja miks nad on vead, mitte maitse:

     1. MÜÜJAL EI OLNUD NÄGU. Nimi oli tekst päises, tekst kassas, tekst
        kviitungil — kolm korda lugemist, null äratundmist. Nüüd on `.crest`:
        monogramm, mis kordub poelehel, kassas, makselehel, kinnitusel ja
        kviitungil. Ostja tunneb poe ära ENNE, kui ta on nime lugenud.
     2. KATALOOGIL EI OLNUD SOTSIAALSET TÕENDIT. Hinne elas ainult tootelehel,
        kuhu ostja jõuab alles pärast otsust. `.product-rating` ja `.shop-score`
        toovad ta sinna, kus otsus tegelikult sünnib.
     3. MAKSELEHT VASTAS KAHELE KÜSIMUSELE JÄRJEST, MITTE KORRAGA. „Kellele" oli
        üleval, „kui palju" järgmises kaardis. `.pay-amount` toob nad ühele pinnale.
     4. KINNITUSE LINNUKE OLI GLÜÜF. `✓` tuleb igas süsteemis eri fondist ja
        mõnes puudub. `.success-check` on joonis — igal pool sama.
   ═══════════════════════════════════════════════════════════════════════════ */

/* --- 41.1 MÜÜJA MONOGRAMM ------------------------------------------------ */
/* Kuju on TEADLIKULT sama, mis `.brand::before` märgil: ümarnurkne ruut, mitte
   ring. Ring oleks avatar ja lubaks nägu; ruut on pitser ja lubab ettevõtet.
   Raadius on `suurus / 3.1` — sama suhe, mis brändimärgil (26px → 8px), nii et
   päiseriba ja poe märk on ühest perekonnast igas suuruses.
   `--crest-size` on ainus asi, mida kontekst muudab. Ükski kutsuja ei kirjuta
   siin ühtegi teist omadust üle. */
.crest{
  --crest-size:52px;
  flex:none;display:grid;place-items:center;
  width:var(--crest-size);height:var(--crest-size);
  border-radius:calc(var(--crest-size) / 3.1);
  background:linear-gradient(158deg,var(--green-2),var(--green-3) 62%,var(--green-4));
  color:#fff;
  font-size:calc(var(--crest-size) * .40);
  font-weight:900;letter-spacing:-.03em;line-height:1;
  text-transform:uppercase;
  user-select:none;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.30),
    inset 0 -1px 0 rgba(0,0,0,.18),
    0 2px 4px -1px rgba(6,58,26,.30),
    0 10px 22px -8px rgba(6,58,26,.38);
  /* Kviitung prinditakse. Ilma selleta jääb märgist tühi ruut ja dokumendi
     päis näeb välja nagu laadimata pilt. */
  print-color-adjust:exact;-webkit-print-color-adjust:exact;
}

/* --- 41.2 POE PÄIS ------------------------------------------------------- */
.shop-id{
  display:flex;align-items:center;
  gap:clamp(14px,2.2vw,20px);
  margin:0 0 18px;
}
.shop-id .crest{--crest-size:clamp(56px,8vw,72px)}
.shop-id-text{min-width:0}
.shop-id-text .eyebrow{margin:0 0 9px}
/* 🔴 MÕÕDETUD 375 px JUURES. Krest (56) + vahe (14) + kesta polster (2×26) +
   ääris (2×20) jätab pealkirjale 213 px. `--t-h1` on seal 32,8 px, ehk
   „PIIMATÖÖSTUS" oleks 234 px ja ajaks kaardi ekraanist välja. Oma clamp hoiab
   ta 21 px peal; `overflow-wrap` on tagavõrk juriidilisele nimele, mis tuleb
   andmebaasist ega mahu ühtegi lubadusse. */
.shop-id-text h1{
  font-size:clamp(1.6rem,5.6vw,3.15rem);
  margin:0;overflow-wrap:anywhere;
}

/* Poe koondhinne. Ta on LINK, mitte silt — TKS §17 lg 4 nõuab, et koondhinde
   juures oleks kättesaadav teave selle kohta, kuidas ostu kontrollitakse. */
.shop-score{margin:0 0 20px}
.shop-score>a{
  display:inline-flex;align-items:center;flex-wrap:wrap;
  gap:6px 12px;
  min-height:44px;padding:7px 18px 7px 14px;
  border-radius:var(--r-full);
  background:#fff;color:var(--ink);text-decoration:none;
  box-shadow:inset 0 0 0 1px rgba(11,107,46,.15),var(--shadow-1);
  transition:transform var(--fast) var(--ease),box-shadow var(--base) var(--ease);
}
.shop-score>a:hover{
  transform:translateY(-1px);
  box-shadow:inset 0 0 0 1.5px var(--green-2),var(--shadow-2);
}
.shop-score>a:active{transform:translateY(0)}
.shop-score .rating-value{
  font-size:1.06rem;font-weight:900;letter-spacing:-.025em;color:var(--ink);
  font-variant-numeric:tabular-nums;
}
.shop-score-count{color:var(--ink-2);font-size:var(--t-small);font-weight:700}

/* --- 41.3 TOOTEKAART ----------------------------------------------------- */
/* Vitriin on nüüd `<a>`, mitte `<div>`: pilt on kaardi suurim pind ja pildile
   vajutamine on ostja esimene refleks. Ankur on `tabindex="-1"` + `aria-hidden`
   (vt `shop.ts` põhjendust), seega tal EI OLE fookusrõngast vaja — ta ei saa
   fookust. Kõik muu kuju tuleb `.product-art`-ist osas 15. */
a.product-art{text-decoration:none;color:var(--green-3);cursor:pointer}

/* Hinderida kaardil. Kõrgus on FIKSEERITUD miinimumiga, sest kaardi rütm sõltub
   sellest, et hinnajoon algaks igal kaardil samalt kõrguselt (osa 15). */
.product .product-rating{
  display:flex;align-items:center;
  min-height:44px;margin:0 0 6px;padding-inline:20px;
}
/* 🔴 `min-height` on LINGIL, mitte ainult ümbritseval real. Rida oli 44 px,
   aga ankur ise kõigest ~18 px — puuteala on see, mis on KLIKITAV, mitte see,
   mis on tema ümber. Doktriin 8: kataloogis ja vormides ei tohi ükski
   puutesihtmärk jääda alla 44 px. */
.product-rating>a{
  display:inline-flex;align-items:center;flex-wrap:wrap;gap:4px 10px;
  min-height:44px;
  color:var(--ink-2);text-decoration:none;
}
.product-rating>a:hover{color:var(--green-3)}
.product-rating>a:hover .rating-value{color:var(--green-3)}
/* 🔴 MÕÕDETUD KITSAIMA KAARDI PEAL (`minmax(268px,1fr)` → 228 px sisu).
   18 px tärnid + number + „12 arvustust" andsid 240 px ja rida murdus kaheks.
   Murdunud rida ühel kaardil ja terve rida naaberkaardil = sama vale, mille
   miinimumkõrgused parandasid. 15 px tärn annab 217 px ja rida jääb terveks. */
.product .review-stars .star{width:15px;height:15px}
.product-rating .rating-value{
  font-weight:900;letter-spacing:-.02em;color:var(--ink);
  font-variant-numeric:tabular-nums;
}
.product-rating-count{color:var(--ink-3);font-size:var(--t-small)}
.product-rating.is-empty{color:var(--ink-3);font-size:var(--t-small)}

/* 🔴 HINNAJOON ALGAB IGAL KAARDIL SAMALT KÕRGUSELT — MÕÕDETUD, MITTE OLETATUD.
   1280 px juures: hind kaardil, millel on laoseisu rida, algas y=1042; kaardil,
   millel seda ei ole (`track_stock=0`), y=1073. 31 px vahe kõrvutistel kaartidel
   loeb kui joondusviga, mitte kui erinev sisu.
   Põhjus: `.product-desc{flex:1}` neelab võre venitatud kaardi ülejäägi, seega
   hinna kõrgus = kaardi põhi miinus nupp miinus laoseisu rida. Kui laoseisu rida
   puudub, tuleb tema kõrgus tagasi anda — mitte tühja elemendina markupis, vaid
   siin. `6px` on `.stock` ülemine marginaal, `1.62` on `body` reakõrgus. */
.product:not(:has(>.stock)) .price{margin-bottom:calc(6px + var(--t-small) * 1.62)}

/* Korvireal on „Eemalda" võre teises reas, esimeses veerus — ehk PILDI all.
   Ilma taandeta hakkab ta pildi vasakust servast ja näeb välja nagu pildi silt,
   mitte kui rea tegevus. Taane = pildi laius + vahe, sama arv mõlemas kohas. */
.cart-row:has(.cart-row-art) .cart-row-remove{margin-left:74px}

/* --- 41.4 TOOTELEHT: JALAJÄLG JA MÜÜJAKAART ------------------------------ */
/* Rada peab kattuma `BreadcrumbList` struktuurandmetega — otsingutulemus ja
   leht ei tohi lubada kahte eri asja. */
.crumbs{
  display:flex;flex-wrap:wrap;align-items:center;gap:2px 10px;
  margin:0 0 clamp(16px,2.4vw,24px);
  font-size:var(--t-small);color:var(--ink-3);
}
.crumbs-link{
  display:inline-flex;align-items:center;min-height:44px;
  color:var(--ink-2);font-weight:750;text-decoration:none;
}
.crumbs-link:hover{color:var(--green)}
.crumbs-sep{color:var(--line-2)}
.crumbs-here{
  min-width:0;max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  color:var(--ink-3);font-weight:650;
}

/* Müüja ei ole tabelirida (vt `sellerMeta()` põhjendust `product.ts`-is). */
.seller-card{
  display:flex;flex-wrap:wrap;align-items:center;gap:12px 16px;
  margin:0;padding:16px 18px;
  border-radius:var(--r-lg);
  background:linear-gradient(180deg,#fff,var(--green-mist));
  box-shadow:var(--hair),var(--shadow-1),var(--edge);
}
.seller-card .crest{--crest-size:46px}
.seller-card-text{flex:1 1 170px;min-width:0}
.seller-card-role{
  margin:0;font-size:var(--t-micro);font-weight:800;
  text-transform:uppercase;letter-spacing:.14em;color:var(--ink-3);
}
.seller-card-name{
  margin:3px 0 0;font-size:1.16rem;font-weight:850;letter-spacing:-.02em;
  color:var(--ink);line-height:1.25;overflow-wrap:anywhere;
}
.seller-card-reg{
  margin:2px 0 0;font-size:var(--t-small);color:var(--ink-2);
  font-variant-numeric:tabular-nums;
}
.seller-card-link{
  flex:none;display:inline-flex;align-items:center;gap:8px;
  min-height:44px;padding:0 16px;border-radius:var(--r-full);
  background:#fff;color:var(--green-3);
  font-size:var(--t-small);font-weight:800;text-decoration:none;
  box-shadow:var(--hair),var(--shadow-1);
  transition:box-shadow var(--base) var(--ease),color var(--fast) var(--ease);
}
.seller-card-link:hover{color:var(--green);box-shadow:inset 0 0 0 1.5px var(--green-2),var(--shadow-1)}
.seller-card-link .ico{width:17px;height:17px;color:var(--green-2)}

.product-trust{margin:0}

/* --- 41.5 KORVIRIDA: PILT, MITTE ARVERIDA -------------------------------- */
/* `:has()` on siin TAOTLUSLIK: reegel hakkab kehtima ainult siis, kui markupis
   on pilt olemas. Ilma pildita korvirida jääb täpselt selliseks, nagu ta oli
   osas 17 — see plokk ei tohi vana kuju katki teha. */
.cart-row-main:has(>.cart-row-art){
  display:flex;align-items:center;gap:14px;min-width:0;
}
.cart-row-text{min-width:0}
.cart-row-art{
  --art-tint:var(--green-mist);
  --art-deep:#E9F1E6;
  flex:none;display:grid;place-items:center;overflow:hidden;
  width:60px;height:60px;
  border-radius:var(--r-md);
  color:var(--green-3);
  background:
    radial-gradient(115% 88% at 26% 6%,rgba(255,255,255,.96),rgba(255,255,255,0) 58%),
    linear-gradient(158deg,var(--art-tint) 0%,var(--art-deep) 54%,var(--paper-3) 100%);
  box-shadow:var(--hair);
}
/* Joon on väiksemal pildil PAKSEM, mitte sama: 4 px joon 60 px pesas kaob
   halliks uduks. Sama joonis, sama kaal silmale. */
.cart-row-art svg{width:44px;height:auto}
.cart-row-art svg :is(path,circle,ellipse,line,polyline,polygon,rect){
  fill:none;stroke:currentColor;stroke-width:5.4;stroke-linecap:round;stroke-linejoin:round;
}

/* --- 41.6 KASSA KOKKUVÕTE: KELLELE SA ANDMED ANNAD ----------------------- */
.order-summary-seller{
  display:flex;align-items:center;gap:12px;
  margin:0 0 16px;padding-bottom:14px;
  border-bottom:1px solid var(--line);
}
.order-summary-seller .crest{--crest-size:38px}
.order-summary-seller-text{display:grid;min-width:0}
.order-summary-seller-text strong{
  font-size:1rem;font-weight:850;letter-spacing:-.015em;
  color:var(--ink);line-height:1.3;overflow-wrap:anywhere;
}
.order-summary-seller-text small{
  color:var(--ink-3);font-size:var(--t-small);
  font-variant-numeric:tabular-nums;
}

/* --- 41.7 MAKSELEHT: KELLELE JA KUI PALJU, ÜHEL PINNAL ------------------- */
.pay-seller{
  display:grid;grid-template-columns:minmax(0,1fr) auto;
  align-items:center;gap:18px clamp(20px,3vw,34px);
}
/* 🔴 `flex-start`, MITTE `center`. Keskjoondatuna maandus märk viierealise
   rekvisiidiploki KESKELE, ehk „Registrikood 16234512" kõrvale — nagu oleks ta
   selle rea juurde kuuluv ikoon. Märk kuulub NIME juurde. */
.pay-seller-id{display:flex;align-items:flex-start;gap:16px;min-width:0}
.pay-seller-id .crest{--crest-size:clamp(48px,7vw,58px)}
.pay-seller-id .party{min-width:0}
/* `.party-name` on osas 20 kõigil pindadel 1,15 rem. Makselehel on ta lehe
   `<h1>` ja vastus lehe peamisele küsimusele — ta ei tohi olla sama suur, mis
   kviitungi külgveeru silt. */
.pay-seller-id .party-name{
  font-size:clamp(1.3rem,2.6vw,1.7rem);line-height:1.18;
  overflow-wrap:anywhere;
}
.pay-amount{margin:0;display:grid;justify-items:end;gap:3px;text-align:right}
.pay-amount-label{
  font-size:var(--t-micro);font-weight:800;
  text-transform:uppercase;letter-spacing:.14em;color:var(--ink-3);
}
.pay-amount-value{
  font-size:clamp(1.9rem,5vw,2.5rem);font-weight:900;
  letter-spacing:-.04em;line-height:1;color:var(--ink);
  font-variant-numeric:tabular-nums;white-space:nowrap;
}
.pay-trust{margin:18px 0 0}

/* --- 41.8 KINNITUS: LINNUKE ON JOONIS, MITTE GLÜÜF ----------------------- */
/* Tee kogupikkus on ~38 ühikut; `40` katab ka ümarad otsad. Joonistumine algab
   pärast `.success-mark` pulssi (260 ms), nii et märk PAISUB kõigepealt ja
   linnuke tõmmatakse sisse — kaks liigutust ühes suunas, mitte kaks korraga. */
.success-mark .success-check{
  width:58%;height:auto;
  stroke-dasharray:40;stroke-dashoffset:40;
  animation:check-draw 520ms var(--ease) 260ms forwards;
}
@keyframes check-draw{to{stroke-dashoffset:0}}

.success-seller{display:flex;align-items:center;justify-content:center;gap:12px}
/* Roheline märk rohelisel pinnal kaoks. Tumedal pinnal on ta klaas, mitte värv. */
.success .crest{
  --crest-size:34px;
  background:rgba(255,255,255,.16);
  color:#fff;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.36);
}

/* --- 41.9 KVIITUNG: SEISUND ON DOKUMENDI TÄHTSAIM VÄLI ------------------- */
.receipt-party{display:flex;align-items:flex-start;gap:14px;min-width:0}
.receipt-party .crest{--crest-size:44px}

.receipt-status{
  display:inline-flex;align-items:center;gap:9px;
  margin:12px 0 0;padding:6px 15px 6px 12px;
  border-radius:var(--r-full);
  font-size:var(--t-small);font-weight:850;
  font-variant-numeric:tabular-nums;
  print-color-adjust:exact;-webkit-print-color-adjust:exact;
}
/* Täpp kannab sama värvi, mis tekst: seisund ei ole KUNAGI ainult värv, ta on
   alati ka sõna („Tasutud 13.08.2026" / „Makset ei toimunud"). Sama reegel,
   mis osas 30 arvustuste tärnidel. */
.receipt-status::before{
  content:"";flex:none;width:8px;height:8px;border-radius:50%;
  background:currentColor;
}
.receipt-status.is-paid{
  background:var(--green-pale);color:var(--green-3);
  box-shadow:inset 0 0 0 1px rgba(11,107,46,.22);
}
.receipt-status.is-test{
  background:var(--amber-pale);color:var(--amber);
  box-shadow:inset 0 0 0 1px var(--amber-line);
}

/* --- 41.10 TELEFON ------------------------------------------------------- */
@media (max-width:620px){
  /* Summa kõrvuti nimega jätaks 375 px juures mõlemale poole 150 px. Üksteise
     all on nimi terve rida ja summa terve rida — ja joon nende vahel ütleb,
     et need on kaks eri asja, mitte üks katkine lõik. */
  .pay-seller{grid-template-columns:1fr}
  .pay-amount{
    justify-items:start;text-align:left;
    padding-top:14px;border-top:1px solid var(--line);
  }
  .cart-row-art{width:52px;height:52px}
  .cart-row-art svg{width:38px}
  .cart-row-main:has(>.cart-row-art){gap:12px}
  .cart-row:has(.cart-row-art) .cart-row-remove{margin-left:64px}
}
@media (max-width:480px){
  /* Poolikult reale mahtuv nupp loeb kui ülevool. Terve rida loeb kui valik. */
  .seller-card-link{width:100%;justify-content:center}
}

/* --- 41.11 PRINT --------------------------------------------------------- */
@media print{
  /* Ostu ARGUMENDID ei kuulu kviitungile — kviitung on tõend, mitte müügileht. */
  .trust-row,.shop-score,.product-rating{display:none}
  /* Vari ei prindi kunagi hästi: ta muutub halliks plekiks. Pind ja tekst
     jäävad, sügavus kaob — täpselt nagu `.receipt`-il osas 27. */
  .crest{box-shadow:none}
  /* Kastiraam asendab varju, et märgis oleks eristatav ka ilma taustavärvita
     (mõni brauser trükib `print-color-adjust`-ist hoolimata värvid välja). */
  .receipt-status{box-shadow:none;border:1px solid currentColor}
}

/* --- 41.12 VÄHENDATUD LIIKUMINE ----------------------------------------- */
/* 🔴 OSA 28 ÜLDPLOKIST EI PIISA JA SEE ON MÕÕDETUD, MITTE TEOREETILINE.
   Üldplokk nullib KESTUSE, aga mitte VIIVITUSE. `check-draw` viivitus on
   260 ms — vähendatud liikumise režiimis oleks linnuke veerand sekundit
   NÄHTAMATU (dashoffset 40) ja alles siis kohal. Just see hüpe on asi, mille
   pärast inimene selle seade sisse lülitas. Siin ta on kohe kohal.
   Sama leping, mis osades 37 ja 40.9: iga uus nimeline animatsioon on siin
   kirjas ja igal ühel on määratud, mis alles jääb. */
@media (prefers-reduced-motion:reduce){
  .success-mark .success-check{animation:none;stroke-dashoffset:0}
}

/* --- 41.2 TELEFON: NIMI EI VÕISTLE OLEKUMÄRGISEGA ----------------------- */
/* 🔴 MÕÕDETUD 375 px JUURES. Osa 32 rida on kolm veergu: nimi (1fr) · olek
   (auto) · summa (auto). Lauaarvutis mahub. Telefonis võtavad „Makstud"-pill
   (110 px) ja „24,50 €" (85 px) ära 195 px 355-st ja nimele jääb 150 px:
     „Kertu Õunapuu-        [Ootel]   8,90 €
      Vahtramäe"
     „10:02 · E-pood ·
      #2"
   Ostja nimi murdus kaheks reaks JA märkus murdus kaheks reaks — kaks rida
   teksti kolmes kitsas veerus loeb TABELINA, mitte nimekirjana. Täpselt see,
   mille Martti ette heitis.

   Parandus on VEERGUDE ARV, mitte kirjasuurus. Kaks veergu, kaks rida:
     rida 1: nimi ................................ summa
     rida 2: kellaaeg · kanal · viide ............ olek
   Nimi saab terve laiuse, summa jääb paremale (raha joondub kogu failis
   paremale), ja olek langeb sinna, kuhu ta kuulub — konteksti juurde.

   🔴 SELEKTOR ON `.tape-orders`, MITTE `.pos-tape`. `.pos-tape` on jagatud:
   kassa ostukorv (`src/routes/haldus-kassa.ts`) kasutab sama linti kogusenupu
   ja summaga ning tema kolmas veerg PEAB alles jääma. Ümberpaigutus kehtib
   ainult tellimuste lindile. */
@media (max-width:620px){
  .tape-orders>li:not(.tape-day){
    grid-template-columns:minmax(0,1fr) auto;
    column-gap:12px;
  }
  .tape-orders>li>.tape-name{grid-column:1;grid-row:1}
  .tape-orders>li>.tape-sum{grid-column:2;grid-row:1;align-self:center}
  .tape-orders>li>.tape-note{grid-column:1;grid-row:2}
  /* Märgis on rea TEINE peategelane ja ta joondub summa alla. `justify-self`
     hoiab pilli oma laiusega — venitatud pill loeks nupuna. */
  .tape-orders>li>.status{grid-column:2;grid-row:2;justify-self:end;align-self:center}
}

/* --- 41.13 KVIITUNGI TABEL 375 px JUURES -------------------------------- */
/* 🔴 MÕÕDETUD ÜLEVOOL, MITTE ETTEVAATUS. 375 px vaateaknas oli
   `.receipt-table` sisemine miinimumlaius 367 px, aga kviitungi sisulaius
   375 − 2×26 = 323 px. 44 px läks üle serva ja doktriin 6 ütleb: null
   horisontaalset ülevoolu 375 px juures.

   Süüdlane on üldine `th,td{padding:15px 12px}` (osa 7): neli veergu × kaks
   külge = 96 px paljast polstrit 323 px peal. Lahendus EI OLE kerimiskast —
   kviitung on DOKUMENT ja horisontaalselt keritav dokument ei ole loetav ega
   prinditav. Lahendus on polster ja kirjasuurus: äärmised veerud loobuvad
   välimisest polstrist täielikult (nad on niikuinii kviitungi serva vastas) ja
   arvud lähevad ühe astme väiksemaks. Rahaveerg jääb tabelnumbritega joondatuks,
   sest `font-variant-numeric` tuleb osast 2 ega sõltu suurusest. */
@media (max-width:560px){
  .receipt-table :is(th,td){padding:12px 7px;font-size:var(--t-small)}
  .receipt-table :is(th,td):first-child{padding-left:0}
  .receipt-table :is(th,td):last-child{padding-right:0}
  /* Päiserida on juba `--t-micro`; tema tähevahe on see, mis „ÜHIKUHIND"
     kolmandiku laiemaks teeb. */
  .receipt-table thead th{letter-spacing:.04em}
  .receipt-table tfoot th{font-size:1.05rem}
}

/* ═══════════════════════════════════════════════════════════════════════════
   42. KASSA MAKSENUPP EI TOHI JÄÄDA NAVI ALLA  (ülevaatuse parandus)
   ═══════════════════════════════════════════════════════════════════════════

   🔴 MÕÕDETUD 375 × 812 px JUURES, MITTE ETTEVAATUSEST.
   `.app-side.pos-checkout` on osas 35 `position:sticky;bottom:0`, ehk ta
   kleepub VAATEAKNA põhja. `.admin-nav` on `position:fixed;bottom:0` ja
   88 px kõrge, `z-index:80` vs paneeli 30. Tulemus enne parandust:

     „Võta makse" nupp   y = 664 … 752
     navi ülemine serv   y = 724
     → nupu alumine 28 px oli navi ALL.

   See on müüja kassa AINUS lõpetav tegevus. Kaetud nupp ei ole kosmeetiline
   viga: pöidlaga vajutus rea 724…752 peale avab hoopis navi ja müüja jääb
   turuletil ostja ees seisma. Piirang 9 („kleepuv nav ei tohi katta sisu")
   on kirjutatud jaluse kohta, aga maksenupp on sellest kallim.

   Nihe on `88px + safe-area`, sest nav ise polsterdab põhja
   `env(safe-area-inset-bottom)`-ga (osa 25) — ilma selle liidendita jääks
   iPhone'i kodujoone kõrgune riba puudu.

   Piiritlus on `:has(.admin-nav)`, mitte paljas `.pos-checkout`, sest nihke
   PÕHJUS on nav. Kui kass avaneb kunagi kestas ilma navita, ei tohi paneel
   jätta 88 px tühja triipu. (Ühtlasi eeldab see, et nav on kestas SEES — vt
   `src/lib/admin-shell.ts` LOGOUT_FORM: pesastatud vorm viskas ta varem
   `<body>` alla ja see selektor ei oleks siis kehtinud.)

   REEGEL ISE ON KOLINUD OSASSE 35. Mõõtmine ja põhjendus kehtivad muutumatult,
   aga sihtmärk on nüüd `.pos-total` — pärast seda, kui kleepuv sai olla ainult
   summariba, mitte kogu kasvav `<aside>`. Nihutamist vajab see, mis kleepub.
   ------------------------------------------------------------------------ */

/* 43. PÄRIS LETIKASSA — makseviisi valik ja tühi korv.
   ------------------------------------------------------------------------
   Siin oli varem ka `.pos-search`, `.pos-product-copy` ja `.pos-quantity`.
   Kõik kolm olid kirjutatud markup'i peale, mida enam ei renderdata (otsingu
   ümbris `<div>`, eraldi tekstitulp, 88+88 px kogusenupud). `grep` kinnitab:
   `pos-product-copy` ja `pos-quantity` ei esine üheski mallis. Kaks neist ei
   olnud isegi vaikselt surnud — `.pos-search label{display:block}` ja
   `.pos-search .button{min-height:52px}` tegid ekraanilugeja-sildi ja
   peidetud otsingunupu NÄHTAVAKS. Otsinguriba päris kuju on all osas 44. */
.payment-choice-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin:24px 0}
.payment-choice-grid .button{min-height:112px;display:grid;align-content:center;gap:6px}
.payment-choice-grid .button span{font-size:var(--t-small);font-weight:650}

@media (max-width:560px){
  .payment-choice-grid{grid-template-columns:1fr}
}

/* Siin oli sama 560 px plokk TEIST KORDA, sõna-sõnalt — ainult ilma
   `.pos-cart-line` ridadeta ja ilma `border-radius`-ita, ehk range alamhulk
   osast 44. Ta oli kirjutatud „teadlikult hiljemaks", et võita vana
   `.pos-product{grid-template-columns:…206px}` reeglit. See vastane on nüüd
   kustutatud, seega kadus ka koopia ainus põhjus. Kaks identset plokki ühe
   reegli peale tähendab, et järgmine parandus tehakse ühte neist. */

/* ==========================================================================
   41. TEEKOND MAKSELAHENDUSENI — `/haldus/alustamine` ja töölaua valmiduse kaart
   --------------------------------------------------------------------------
   Martti 16.08.2026: „see peab olema väga informatiivne ning aitama läbi
   terve protsessi."

   🔴 KOGU TEE ON KORRAGA NÄHA JA LAHTI ON TÄPSELT ÜKS SAMM. Kaks lahtist
   sammu on kaks kutset ja müüja teeb siis kumbagi pooleldi; null lahtist on
   nimekiri, mitte juhend. Tehtud samm kahaneb üheks reaks, aga EI KAO —
   nähtav tehtud töö on ainus koht, kus müüja näeb, kui palju ta juba tegi.
   ========================================================================== */

/* --- Edenemisriba ---------------------------------------------------------
   🔴 LAIUS TULEB KLASSIST, MITTE `style=""`-ist. CSP `style-src 'self'` tapab
   inline-stiilid ja erandit ei tehta (UX-SPETS §6). Seitse klassi ≈ 120 baiti;
   number on ka TEKSTIS, sest 165 px laiusel on riba üksi loetamatu. */
.valmidus-riba{display:flex;align-items:center;gap:14px;margin:0 0 26px}
.valmidus-taht{
  flex:1 1 auto;height:10px;border-radius:999px;
  background:var(--paper-2);box-shadow:var(--hair);overflow:hidden;
}
.valmidus-tais{
  display:block;height:100%;border-radius:999px;
  background:linear-gradient(90deg,var(--green-2),var(--green));
  transition:width var(--slow) var(--ease);
}
.taidetud-0{width:0}
.taidetud-1{width:16.6%}
.taidetud-2{width:33.3%}
.taidetud-3{width:50%}
.taidetud-4{width:66.6%}
.taidetud-5{width:83.3%}
.taidetud-6{width:100%}
.valmidus-arv{margin:0;flex:0 0 auto;color:var(--ink-2);font-size:var(--t-small)}
.valmidus-arv strong{color:var(--ink);font-variant-numeric:tabular-nums}

/* --- „Müüa saad juba praegu" ----------------------------------------------
   See plokk on ENNE samme ja see on tahtlik. Müüja esimene küsimus ei ole
   „mis on samm 1", vaid „kas ma saan juba raha teenida". Vastus on jah ja ta
   ei tohi olla üheksa sammu taga. */
.alusta-kohe{
  margin:0 0 26px;padding:20px 22px;
  border-radius:var(--r-lg);
  background:linear-gradient(180deg,var(--card),var(--green-mist));
  box-shadow:var(--hair),var(--shadow-1);
}
.alusta-kohe h2{font-size:var(--t-h3);margin:0 0 8px}
.alusta-kohe p{margin:0 0 8px}
.alusta-kohe .actions{margin-top:14px}

/* --- Järgmine samm, tõstetud välja ---------------------------------------- */
.jargmine-samm{
  margin:0 0 30px;padding:22px;
  border-radius:var(--r-lg);
  background:var(--card);
  box-shadow:inset 0 0 0 2px var(--green),var(--shadow-2);
}
.jargmine-samm h2{font-size:var(--t-h3);margin:.15em 0 10px}
.jargmine-samm p{margin:0}
.jargmine-samm .actions{margin-top:16px}

.faasi-pealkiri{font-size:var(--t-h3);margin:30px 0 6px}
.faasi-selgitus{margin:0 0 16px;color:var(--ink-2);font-size:var(--t-small);line-height:1.6}

/* --- Sammuloend -----------------------------------------------------------
   `<ol>` ilma numbriteta: järjekord ON semantiline (LHV p 4.4–4.6 on
   järjestus), aga oma number kõrval marker­veerus oleks kaks loendurit. */
.sammud{list-style:none;margin:0 0 10px;padding:0;display:grid;gap:10px}
.samm{
  display:grid;grid-template-columns:32px 1fr;gap:14px;
  padding:16px 18px;border-radius:var(--r-lg);
  background:var(--paper-2);box-shadow:var(--hair);
}
.samm-marker{
  display:flex;align-items:center;justify-content:center;
  width:32px;height:32px;border-radius:999px;
  background:var(--card);box-shadow:var(--hair);
  font-weight:800;line-height:1;color:var(--ink-3);
}
.samm-sisu{min-width:0}
.samm-pealkiri{font-size:1rem;margin:.35em 0 0;color:var(--ink)}
.samm-miks,.samm-saavutus{margin:8px 0 0;font-size:var(--t-small);line-height:1.6;color:var(--ink-2)}
.samm-tegevus{margin:16px 0 0}
.samm-tegevus .button{min-height:56px}

/* Tehtud: roheline märk, vaiksem kaart. Seisundivärv EI OLE kunagi ainus
   signaal (UX-SPETS §7.1) — ✓ ja tekst käivad alati kaasas. */
.samm-tehtud .samm-marker{background:var(--green);color:#fff;box-shadow:none}
.samm-tehtud .samm-pealkiri{color:var(--ink-2)}

/* Järjekorras: ainus kaart, mis on lahti, ja ainus, mis kannab ääre. */
.samm-jarjekorras{background:var(--card);box-shadow:inset 0 0 0 2px var(--green),var(--shadow-1)}
.samm-jarjekorras .samm-marker{background:var(--green);color:#fff;box-shadow:none}
.samm-jarjekorras .samm-pealkiri{font-size:1.06rem;font-weight:800}

/* Teiste käes: pall ei ole müüja käes. Ei spinnerit, ei „ootel" —
   UX-SPETS §3.11 keelab mõlemad. Punktiirjoon ütleb „pooleli" ilma sõnata. */
.samm-teiste_kaes{background:var(--card);box-shadow:inset 0 0 0 2px var(--line)}
.samm-teiste_kaes .samm-marker{background:var(--paper-2)}

/* Ootab: kahvatum, ilma nuputa — tal ei ole veel midagi teha. */
.samm-ootab{opacity:.72}

.alusta-abi{margin:26px 0 0;padding-top:18px;border-top:1px solid var(--line)}
.alusta-abi h2{font-size:var(--t-h3);margin:0 0 6px}
.alusta-abi p{margin:0;color:var(--ink-2)}

@media (max-width:520px){
  .samm{grid-template-columns:26px 1fr;gap:10px;padding:14px}
  .samm-marker{width:26px;height:26px;font-size:.85rem}
}

/* --- Sammuekraani vorm ----------------------------------------------------
   Onboardingu sammul on ALATI täpselt üks edasiviiv tegevus ja ta peab välja
   nägema nagu edasiviiv tegevus: sama laius ja sama kõrgus, mis liitumisvormi
   nupul. 187 px lai nupp keset lehte loeb valikuna, mitte teena. */
.samm-vorm .field+.field{margin-top:18px}
.samm-vorm .field-input{min-height:56px}
.samm-vorm .micro{margin:6px 0 0}
.samm-vorm .field-error{margin:6px 0 0}
.samm-vorm .choice+.choice{margin-top:10px}
.samm-vorm>.button{width:100%;min-height:64px;margin-top:24px;font-size:1.05rem}

/* Saatmise tingimused on alati nähtavad — JS-i ei ole ja väljade peitmine
   tähendaks, et JS-ita brauseris ei saa neid üldse täita (doktriin §1). */
.tarne-tingimused{margin-top:18px;padding-left:16px;border-left:3px solid var(--line)}
/* Õigusdokument on LUGEMISEKS, mitte skannimiseks: kitsas mõõt ja hõre rida. */
.legaldoc{width:min(680px,100%);margin-inline:auto}
.legaldoc h1{font-size:var(--t-h2);margin:.1em 0 20px}
.legaldoc h2{font-size:var(--t-h3);margin:30px 0 8px}
.legaldoc p{margin:0 0 12px;line-height:1.7}
.legaldoc>.micro{margin-top:30px;padding-top:16px;border-top:1px solid var(--line)}
/* Juhise sammud on NUMBRIGA loend, mitte täpid: järjekord on siin sisuline
   (LHV p 4.4–4.6) ja number on ainus asi, mis seda ütleb. */
.juhis{margin:0 0 20px;padding-left:24px;display:grid;gap:14px}
.juhis li{line-height:1.6}
.juhis .button{margin-top:8px}
/* Callback-aadress peab olema VALITAV ja TERVIKUNA NÄHTAV.

   🔴 SEE ON AINUS STRING KOGU TOOTES, KUS ÜKS PUUDUV MÄRK TÄHENDAB MAKSEID,
   MIS EI TULE KUNAGI — ja tema viga on VAIKNE: makse läheb pangas läbi, raha
   liigub, ja ainult müüja ekraan jääb maksmata tellimuse peale seisma.

   Esimene versioon kasutas `white-space:nowrap` + `overflow-x:auto`. Telefonis
   mõõdetuna oli tulemus see, et aadressist paistis ligikaudu pool ja ülejäänu
   oli horisontaalse kerimise taga. Ilus, ja vale: müüja ei saa kontrollida,
   kas ta kleepis terve rea, kui ta ei näe terve rida.

   `break-all` murrab suvalisest kohast — see on siin ÕIGE, sest URL-il ei ole
   sõnapiire, mida austada. `user-select:all` hoiab ühe klõpsuga valimise
   alles, ehk mugavus ei kao. */
.callback-url{margin:0 0 16px;padding:14px 16px;border-radius:var(--r-lg);
  background:var(--paper-2);box-shadow:var(--hair)}
.callback-url code{
  font-size:.95rem;line-height:1.55;
  word-break:break-all;overflow-wrap:anywhere;
  user-select:all;
}

/* ==========================================================================
   42. PLATVORMI OMANIKU PANEEL — `/platvorm`
   --------------------------------------------------------------------------
   Martti 16.08.2026: „tee platvormi omaniku admin paneel ka."

   🔴 SIIN EI KEHTI MÜÜJA KESTA REEGLID JA SEE ON TAHTLIK. 88 px puuteala,
   ≥7:1 kontrast ja alumine navi tulevad turuleti kontekstist: märjad käed,
   päike, üks pöial. Platvormi omanik istub laua taga ja võrdleb kümmet rida
   korraga — seal mahutab 88 px rida kuus müüjat ja alumine navi varjab tabeli
   lõppu. Sama kest kahele tööle teeniks kumbagi halvasti.

   🔴 TUME RIBA ON TURVAOMADUS, MITTE KAUNISTUS. Omanik on ka müüja; kaks rolli,
   üks sisselogimine, üks brauser. Kui ekraanid näeksid ühesugused välja, oleks
   „kelle andmeid ma vaatan" mälu küsimus — ja mälu eksib. Sama roll, mis
   testrežiimi ribal kassas.
   ========================================================================== */

.plat-shell{min-height:100dvh;display:flex;flex-direction:column;background:var(--bg)}

/* Riba ei keri ära: ta vastab „kelle andmeid ma vaatan" enne sisu. */
.plat-bar{
  position:sticky;top:0;z-index:20;
  display:flex;align-items:center;gap:18px;flex-wrap:wrap;
  padding:10px var(--gutter);
  background:var(--ink);color:#fff;
}
.plat-mark{
  font-size:var(--t-micro);font-weight:800;letter-spacing:.14em;
  padding:4px 10px;border-radius:999px;
  background:rgba(255,255,255,.14);
}
.plat-nav{display:flex;gap:4px;flex:1 1 auto;flex-wrap:wrap}
.plat-nav a{
  display:inline-flex;align-items:center;min-height:36px;padding:0 12px;
  border-radius:8px;color:rgba(255,255,255,.72);
  font-size:var(--t-small);font-weight:700;text-decoration:none;
}
.plat-nav a:hover{color:#fff;background:rgba(255,255,255,.1)}
.plat-nav a[aria-current="page"]{color:var(--ink);background:#fff}
.plat-nav a:focus-visible{outline:2px solid #fff;outline-offset:2px}
.plat-tagasi{color:rgba(255,255,255,.72);font-size:var(--t-small);font-weight:700;text-decoration:none}
.plat-tagasi:hover{color:#fff}

.plat-head{
  display:flex;align-items:baseline;justify-content:space-between;gap:16px;flex-wrap:wrap;
  padding:22px var(--gutter) 0;
}
.plat-head h1{font-size:var(--t-h2);margin:0}
.plat-head-actions{display:flex;gap:8px;flex-wrap:wrap}

.plat-main{flex:1 1 auto;padding:18px var(--gutter) 40px;min-width:0}

/* --- Numbriplaadid --------------------------------------------------------
   Ülevaate esimene rida. `auto-fit` hoiab nad ühel real laual ja murrab
   telefonis ise — meediapäringut ei ole vaja. */
.plat-plaadid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));margin:0 0 24px}
.plat-plaat{padding:16px 18px;border-radius:var(--r-lg);background:var(--card);box-shadow:var(--hair),var(--shadow-1)}
.plat-plaat dt{margin:0 0 6px;color:var(--ink-2);font-size:var(--t-small);font-weight:700}
.plat-plaat dd{margin:0;font-size:1.6rem;font-weight:800;font-variant-numeric:tabular-nums;line-height:1.1}
/* Plaat, mis nõuab tegevust, kannab ääre — mitte ainult teist värvi. */
.plat-plaat.on-tegevus{box-shadow:inset 0 0 0 2px var(--green),var(--shadow-1)}

/* --- Tabel ----------------------------------------------------------------
   🔴 KERIB HORISONTAALSELT AINULT TABEL, MITTE LEHT. Doktriin: telefonis ei
   tohi olla lehe horisontaalset kerimist. Mähis annab tabelile oma kerimise
   ja `min-width` hoiab veerud loetavana. */
.plat-tabel-wrap{overflow-x:auto;border-radius:var(--r-lg);background:var(--card);box-shadow:var(--hair),var(--shadow-1)}
.plat-tabel{width:100%;min-width:640px;border-collapse:collapse;font-size:var(--t-small)}
.plat-tabel th,.plat-tabel td{padding:11px 14px;text-align:left;border-bottom:1px solid var(--line)}
/* 🔴 KLEEPUVAT PÄIST SIIN EI OLE, JA SEE ON MÕÕDETUD OTSUS.
   `position:sticky` positsioneerib SISALDUSKASTI suhtes, ja tema
   sisalduskast on `.plat-tabel-wrap`, millel on `overflow-x:auto`. Tulemus oli
   nähtav viga: `top:56px` lükkas päise 56 px ALLAPOOLE ja tabeli kohale jäi
   tühi valge riba. Ja isegi õige nihkega ei teeks ta midagi — mähis ei keri
   VERTIKAALSELT, ehk päisel ei ole millegi külge kleepuda.
   Horisontaalne kerimine mähises on tähtsam: doktriin keelab LEHE
   horisontaalse kerimise telefonis, ja tema hind on kleepuv päis. */
.plat-tabel thead th{
  background:var(--paper-2);color:var(--ink-2);
  font-size:var(--t-micro);font-weight:800;letter-spacing:.04em;text-transform:uppercase;
}
.plat-tabel tbody tr:last-child td{border-bottom:0}
.plat-tabel tbody tr:hover{background:var(--paper-2)}
.plat-tabel a{font-weight:700}
.plat-arv{font-variant-numeric:tabular-nums;white-space:nowrap}
.plat-tabel td:has(.plat-arv){text-align:right}
.plat-tyhi{margin:0;padding:26px;color:var(--ink-2);text-align:center}

/* --- Seisumärk ------------------------------------------------------------
   Värv ei ole kunagi ainus signaal — sõna on alati sees. */
.plat-seis{
  display:inline-block;padding:3px 9px;border-radius:999px;
  font-size:var(--t-micro);font-weight:800;white-space:nowrap;
}
.plat-seis-review{background:var(--amber-pale);color:var(--amber)}
.plat-seis-active{background:var(--green-mist);color:var(--green-3)}
.plat-seis-draft{background:var(--paper-2);color:var(--ink-2)}
.plat-seis-suspended{background:var(--amber-pale);color:var(--amber)}
.plat-seis-closed{background:var(--paper-2);color:var(--ink-3);text-decoration:line-through}

/* --- Filtririba ----------------------------------------------------------- */
.plat-filter{display:flex;gap:6px;flex-wrap:wrap;margin:0 0 16px}
.plat-filter a{
  display:inline-flex;align-items:center;min-height:36px;padding:0 14px;
  border-radius:999px;background:var(--card);box-shadow:var(--hair);
  font-size:var(--t-small);font-weight:700;text-decoration:none;color:var(--ink-2);
}
.plat-filter a[aria-current="page"]{background:var(--ink);color:#fff;box-shadow:none}

/* --- Ühe müüja kaart ------------------------------------------------------ */
.plat-kaardid{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}
.plat-kaart{padding:18px 20px;border-radius:var(--r-lg);background:var(--card);box-shadow:var(--hair),var(--shadow-1)}
.plat-kaart h2{font-size:var(--t-h3);margin:0 0 12px}
.plat-kaart dl{display:grid;grid-template-columns:auto 1fr;gap:7px 16px;margin:0}
.plat-kaart dt{color:var(--ink-2);font-size:var(--t-small)}
.plat-kaart dd{margin:0;font-weight:700;overflow-wrap:anywhere}
.plat-kaart form{margin-top:14px}
.plat-kaart .button{width:100%;min-height:48px}

/* 🔴 OHTLIK TEGEVUS ON `<details>` TAGA, MITTE NUPP NUPU KÕRVAL. Poe
   sulgemine ja avamine ei tohi olla ühe eksinud klõpsu kaugusel teineteisest. */
.plat-ohtlik{margin-top:14px;border-radius:var(--r-lg);background:var(--paper-2);box-shadow:var(--hair)}
.plat-ohtlik>summary{
  min-height:44px;display:flex;align-items:center;padding:0 16px;cursor:pointer;
  font-size:var(--t-small);font-weight:700;color:var(--ink-2);
}
.plat-ohtlik>summary::-webkit-details-marker{display:none}
.plat-ohtlik>div{padding:0 16px 16px}

@media (max-width:620px){
  .plat-head{padding-top:16px}
}
