# PDP EcoSystem — UI rules for AI assistants (PDP Design System v0.6, brand "ecosystem")

You write UI for PDP EcoSystem, the parent brand of PDP Academy, PDP Online, PDP University, PDP School and PDP Junior. Follow these rules exactly. If a request conflicts with a rule, follow the rule and say which rule you kept. Tokens: https://design.pdp.uz/ds/tokens/ecosystem.css (CSS custom properties) or https://design.pdp.uz/ds/tokens/ecosystem.json (W3C DTCG). Load one token file only.
The system is based on Untitled UI: structure, sizes, variants, states and token names come from Untitled UI (with the --eco- prefix); colours, fonts and the logo are EcoSystem's.

## Mode
- Products are light-first: for a product screen the light mode is the default. Set data-theme="light" on <html> — bare :root is the dark mode.
- Dark is the supported alternative, not the product default: leave data-theme off (or set "dark") for brand surfaces — hero, covers, the brand book — and when the user asks for dark.
- Light: page background #FFFFFF, brand fill green #00B533 with white text. Dark: page background #141414, brand fill lime with black text. All semantic tokens switch; component CSS stays the same.
- Every component works in both modes. Never hard-code colours in components; use var(--eco-*).

## Brand colours (fixed, from the brand book)
- Vivid Malachite #00C508 (--eco-color-malachite): brand green — the mark, decoration and brand graphics.
- Button color #00B533 (--eco-color-malachite-button): every green component fill in UI — light-mode brand fill, primary button, checked controls, solid badge, brand band.
- Black #141414 (--eco-color-black): backgrounds and text.
- Bitter Lime #BDFF00 (--eco-color-lime): dark-mode brand fill (primary button, links, focus ring).
- Green: Done #00A603 (--eco-color-green-done): all green text in the light mode — section eyebrows, card titles, labels and links (--eco-text-brand-secondary); 3.25:1 on #FFFFFF, 2.98:1 on #F5F5F5 — art director exception (05.10.2026). Never a fill: green fills stay #00B533 with white text.
- Gradient --eco-gradient: #F2FFC7 0%, #BDFF00 22%, #00C508 58%, #013A04 100%; every stop has its own token --eco-gradient-stop-1…4 (the gradient is built from them). Brand moments only, never behind body text.
- Primitive scales (25, 50, 100…900, 950): --eco-color-green-*, --eco-color-lime-*, --eco-color-neutral-*, --eco-color-error-*, --eco-color-warning-*. Components use semantic tokens, not primitives.
- No black text or marks on a green fill (brand decision 30.09.2026): text and marks on green are white #FFFFFF. Text on lime fills is ALWAYS black #141414 (15.3:1).
- Exception: white text on green fills (#00B533) — brand decision (30.09.2026): no black text or marks on a green fill, contrast 2.7:1. Every green component fill (primary button, checked checkbox and switch, solid badge, brand band, success call to action) is #00B533 with white text and marks: EcoSystem light mode, Academy, Online. Take the colour from the tokens (--eco-text-primary_on-brand, --eco-brand-on-*), never hard-code it. Black on green appears only in SMM designs and large banners, never in UI.
- Exception: the selected tab label is pure black or pure white exactly as in the design (user decision 30.09.2026), for every brand, even below 4.5:1 (white on the University teal pill). Unselected tab labels are black at 70 % (white at 70 % in the dark mode). Take them from --eco-tab-label, --eco-tab-label-strong and --eco-tab-*-fg, never hard-code them.
- Exception: white text on teal fills in PDP University — brand decision (30.09.2026): no black text or marks on a teal fill, contrast 3.05:1. Every teal component fill (primary button, checked checkbox and switch, solid badge, brand band) takes white text and marks through the tokens (--eco-text-primary_on-brand, --eco-brand-on-*); the yellow accent keeps black text. Black on teal appears only in media and SMM designs, never in UI.
- Never lime text on white or light surfaces (1.2:1). Never #00C508 as text on white (2.3:1).
- Light mode: brand text = --eco-text-brand-tertiary and links = --eco-text-brand-secondary, both Green: Done #00A603 (3.25:1 on white, 2.98:1 on the #F5F5F5 grey surface — art director exception, 05.10.2026); link hover green-900. Green-700 #048307 stays for borders and the focus ring, never for text.

## Distinction colours — these are NOT brand accents
- There is no separate working palette: the old PDP Portal 2025 working-colour scales were removed (01.10.2026). Only colours the designer gave tell things apart.
- Chart series: --eco-chart-2…6 (see Charts). Category badges: --eco-cat-{black|green|blue|teal|red} through .eco-badge--cat-* (the diversity set; avatars do not use it). The key names are slots: in EcoSystem the set is text colour, green, dark green, grey and lime, and the board / calendar / tag dots --eco-board-1…6 (text on the fill --eco-board-ink-1…6) are green, black (white in Dark), grey, light green, dark green and lime — no blue, cyan, teal, yellow or red. Callout tones: .eco-callout--tip (green), --warning (orange), --note (teal), --important (purple), colours from the callout frame.
- A distinction colour NEVER becomes a button, a link, a focus ring or a status (success, warning, error). Those stay brand (lime/malachite) and the status scales. The category green and red look like status colours: a category badge never gets a dot and always carries a word.
- Brand colours keep their jobs unchanged: accent, primary action, link, focus, brand surfaces.
- Contrast still applies: text on a category tint ≥ 4.5:1 (the components mix the colour toward black in the light mode and toward white in the dark mode), marks and borders ≥ 3:1, in both modes.
- Product surfaces (page, card, divider) come from --eco-color-neutral-* and the project's light grey surface --eco-color-surface (--eco-bg-secondary in the light mode; currently neutral #F5F5F5 in every project, each project will get its own later) through the semantic tokens, never from a distinction colour.
- Light mode hover, active, disabled and tertiary backgrounds (--eco-bg-primary_hover, --eco-bg-active, --eco-bg-secondary_hover, --eco-bg-tertiary, --eco-bg-disabled) are hue-less greys derived from --eco-color-surface (--eco-color-surface-active, -hover, -tertiary; currently #F7F7F7, #E6E6E6, #E6E6E6, and #F5F5F5 for disabled). Never use the green-tinted neutral-50/100/200 steps as a light background; they stay for text, icons and borders.

## Charts
- Categorical series in a fixed order: --eco-chart-1, -2, -3, -4, -5, -6. Series 1 always takes chart-1 (the brand). Series 2–6 are the brand's OWN colours plus near-black/near-white and greys (art director, 05.10.2026) — EcoSystem light: #00B533 green, near-black (neutral-900, not pure black), lime, greys; EcoSystem dark: lime, near-white (neutral-100), malachite, greys. Never another brand's colour: no blue, yellow, teal or aqua in EcoSystem charts. Black is a primary colour — use it before reaching for grey. Never reshuffle the order per chart; take the colour from the token, never the HEX.
- Maximum six series. Need more? Merge the tail into “Boshqa”, or separate them with a pattern or a direct label — never invent a seventh colour.
- Never put two close greens next to each other (e.g. green-700 beside #00B533 beside green-300). Lime is fine for fills and bars; in the light mode it is 1.2:1 on white, so a lime line or slice always carries a direct label.
- Sequential (low → high): --eco-chart-seq-1…5, one green ladder — ONLY for ordered magnitude (heatmap, activity calendar, density). Never use it for categorical series or stacked parts. Diverging (error ↔ success): --eco-chart-div-1…5, neutral in the middle.
- Colour never carries meaning alone: label the series or add a pattern. Axes and gridlines ≥ 3:1 against the background; series colours follow the known limits above.

## Project accents
- --eco-project-{academy|school|junior|university|online}: one accent per active ecosystem project, its own brand colour (school blue, a lighter step in dark; university teal; junior cyan; online yellow — the Academy family sun). Values come from the tokens; the hue stays, only the step may shift with the mode.
- Use them to tell projects apart: project chip, filter, legend, card stripe, avatar background. Not for buttons, links or focus.
- A project may re-map its own --eco-project-* token; it may not re-map the brand colours or another project's accent.

## Semantic tokens (use inside components)
- Backgrounds: --eco-bg-primary (page), --eco-bg-secondary (cards, sections, progress track), --eco-bg-tertiary (progress track on grey surfaces), --eco-bg-quaternary, --eco-bg-primary_alt (dialogs, popovers, raised cards), --eco-bg-primary_hover, --eco-bg-secondary_hover, --eco-bg-active, --eco-bg-disabled, --eco-bg-overlay (behind dialogs), --eco-bg-primary-solid (tooltips, toasts)
- Text: --eco-text-primary, --eco-text-secondary (+ _hover), --eco-text-tertiary (muted, + _hover), --eco-text-quaternary, --eco-text-placeholder, --eco-text-disabled, --eco-text-white, --eco-text-brand-primary, --eco-text-brand-secondary (links, + _hover), --eco-text-brand-tertiary, --eco-text-primary_on-brand (text on brand fills: white on the light-mode green fill, black on the dark-mode lime fill)
- Borders: --eco-border-primary (strong strokes; ≥ 3:1), --eco-border-secondary (strong dividers, hover), --eco-border-tertiary (dividers, table rows), --eco-border-disabled, --eco-border-brand (input focus, drag-over), --eco-border-error, --eco-border-error_subtle
- Foreground (icons): --eco-fg-primary, --eco-fg-secondary, --eco-fg-tertiary, --eco-fg-quaternary (+ _hover), --eco-fg-white, --eco-fg-disabled, --eco-fg-brand-primary, --eco-fg-brand-primary_alt (on inverted surfaces such as .eco-toast), --eco-fg-brand-secondary, --eco-fg-error-primary, --eco-fg-error-secondary, --eco-fg-warning-primary, --eco-fg-success-primary, --eco-fg-success-secondary
- Brand fills: --eco-bg-brand-solid (+ _hover) for checked controls, solid badges and brand bands; --eco-bg-brand-primary, --eco-bg-brand-secondary for soft tints. In the light mode --eco-bg-brand-primary is the project's brand tint --eco-color-brand-tint (#E9FED8 in EcoSystem, Academy and Online): selected cards, info cards, pressed chips, brand badges; never mix your own tint from the brand colour.
- Buttons: --eco-brand-button with --eco-brand-on-button (primary), --eco-brand-button-accent with --eco-brand-on-button-accent, --eco-brand-button-ink with --eco-brand-on-button-ink; secondary text --eco-brand-button-secondary-fg. Never mix the pairs.
- Status: success, warning, error, plus info only for the “Waiting” status (.eco-badge--info, icon --eco-fg-info-primary) — the only blue in EcoSystem. Soft fill --eco-bg-{success|warning|error}-primary, solid fill --eco-bg-{success|warning|error}-solid, text --eco-text-{success|warning|error}-primary, icon --eco-fg-{success|warning|error}-primary; error also has --eco-bg-error-secondary, --eco-bg-error-solid_hover, --eco-text-error-primary_hover.
- Focus: --eco-focus-ring; --eco-focus-ring-error on destructive controls.
- Shadows: --eco-shadow-xs (modern featured icons, table cards), --eco-shadow-sm, --eco-shadow-md, --eco-shadow-lg (dropdowns, toasts, raised cards), --eco-shadow-xl (dialogs), --eco-shadow-2xl, --eco-shadow-3xl. Buttons, inputs and plain cards have no shadow.
- Light ↔ dark: brand fill green #00B533 ↔ lime; links green-done #00A603 ↔ lime; focus green-700 ↔ lime; --eco-bg-primary #FFFFFF ↔ #141414; text on brand fills white ↔ black.
- Removed in v0.3, never use: --eco-surface*, --eco-accent*, --eco-on-accent, --eco-text-muted, --eco-border-strong, --eco-space-N, --eco-control-*, --eco-type-*, --eco-tracking-*, --eco-shadow-1/2/3, --eco-danger-*, --eco-info-*.

## Typography
- Headings: --eco-font-display ("PDP Display": Space Grotesk for Latin, Golos Text for Cyrillic, one weight lighter at 96%). Medium 500 for display/h1/h2, Regular 400 for h3/h4. Display text of 20px and larger: letter-spacing −4% (var(--eco-font-display--letter-spacing)); never on uppercase eyebrows or labels.
- Body and UI: --eco-font-body (Inter). Code: --eco-font-mono (IBM Plex Mono). Load all of them with one <link rel="stylesheet" href="https://design.pdp.uz/ds/fonts/fonts.css"> (self-hosted, SIL OFL).
- Scale, size/line-height in px: --eco-text-xs 12/18, --eco-text-sm 14/20, --eco-text-md 16/24, --eco-text-lg 18/28, --eco-text-xl 20/30, --eco-text-display-xs 24/32, --eco-text-display-sm 30/38, --eco-text-display-md 36/44, --eco-text-display-lg 48/60, --eco-text-display-xl 60/72, --eco-text-display-2xl 72/90.
- Every size has a --line-height pair; every display size also has --letter-spacing (−4%). Use: font: 500 var(--eco-text-display-lg)/var(--eco-text-display-lg--line-height) var(--eco-font-display); letter-spacing: var(--eco-text-display-lg--letter-spacing). Other styles use 0.
- Sentence case. Body and input text 16px (--eco-text-md); buttons 16/24 in --eco-font-body, weight 500 (xs and sm 14/20); labels and hints 14px. Nothing below 12px.
- Section eyebrows (the uppercase label above a section title, e.g. “05 — TYPOGRAPHY”): --eco-font-mono, Medium 500, 14px, letter-spacing 0.12em, uppercase, in every brand. In EcoSystem, Academy and Online all green text in the light mode — eyebrows, card titles, labels and links — is --eco-color-green-done, an exception below 4.5:1 approved by the user (01.10.2026). Green fills keep their colour and white text.

## Spacing, shape, size
- Spacing scale only, px: --eco-spacing-{none 0, xxs 2, xs 4, sm 6, md 8, lg 12, xl 16, 2xl 20, 3xl 24, 4xl 32, 5xl 40, 6xl 48, 7xl 64, 8xl 80, 9xl 96, 10xl 128, 11xl 160}.
- Radius scale only, px: --eco-radius-{none 0, xxs 2, xs 4, sm 6, md 8, lg 10, xl 12, 2xl 16, 3xl 20, 4xl 24, full 9999}.
- Buttons, cards, alerts, dialogs, dropdown menus: 24px (--eco-radius-4xl; buttons are pills; xs buttons 16px; menu rows 20px); link-style buttons 4px (--eco-radius-xs). Inputs, selects, input groups, comboboxes, date and search fields: pill (--eco-field-radius-affix = --eco-radius-full), 44px high (sm 40px); multi-line textarea 20px (--eco-field-radius-multiline); OTP cells 12px. Toasts, tooltips: 12px (--eco-radius-xl). Callouts: 10px (--eco-radius-lg). Chips and --badge badges: 6px (--eco-radius-sm; lg badges 8px). Fully round (--eco-radius-full) only for single-line fields, pill badges, avatars, radios, switches, progress bars, sliders, segments and pill tabs.
- Heights: buttons xs 32, sm 36, md 40 (default), lg 44, xl 48px; inputs sm 40, md 44px (default). Buttons have a fixed height and horizontal padding only (xs 12, sm and md 16, lg 20, xl 24px; icon-only: a square, no padding); inputs take their height from padding + line-height.
- Content width: --eco-max-width-container 1280px.
- Icons: Phosphor Icons v2.1.1 (MIT) — Regular weight by default, Fill weight for active / selected / on states (current nav item, selected tab or segment, pressed toggle such as Saved or Favourite, current lesson, rating star); Bold only for tiny status marks in circles (check-bold, x-bold). Sizes --eco-icon-sm 16px, --eco-icon-md 20px, --eco-icon-lg 24px; colour is currentColor.
- Motion: --eco-duration-fast 120ms (hover, press), --eco-duration-base 200ms (toggles, tabs), --eco-duration-slow 360ms (panels); easing --eco-ease-standard, --eco-ease-emphasized (entering), --eco-ease-exit (leaving).
- Breakpoints (min-width): xs 600, sm 640, md 768, lg 1024, xl 1280, 2xl 1536px. Grid: 4 columns below 768px, 8 from md, 12 from lg; gutter 16px, 24px from md. Mobile first; no horizontal scroll at 390px.

## Components (reuse these class names; if the CSS is missing, implement them with these names and tokens)
- .eco-btn: sizes --xs | --sm | md (default, no class) | --lg | --xl; variants --primary | --accent | --ink | --secondary | --tertiary | --outline | --ghost | --link-color | --link-gray | --primary-destructive | --secondary-destructive | --tertiary-destructive | --link-destructive; --icon (square, icon only), --block (full width); .is-loading; [disabled]. While a button waits, put .eco-loader.eco-loader--sm.eco-loader--mono (aria-hidden) before the label and change the label (“Saqlanmoqda…”). Pill, no shadow; only --outline has a ring (1px, the same neutral as the tertiary fill in the dark mode). Hover darkens the fill; focus = hover fill + ring; pressed: scale(.975). Icon 16px (lg, xl: 20px), gap 8px (xs: 4px). In link variants wrap the label in <span> for the hover underline. Joined buttons: .eco-btn-group > .eco-btn.
- .eco-field > .eco-label (+ .req) + .eco-input (input, textarea, select; --sm 40px, md 44px default; no border: --eco-bg-secondary fill, --eco-bg-primary inside a card) + .eco-hint; .eco-input-wrap with a leading and/or trailing .eco-icon; .is-error (or aria-invalid="true"), .is-success
- .eco-otp (fieldset) > legend.eco-label + .eco-hint + .eco-otp__row (6 × input.eco-input.eco-otp__cell, 42×44px, 3 + 3 with an optional span.eco-otp__sep) + .eco-otp__foot (text + .eco-btn--link-color “resend”, aria-disabled while the timer runs). First cell autocomplete="one-time-code", all inputmode="numeric", no maxlength (spread a pasted code from the first cell); error: .is-error + aria-invalid="true" on every cell, message with role="alert"; checking: aria-busy="true"; disabled: fieldset[disabled].
- .eco-input-group (+ --sm; 44px default, 40px sm; inner pill 32 / 28px) > .eco-input-group__addon | select.eco-input-group__select (inside the addon) | button.eco-input-group__btn (--icon = icon only) + input.eco-input-group__input. One pill surface (radius var(--eco-field-radius-affix) = --eco-radius-full; plain .eco-input stays 12px), 6px inset, NO divider lines. Prefix/suffix = a pill inside the field (height = field − 12px); only a part with a function (select, button: copy, show, apply) or static text (%, .pdp.uz, +998) gets its own fill; static icons (globe, search, mail, lock) are .eco-input-group__addon--icon: no fill, --eco-fg-quaternary, like a search icon; --plain = text without fill. Fills come from context: on white the field is --eco-bg-secondary and the pill --eco-bg-primary_alt; on grey (.eco-card, .eco-input-group--on-grey) the field is --eco-bg-primary and the pill --eco-bg-secondary (custom properties --field-bg / --affix-bg, Light and Dark). Focus: 1.5px --eco-brand-button ring around the whole group; error: constant 1.5px --eco-focus-ring-error ring + message with an icon below. A text affix is a second <label for> of the input; with a select: role="group" + aria-labelledby on the group, aria-label on the select. At ≤ 479px a button pill with an icon shows the icon only.
- .eco-choice > .eco-check | .eco-radio (16px, --md 20px) | .eco-switch (36×20, --md 44×24) + label text (+ <small> hint); .eco-check--round (24px, + --lg 28px; + --media on photos) for multi-select on phones, lists, photos and avatars. Native inputs (spans with .is-on in aria-hidden mock-ups). Checkbox and radio geometry from Figma «Telegram Design System» (07.10.2026): unchecked = transparent inside + a neutral --eco-border-primary ring (1.5px at 16, 2px at 20; the one allowed control ring), hover = ring in the brand button colour; checked checkbox = square (13% corners) filled with --eco-brand-button + a round-cap tick in --eco-brand-on-button, indeterminate = the same fill + a dash; checked radio = brand ring + brand dot (47% of the size); on a brand-filled surface set --ctl-on: var(--btn-p-fg). One radio and one checkbox style only — never a check-circle radio or a solid disc with a white dot. Switch = brand fill + --eco-text-primary_on-brand thumb.
- .eco-slider (#slider): .eco-slider__head + .eco-slider__control (track, fill, 1–2 range inputs, optional __tip); --steps = step dots. Fill --eco-slider-fill (brand colour, both modes), white thumb, soft shadow only — no ring on track, thumb or bubble.
- .eco-badge: type pill (default) | --badge (6px corners); size --sm 22 | md 24 (default) | --lg 28px; colour --gray (default) | --brand | --success | --warning | --error; --dot. --solid (brand fill: green #00B533 with white text in light, lime with black text in dark) only for “Yangi”.
- .eco-chip (button[aria-pressed], 6px corners), .eco-avatar (--xs 24 | --sm 32 | --36 (design size: Inter 500 12/20, icon 16px) | md 40 default | --lg 48 | --xl 56 | --2xl 64px; .eco-avatar__status)
- Avatars (section “Avatarlar”, #avatars): an avatar always has a coloured background — no gradient (blurred orb) avatars and no grey circle with an icon or initials (art director decision, 04.10.2026). Every person, the current user included (lists, tables, chat, comments, rankings, kanban, groups), uses a 3D avatar (background colour baked into the image, the same in Light and Dark) — <span class="eco-avatar eco-avatar--3d" aria-hidden="true"><img src="https://design.pdp.uz/ds/assets/avatars/avatar-{01…16}.webp" alt="" width="40" height="40" loading="lazy" decoding="async"></span>; image picked by a stable hash of the user id, neighbours differ (images: Figma Community set by Arthur Belfort, CC BY 4.0 — credit kept in /ds/assets/avatars/README.md). Non-person agents — AI-mentor, bots, the system, groups — and the project mark use .eco-avatar--tint: a solid brand-tint circle (--eco-avatar-tint-bg) with a brand-colour Phosphor icon (#i-sparkles for the AI-mentor, #i-bot, #i-users) or the project initials (--eco-avatar-tint-ink). There is no initials fallback for people (--solid, --ink-*, --cat-* removed, 02.10.2026). Colours come from the --eco-avatar-* tokens. No real photos, no ring or border around an avatar, no animation.
- The EcoSystem project mark may also use .eco-avatar--accent (lime circle, green initials) or --inverse (#1F1F1F circle, lime initials).
- .eco-card (--raised, --interactive; .eco-card__title, .eco-card__meta): 24px corners, 24px padding, --eco-bg-secondary, no border (1px transparent keeps the size), no shadow; --raised and --interactive hover add --eco-shadow-lg
- .eco-tabs > .eco-tab[role=tab][aria-selected] (underline; pill — .eco-tabs--pill; --fill = equal widths), .eco-segment > button[aria-pressed] (--fill; --stacked — icon on top), .eco-link
- Dropdown menu and list (section “Menyu va ro‘yxat”, #menus): .eco-dropdown > button[aria-haspopup=menu|listbox][aria-expanded][aria-controls] + .eco-menu[role=menu|listbox][hidden] (--eco-bg-primary_alt + shadow-lg) > .eco-menu__group (.eco-menu__label), .eco-menu__sep, .eco-menu__item[role=menuitem|menuitemradio|menuitemcheckbox|option] (svg 16 or .eco-avatar 36, .eco-menu__body > .eco-menu__title + .eco-menu__desc, .eco-menu__kbd or .eco-menu__end; .eco-menu__check, --dot for one choice; --danger last, in its own group). Rows 36 / 38 / 56px. Arrows, Home/End, typeahead; Esc returns focus to the trigger. Form fields keep a native <select>.
- .eco-table (td.num), .eco-alert (--brand --success --warning --error; svg.eco-alert__icon + .eco-alert__body > __title + __desc, optional .eco-btn--sm.eco-alert__cta), .eco-toast, .eco-tooltip (+ <small>), .eco-progress > span (--v; fill --eco-brand-button, track --eco-bg-secondary, no stroke), .eco-progress-field (__head: __label + optional __info icon, __value with % + __status icon in role="status" — spinner #i-loader, .is-complete #i-circle-check, .is-error #i-circle-x; then .eco-progress or .eco-progress-row; __hint below, error message with role="alert"), .eco-progress-row (.eco-progress + <b>40%</b>), .eco-progress-float (--bottom; label bubble with shadow, no stroke), .eco-skeleton
- .eco-callout (tone: none = neutral grey | --brand | --info | --warning | --error | --success; variants: --compact, dismissible with .eco-callout__close), role="note": span.eco-callout__icon[aria-hidden] > svg (Phosphor fill: notepad-text, sparkles, info, triangle-alert, circle-x, circle-check), then div.eco-callout__content > p.eco-callout__title + div.eco-callout__body + optional div.eco-callout__actions > a.eco-callout__action (or one .eco-btn--sm); optional button.eco-callout__close[aria-label] > svg #i-x. Calm filled surface from semantic tokens only (brand tint follows the brand, info is the status blue --eco-cat-blue), 32px icon tile, title Inter 600 16/24 in --eco-text-primary, body 14/20 at 76% of the text colour; no border, left stripe or shadow, no decorative tones (teal/purple are gone). Old names still work: --note = neutral, --tip = --brand, --important = --info. A status or system response is .eco-alert.
- App components (section “Ilova komponentlari”, #app): tabs (.eco-tabs underline; pill — .eco-tabs--pill or .eco-segment in a grey track, stroke-less: neutral by default — white pill with a soft shadow and a black label, --inverse — black pill with a white label, --brand and --accent — brand pills from the --eco-tab-* tokens; sizes --sm | --md | --lg; the old --button-border | --button-gray | --button-brand names still work), progress bar, field with states and circle (.eco-progress, .eco-progress-field, .eco-progress-circle --xxs | --sm | --md, --p number), table in a card (.eco-table-card with .eco-table and .eco-pagination), pagination (.eco-pagination, --minimal), dialog (.eco-modal in .eco-modal-overlay or <dialog class="eco-modal">; --xs 320 | 480 | --md 640 | --lg 800, <dialog> only --cover | --full; --blur backdrop; cancel --tertiary), empty state (.eco-empty, --md), file upload (.eco-dropzone + .eco-file list), kanban board — moved to the Ilova page as the Nextcloud Deck reskin (/ds/ilova/#kanban: Deck DOM classes .app-deck, .stack, .card, .card-labels .labels li with a --eco-board-* dot, .duedate[data-due-state], .icon-badge; grey stacks, white cards, no outlines; EcoSystem tokens only). Copy their markup from that section.
- Icon markup (Phosphor symbols in an SVG sprite, id "i-<key>", filled twin "i-<key>-fill"): <svg class="eco-icon" aria-hidden="true"><use href="#i-search"/></svg>. On a control whose state changes (aria-pressed, aria-selected, aria-current) put both weights in one svg and let base.css switch them: <svg class="eco-icon" aria-hidden="true"><use href="#i-heart"/><use class="eco-on" href="#i-heart-fill"/></svg>

## Layout
- One primary action per screen: at most one .eco-btn--primary. Next to a coloured button (primary, accent, ink) put only a colourless one: .eco-btn--tertiary (neutral fill, the default) or .eco-btn--outline (no fill, 1px neutral ring; on busy or coloured backgrounds). Never two coloured buttons side by side; .eco-btn--secondary (brand-coloured text) is for a lone secondary action, never next to a primary. Otherwise use a link button.
- Buttons and single-line inputs are pills; multi-line textareas 20px, cards 24px.
- Lime and green are accents. Most of the screen stays white (light mode) or black (dark mode).
- Layer surfaces with --eco-bg-secondary / --eco-bg-tertiary fills, not borders or heavy shadows. No stroke around a filled object (card, control, chip, tab, stage): switches and slider tracks sit on --eco-bg-tertiary (--eco-bg-primary inside a grey card), checkboxes and radios use their thin neutral ring; a selected chip or card is a brand tint without a ring; a selected tab is a solid pill or the 2px underline, without a ring. Keep dividers inside components (key–value rows, table rows, card footers), focus rings and error strokes. Only floating layers (dropdowns, dialogs, toasts) get --eco-shadow-lg or --eco-shadow-xl.

## Screens
- Look for an existing component or pattern first (sections “Majburiy bloklar”, “Sahifa anatomiyasi”, “Ilova komponentlari”). Build a new component only when nothing fits, and start from the closest one.
- One lead metric per screen, next to the one primary action: the lead number is the largest on the screen; other numbers are smaller and neutral.
- Learning data first: progress, grades and deadlines come before technical data (IDs, sync times, system status).
- Every screen that shows data ships three states: loading (.eco-skeleton in the shape of the content; a page or action wait shows .eco-loader, never a border spinner), empty (.eco-empty: icon, title, one action) and error (what happened, plus a retry action).
- Responsive cabinet: sidebar 248px from 1280px, a 72px icon rail with tooltips from 1024px, a drawer with an overlay from 768px, a bottom tab bar (4–5 items, each ≥ 48px) below 768px. Below 768px each table row becomes a card with its main value and status.
- Headings go h1 → h2 → h3 without skipping a level; tabular data is a real <table> with th cells.
- Check every button, badge and tab label in Uzbek, Russian and English: Uzbek is often the longest (Russian ≈ +1%, English ≈ −7% on average), so design for the Uzbek length first, leave ~30% room, and labels never truncate.

## Content and language
- UI copy in Uzbek Latin unless asked for Russian. <html lang="uz">; Russian pages lang="ru".
- Write o‘ and g‘ with U+2018 (‘) and the tutuq belgisi with U+2019 (’): o‘quvchi, g‘olib, ma’lumot, e’tibor. Never ASCII ' or ` there. Quotes: “…”.
- Realistic content: courses (Frontend dasturlash, UI/UX dizayn, Backend · Node.js), names (Dilnoza, Jasur, Madina), prices in so‘m (1 200 000 so‘m), dates DD.MM.YYYY (21.09.2026). No lorem ipsum.
- Tone: short, direct, imperative.

## Accessibility minimums (WCAG 2.2 AA)
- Text ≥ 4.5:1; large text (≥ 24px), icons and focus ring ≥ 3:1. Status never by colour alone.
- Exception: avatar initials keep the designed colours even below 4.5:1 on the tint (user decision 30.09.2026). The avatar is decorative (aria-hidden="true") and the name is always shown next to it as text.
- Focus: :focus-visible — 1.5px ring (--eco-focus-w) drawn with box-shadow: 0 0 0 2px var(--eco-bg-primary), 0 0 0 calc(2px + var(--eco-focus-w)) var(--eco-focus-ring), plus outline: var(--eco-focus-w) solid transparent for forced-colors (Chrome rounds outline widths to whole px). Never 2px. Never remove it. Destructive controls use --eco-focus-ring-error. Fields (input, textarea, select, OTP, input group, search, combobox, date, tag and chat inputs) all share ONE focus state: outline: var(--eco-field-focus-w) solid var(--eco-brand-button); outline-offset: 0 — 1.5px, the brand button colour, following the field radius; --eco-focus-ring-error on a field with an error. Never 2px and never --eco-focus-ring on a field. Inside a brand-filled area set --eco-focus-ring: var(--eco-text-primary_on-brand).
- Touch targets ≥ 40px on mobile: md (40px) buttons by default, lg (44px) or xl (48px) for the main mobile action. xs (32px) and sm (36px) buttons and chips only in dense UI, at least 8px apart.
- Real elements: <button>, <a href>, <input> with a visible <label>. Icon-only buttons get an Uzbek aria-label.
- Keyboard: logical Tab order, Esc closes overlays and returns focus, arrow keys move inside tabs and segments.
- Form errors: text + icon + colour, aria-invalid="true", aria-describedby to the message.
- Images: meaningful Uzbek alt text; decorative images alt="" or aria-hidden="true".
- Honour prefers-reduced-motion: no movement, near-zero durations.

## Never
- No purple, blue or rainbow gradients; no gradient except --eco-gradient (avatars have no gradients).
- No distinction colour (chart series, category tone) as a button, link, focus ring or status; none where a brand or status token exists.
- No seventh chart colour, no re-ordered or re-tuned chart series.
- No emoji as icons and no other icon sets; use Phosphor (Regular, Fill for active states).
- No lime text on white or light backgrounds; no white text on lime; no black text or marks on green.
- No new colours, fonts, radii, shadows or spacing values outside the tokens.
- No sharp-cornered buttons, inputs or cards, no pill-shaped inputs, no more than one primary button per screen.
- No ALL CAPS body text; no text in images.
- Do not stretch, recolour, rotate or restyle the PDP EcoSystem logo; keep 1X clear space (X = mark width / 9).

Before you finish, check your output against this list and name any rule you could not follow.