/* =====================================================================
 * IsaZade — site kit v3 (final). The shared primitives every inner page
 * is rebuilt from. Tokens come from tokens.css (vault) + chrome.css (--iz-*).
 * Logical properties throughout: the site is RTL, the CSS never says left/right — except in the
 * three places CSS offers no logical form, all of them below and all of them deliberate: a mask
 * gradient's direction, a background-position keyword, and the text-align of an isolated LTR run.
 *
 * Ported from Claude outputs/design-system-v3/css/kit.css, which is the reference
 * implementation of every specimen in the v3 pattern book. Two additions the
 * reference leaves to the host page:
 *
 *   --iz-ease       used by transitions here, declared in chrome.css. Repeated so
 *                   this file stands on its own if chrome.css ever loads later.
 *   --art-{slot}    the illustration slots. The URLs below are the plain path; PHP
 *                   re-declares each one with a cache-busting ?v= through
 *                   isazadeh_art_vars_css() (inc/kit.php), and that declaration wins
 *                   because it is added after this file. A slot with no file is never
 *                   rendered — isazadeh_art() returns nothing — so these defaults are
 *                   only ever read for art that is actually installed.
 * ===================================================================== */
:root {
	--art-state-start: url("../images/art/state-start.webp");
	--art-state-empty: url("../images/art/state-empty.webp");
	--art-sprig: url("../images/art/sprig.webp");
	--art-sprig-light: url("../images/art/sprig-light.webp");
	--art-card-course: url("../images/art/card-course.webp");
	--art-card-post: url("../images/art/card-post.webp");
	--art-hero-plant: url("../images/art/hero-plant.webp");
	--art-bloom: url("../images/art/bloom.webp");
	--art-roots: url("../images/art/roots.webp");
	--art-bg-tests: url("../images/art/bg-tests.webp");
	--art-vine: url("../images/art/vine.webp");
	--art-head-forum: url("../images/art/head-forum.webp");
	--art-head-support: url("../images/art/head-support.webp");
	--art-empty-state-found: url("../images/art/empty-state-found.webp");
	--art-state-empty-booking: url("../images/art/state-empty-booking.webp");
	--art-state-empty-learning: url("../images/art/state-empty-learning.webp");
	--art-card-workshop: url("../images/art/card-workshop.webp");
	--iz-ease: cubic-bezier(.25, .1, .25, 1);
	--iz-r-sm: 10px;
	--iz-r: 16px;
	--iz-r-lg: 24px;
	--iz-leaf: 28px 8px 28px 8px;          /* the leaf-frame corner set, mirrored from the hero photo */
	--iz-surface: #fff;
	--iz-sunk: #f4f8f8;                     /* inputs, rails, zebra */
	--iz-line: var(--neutral-light);
	--iz-line-soft: #e8efee;
	--iz-ink: var(--neutral-dark);
	--iz-text: var(--neutral-medium);
	--iz-ink-soft: #58707a;                 /* captions — 4.68:1 on every light ground */
	--iz-focus: 0 0 0 3px rgb(46 113 136 / .45);
	--iz-shadow-1: 0 1px 2px rgb(22 75 96 / .06), 0 4px 16px rgb(22 75 96 / .06);
	--iz-shadow-2: 0 2px 4px rgb(22 75 96 / .05), 0 14px 32px rgb(22 75 96 / .09);
	--iz-shadow-3: 0 24px 60px -30px rgb(22 75 96 / .35);
	--iz-ease-out: cubic-bezier(.23, 1, .32, 1);
	/* Icon glyph sizes (2026-09-29). An icon's size is exempt from the type ladder (spacing standard,
	 * rule 5) but not from having a scale: the kit drew glyphs at 12, 14, 18, 19, 20, 22 and 26px. Five
	 * steps now. Declared here until tokens.css carries them. */
	--iz-icon-xs: var(--icon-xs);
	--iz-icon-s: var(--icon-s);
	--iz-icon-m: var(--icon-m);
	--iz-icon-l: var(--icon-l);
	--iz-icon-xl: var(--icon-xl);
	--iz-ease-in-out: cubic-bezier(.77, 0, .175, 1);
	--iz-ease-drawer: cubic-bezier(.32, .72, 0, 1);
	/* Press feedback, one depth for the whole kit: `transform: scale(var(--iz-press))` on :active,
	 * with `transform 160ms var(--iz-ease-out)` in the element's transition list. A surface wider
	 * than about 320px takes --iz-press-lg instead, because the travel is proportional to the width:
	 * a 150px button at .97 draws its edges in 2.3px a side, a 600px option card at .97 would lurch
	 * 9px, and at .985 it moves 4.5. Disabled controls never scale (the guard ends this file). */
	--iz-press: .97;
	--iz-press-lg: .985;
	/* status tones — one map for tickets, orders, appointments, forum, tests */
	--tone-open-bg: var(--primary-50);       --tone-open-fg: var(--primary-700);     --tone-open-dot: var(--primary-500);
	--tone-success-bg: var(--secondary-50);  --tone-success-fg: var(--secondary-700); --tone-success-dot: var(--secondary-500);
	--tone-attention-bg: var(--accent-50);   --tone-attention-fg: var(--accent-700); --tone-attention-dot: var(--accent-500);
	--tone-neutral-bg: #eef3f2;              --tone-neutral-fg: var(--neutral-medium); --tone-neutral-dot: #8fa3a8;
	--tone-danger-bg: var(--accent-100);     --tone-danger-fg: var(--accent-700);    --tone-danger-dot: var(--accent-700);
}

/* ------------------------------------------------------------- art (illustration slots)
 * Always decorative: every .art element is aria-hidden with no text, so a slot that is
 * missing costs a reader nothing. One class per slot so a template names the moment of the
 * growth story it wants (docs/art-slots.md) rather than a file path. */
.art { display: block; background: center / contain no-repeat; flex: none; }
.art--flip { transform: scaleX(-1); }
.art--state-start { background-image: var(--art-state-start); }
.art--state-empty { background-image: var(--art-state-empty); }
.art--sprig { background-image: var(--art-sprig); }
.art--sprig-light { background-image: var(--art-sprig-light); }
.art--card-course { background-image: var(--art-card-course); }
.art--card-post { background-image: var(--art-card-post); }
.art--hero-plant { background-image: var(--art-hero-plant); }
.art--bloom { background-image: var(--art-bloom); }
.art--roots { background-image: var(--art-roots); }
.art--bg-tests { background-image: var(--art-bg-tests); background-size: cover; }
.art--vine { background-image: var(--art-vine); }
.art--head-forum { background-image: var(--art-head-forum); }
.art--head-support { background-image: var(--art-head-support); }
.art--empty-state-found { background-image: var(--art-empty-state-found); }
.art--state-empty-booking { background-image: var(--art-state-empty-booking); }
.art--state-empty-learning { background-image: var(--art-state-empty-learning); }
.art--card-workshop { background-image: var(--art-card-workshop); }
@media (prefers-reduced-motion: no-preference) {
	.art--sway { transform-origin: 50% 100%; animation: iz-sway 7s var(--iz-ease-in-out) infinite alternate; }
	@keyframes iz-sway { from { rotate: -1.4deg; } to { rotate: 1.6deg; } }
}

/* ------------------------------------------------------------- patterns
 * A quiet botanical texture for a band that would otherwise feel empty — a lone card on a wide
 * tint, a short section on the bare canvas (owner, 2026-09-26: "consider a related background
 * pattern for some sections to avoid the empty feeling"). One class on the section: the texture
 * is its ::before, painted under the content and inside the box, so there is no wrapper and
 * nothing to overflow. Decorative only — it carries no meaning and is invisible to assistive technology.
 *
 *   .iz-pattern                  the layer; alone it draws the leaves
 *   .iz-pattern--leaves          scattered leaf outlines with a midrib, the art's leaf in a pen line
 *   .iz-pattern--sprigs          the site's own mark (#iz-leaf) as a sparse, upright outline stamp
 *   .iz-pattern--dots            a staggered seed grid, hand-irregular
 *   .iz-pattern--contour         growth-ring lines that part and gather like contours
 *   .iz-pattern--fade-start      quiet at the inline start, where a right-to-left heading begins
 *   .iz-pattern--fade-end        quiet at the inline end
 *   .iz-pattern--fade-edges      dissolves toward every edge, so it never meets a band's boundary
 *   .iz-pattern--fade-center     quiet in the middle, present at the edges — for centred content
 *   .iz-pattern--on-tint         white ink, for the tinted bands (--surface-blue/-green, --iz-sunk):
 *                                it lifts the ground away from the text, so it costs no contrast
 *   .iz-pattern--on-dark         light ink, for the dark bands (footer, greeting)
 *   .iz-pattern--after           uses ::after, for a host whose ::before is already taken
 *
 *   --iz-pattern-ink      the colour, alpha included (default --secondary-500 at .22; --on-tint
 *                         white; --on-dark white at .2)
 *   --iz-pattern-opacity  the whole layer (default .4, 1 for --on-tint — so the ink the eye meets
 *                         on the canvas is under a tenth)
 *   --iz-pattern-size     the tile's width (per motif, 72-360px); the stroke scales with it, so
 *                         stay within about ±30% — larger reads as sparser, smaller as denser
 *   --iz-pattern-fade     any gradient, used as a mask: opaque shows the pattern, transparent hides it
 *
 * The motif is a MASK rather than a background image because a data-URI SVG cannot read a custom
 * property: the layer is filled with the ink and the SVG only decides where that ink shows, so the
 * colour stays a token and one file serves every ground. The fade is a second mask layer
 * intersected with the first. A continuous line carries four times the ink of a scattered stamp,
 * so the contour draws at .65 of the layer's opacity (--_iz-weight) to sit at the same visual
 * weight as the other three. Its gradients name `left` through --_iz-end — a gradient's direction
 * is the one more place CSS has no logical form — and `:dir(ltr)` flips it.
 *
 * Measured 2026-09-26 at the worst pixel behind each line of text, pattern on against off:
 * --on-tint costs 0.0% on every tint (its ink is lighter than the ground, so contrast can only
 * rise); the default ink on the canvas or white at most 10.5% (caption grey keeps 4.58:1, body
 * text 6.26:1); --on-dark at most 21% (white keeps 9.2:1, white at .82 6.8:1, at .7 5.5:1). Text
 * inside a fade's quiet zone lost at most 1.9%. The default ink on a tint would take caption grey
 * to 4.25:1, under AA — which is what --on-tint is for.
 * Browsers without unprefixed mask compositing draw nothing rather than a flat tint.
 */
:where(.iz-pattern) { position: relative; isolation: isolate; }
.iz-pattern {
	--_iz-motif: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200' fill='none' stroke='black' stroke-width='1.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cdefs%3E%3Cpath id='l' d='M0 0C5-3 7.5-11 1-21C-5.5-14-6.5-5-1.2-.8M0 4Q1.2-7 .6-15'/%3E%3C/defs%3E%3Cuse href='%23l' transform='translate(40 52) rotate(-38)'/%3E%3Cuse href='%23l' transform='translate(132 30) rotate(44) scale(.8)'/%3E%3Cuse href='%23l' transform='translate(172 124) rotate(118) scale(.9)'/%3E%3Cuse href='%23l' transform='translate(88 132) rotate(-112) scale(.9)'/%3E%3Cuse href='%23l' transform='translate(28 170) rotate(16) scale(.8)'/%3E%3C/svg%3E");
	--_iz-tile: 200px;
	--_iz-ink: rgb(from var(--secondary-500) r g b / .22);
	--_iz-opacity: .4;
	--_iz-end: left;
}
.iz-pattern:dir(ltr) { --_iz-end: right; }
.iz-pattern--sprigs {
	--_iz-motif: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220' fill='none' stroke='black' stroke-width='1.1' stroke-linecap='round' stroke-linejoin='round'%3E%3Cdefs%3E%3Cpath id='s' d='M0 8Q1.2 0 0-8M.1-4.4C2.2-10.2 6.8-13 11.7-12.2C10.9-6.2 6-2.6 .1-4.4M-.1 .3C-2-4.4-6-7-10.4-6.5C-9.8-1.3-5.5 2.1-.1 .3'/%3E%3C/defs%3E%3Cuse href='%23s' transform='translate(46 40) rotate(-12) scale(1.1)'/%3E%3Cuse href='%23s' transform='translate(158 70) rotate(18) scale(-.9 .9)'/%3E%3Cuse href='%23s' transform='translate(96 150) rotate(6) scale(-.9 .9)'/%3E%3Cuse href='%23s' transform='translate(190 188) rotate(-22) scale(.8)'/%3E%3C/svg%3E");
	--_iz-tile: 220px;
}
.iz-pattern--dots {
	--_iz-motif: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='72' height='72'%3E%3Ccircle cx='12.4' cy='11.7' r='1.4'/%3E%3Ccircle cx='35.5' cy='12.2' r='1.2'/%3E%3Ccircle cx='60.2' cy='12.5' r='1.5'/%3E%3Ccircle cx='23.7' cy='35.6' r='1.3'/%3E%3Ccircle cx='48.5' cy='36.1' r='1.4'/%3E%3Ccircle cx='71.8' cy='36.4' r='1.1'/%3E%3Ccircle cx='12.3' cy='59.5' r='1.4'/%3E%3Ccircle cx='35.6' cy='60.3' r='1.6'/%3E%3Ccircle cx='60.1' cy='59.8' r='1.2'/%3E%3C/svg%3E");
	--_iz-tile: 72px;
}
.iz-pattern--contour {
	--_iz-motif: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='360' height='240' fill='none' stroke='black' stroke-width='1' stroke-linecap='round'%3E%3Cpath d='M0 16c15-5 30-13 45-15s30 1 45 4s30 11 45 14s30 4 45 5s30 0 45 1s30 5 45 6s30 2 45 0s30-10 45-15M0 256c15-5 30-13 45-15s30 1 45 4s30 11 45 14s30 4 45 5s30 0 45 1s30 5 45 6s30 2 45 0s30-10 45-15M0 60c15-1 30-6 45-6s30 4 45 6s30 3 45 3s30-2 45-3s30-3 45-3s30 2 45 3s30 2 45 2s30-1 45-2M0 104c15 5 30 13 45 15s30-1 45-4s30-8 45-11s30-6 45-8s30-4 45-5s30-2 45-2s30 1 45 4s30 7 45 11M0 144c15 4 30 9 45 10s30-1 45-3s30-8 45-11s30-3 45-4s30-2 45-4s30-6 45-7s30-1 45 2s30 12 45 17M0 180c15 1 30 2 45 2s30-1 45-2s30-3 45-3s30 2 45 3s30 4 45 4s30-2 45-4s30-5 45-5s30 4 45 5M0 216c15-4 30-6 45-7s30-1 45 0s30 5 45 7s30 6 45 8s30 4 45 6s30 5 45 5s30 0 45-4s30-11 45-15'/%3E%3C/svg%3E");
	--_iz-tile: 360px;
	--_iz-weight: .65;
}
.iz-pattern--on-tint { --_iz-ink: #fff; --_iz-opacity: 1; }
.iz-pattern--on-dark { --_iz-ink: rgb(255 255 255 / .2); }
.iz-pattern--fade-start { --iz-pattern-fade: linear-gradient(to var(--_iz-end), transparent 12%, #000 72%); }
.iz-pattern--fade-end { --iz-pattern-fade: linear-gradient(to var(--_iz-end), #000 28%, transparent 88%); }
.iz-pattern--fade-edges { --iz-pattern-fade: radial-gradient(farthest-side, #000 45%, transparent); }
.iz-pattern--fade-center { --iz-pattern-fade: radial-gradient(farthest-side, transparent 38%, #000 92%); }
@supports (mask-composite: intersect) {
	.iz-pattern:not(.iz-pattern--after)::before, .iz-pattern.iz-pattern--after::after {
		content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; border-radius: inherit;
		background: var(--iz-pattern-ink, var(--_iz-ink));
		opacity: calc(var(--iz-pattern-opacity, var(--_iz-opacity)) * var(--_iz-weight, 1));
		mask: var(--_iz-motif) 0 0 / var(--iz-pattern-size, var(--_iz-tile)) auto repeat, var(--iz-pattern-fade, linear-gradient(#000 0 0)) 0 0 / 100% 100% no-repeat;
		mask-composite: intersect;
	}
}

/* ------------------------------------------------------------- page head */
.iz-pagehead {
	position: relative;
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	gap: var(--space-2) var(--space-4);
	align-items: center; /* 2026-09-29, owner review: the copy centred against the art, not sat on its baseline */
	padding: var(--space-block) clamp(var(--space-3), 3.4vw, var(--space-5));
	border-radius: var(--iz-r-lg);
	background: linear-gradient(160deg, #fff 0%, var(--surface-blue) 70%);
	border: 1px solid var(--iz-line-soft);
	overflow: hidden;
	isolation: isolate;
}
.iz-pagehead::after { /* one quiet leaf watermark, never behind text */
	content: ""; position: absolute; z-index: -1; inset-inline-end: -60px; bottom: -80px;
	width: 260px; aspect-ratio: 1; border-radius: 50%;
	background: radial-gradient(closest-side, rgb(120 154 131 / .16), transparent 70%);
}
.iz-pagehead__eyebrow { display: inline-flex; align-items: center; gap: var(--gap-inline); margin: 0; color: var(--secondary-600); font: var(--text-eyebrow); }
.iz-pagehead__eyebrow svg { width: 18px; height: 18px; color: var(--secondary-500); }
.iz-pagehead h1 { margin: var(--gap-title) 0 0; color: var(--iz-ink); font: var(--text-h1); text-wrap: balance; }
.iz-pagehead__summary { max-width: 60ch; margin: var(--gap-title) 0 0; color: var(--iz-text); font: var(--text-body-s); text-wrap: pretty; }
.iz-pagehead__actions { display: flex; flex-wrap: wrap; gap: var(--gap-inline); margin-top: var(--space-head); }
.iz-pagehead__art { width: clamp(96px, 14vw, 168px); aspect-ratio: 1; align-self: center; }
/* `overflow: hidden` on the full page head keeps its leaf watermark inside the card. The compact
 * variant has no card and no watermark, and clipping there swallows the focus ring of anything
 * that sits at its edge. */
.iz-pagehead--compact { padding: 0; border: 0; background: none; align-items: center; overflow: visible; }
.iz-pagehead--compact::after { display: none; }
.iz-pagehead--compact .iz-pagehead__art { width: 84px; }
/* The page head without its card — what the course, workshop, test and forum catalogues already
 * draw through their own `.catalog-head`/`.forum-head`/`.test-band` overrides, as a kit variant so
 * the blog can have it too (2026-09-29): inside the card the eyebrow and title started 40px in from
 * the crumb trail above them, the "extra right space" of the owner's review. The art stays. */
.iz-pagehead--plain { padding: 0; border: 0; border-radius: 0; background: none; overflow: visible; }
.iz-pagehead--plain::after { display: none; }
.iz-pagehead--dark { background: var(--primary-900) center / cover no-repeat; border-color: transparent; }
.iz-pagehead--dark h1 { color: #fff; }
.iz-pagehead--dark .iz-pagehead__summary { color: rgb(255 255 255 / .82); }
.iz-pagehead--dark .iz-pagehead__eyebrow { color: var(--secondary-200); }
/* A page head that carries a real picture rather than an art slot — an article's featured image.
 * The leaf frame is the course cover's, so the two detail pages open with the same gesture. It goes
 * above the copy once the columns stack, because a picture under its own caption reads as an
 * afterthought. */
.iz-pagehead--media { grid-template-columns: minmax(0, 1.1fr) minmax(260px, .9fr); gap: clamp(20px, 4vw, 48px); align-items: center; }
.iz-pagehead__media { margin: 0; aspect-ratio: 3 / 2; overflow: hidden; border-radius: var(--iz-leaf); background: linear-gradient(165deg, #edf5f7, #d7e6e9); box-shadow: var(--iz-shadow-2); }
.iz-pagehead__media img { display: block; width: 100%; height: 100%; object-fit: cover; }
@media (max-width: 860px) {
	.iz-pagehead--media { grid-template-columns: 1fr; }
	.iz-pagehead__media { order: -1; aspect-ratio: 16 / 9; }
}
@media (max-width: 640px) {
	.iz-pagehead { grid-template-columns: 1fr; }
	.iz-pagehead__art { grid-row: 1; width: 128px; justify-self: end; margin-bottom: calc(-1 * var(--space-1)); } /* 88 → 128, owner review 2026-09-29 */
	.iz-pagehead--compact .iz-pagehead__art { display: none; }
}

/* ------------------------------------------------------------- page stack
 * What an inner page opens with, in order: breadcrumb, page head, then whatever bar or toolbar
 * the page carries. Here because every converted template needs the same three gaps and the same
 * top padding, and three of them reached for an inline style to get it. */
/* `minmax(0, 1fr)`, not the implicit `auto` track. An auto track is sized to its widest child's
 * max-content, so one `white-space: nowrap` child — the breadcrumb — made this column wider than
 * the screen and every sibling stretched to match. The ticket thread, which has the site's longest
 * crumb trail, overflowed by 7px at 390. A 1fr track with a zero floor can never exceed its
 * container, and the crumb trail scrolls inside itself as it was always meant to. */
.iz-pagestack { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-head); padding-block-start: var(--space-block); }
/* Inside the account shell `.acct` already pays for the page's top padding, and paying twice drops
 * the content column below the top of the nav card. */
.acct .iz-pagestack { padding-block-start: 0; }

/* ------------------------------------------------------------- breadcrumb */
/* `min-width: 0` is what makes `overflow-x: auto` above actually work. As a grid or flex item the
 * crumb trail defaults to `min-width: auto`, which is its own min-content — and since it is
 * `white-space: nowrap`, that is the full untruncated trail. So instead of scrolling inside itself
 * it pushed the whole page column wider than the screen; the ticket thread, with the site's
 * longest breadcrumb, overflowed by 7px at 390. */
.iz-crumbs { min-width: 0; display: flex; align-items: center; gap: var(--gap-inline); margin: 0; padding: 0; overflow-x: auto; scrollbar-width: none; color: var(--iz-ink-soft); font: var(--text-caption); font-weight: 500; white-space: nowrap; mask-image: linear-gradient(to left, #000 88%, transparent); }
.iz-crumbs::-webkit-scrollbar { display: none; }
/* 32px drawn, 44px to a finger: the ::after pads the hit area without moving the row. */
.iz-crumbs a { position: relative; display: inline-flex; min-height: 32px; min-inline-size: 44px; align-items: center; justify-content: center; color: var(--iz-ink-soft); text-decoration: none; border-radius: 6px; transition: color .16s var(--iz-ease); }
.iz-crumbs a::after { content: ""; position: absolute; inset: -6px -4px; }
.iz-crumbs a:focus-visible { outline: none; box-shadow: var(--iz-focus); }
.iz-crumbs i { font-size: var(--iz-icon-xs); opacity: .6; }
.iz-crumbs strong { color: var(--iz-ink); font-weight: 600; }
@media (hover: hover) and (pointer: fine) { .iz-crumbs a:hover { color: var(--primary-700); } }

/* ------------------------------------------------------------- status */
.iz-status {
	--bg: var(--tone-neutral-bg); --fg: var(--tone-neutral-fg);
	display: inline-flex; align-items: center; gap: var(--gap-inline); min-height: 26px; padding: 2px var(--pad-chip-x); /* 2px, not --pad-chip-y: the 26px min-height sets the pill's height, the padding only keeps a wrapped label off the edge */
	border-radius: 999px; background: var(--bg); color: var(--fg);
	font: var(--text-caption); font-weight: 600; white-space: nowrap;
}
/* No dot (2026-09-29, owner review): the tint and the word already carry the state, and the danger
 * tone keeps its icon. The dot went, and with it the ping that `--live` animated on it — the class
 * is still emitted by status.php and styles nothing. */
.iz-status i { margin-inline-start: -2px; font-size: var(--iz-icon-s); }
.iz-status--open      { --bg: var(--tone-open-bg); --fg: var(--tone-open-fg); }
.iz-status--success   { --bg: var(--tone-success-bg); --fg: var(--tone-success-fg); }
.iz-status--attention { --bg: var(--tone-attention-bg); --fg: var(--tone-attention-fg); }
.iz-status--danger    { --bg: var(--tone-danger-bg); --fg: var(--tone-danger-fg); }

/* count badge (nav, tabs) */
.iz-count { display: inline-grid; place-items: center; min-width: 22px; height: 22px; padding: 0 var(--space-0); border-radius: 999px; background: var(--primary-50); color: var(--primary-700); font-family: var(--font-body); font-size: var(--text-micro-size); line-height: 1; font-weight: 700; }
.iz-count--hot { background: var(--secondary-500); color: #fff; }

/* ------------------------------------------------------------- fields */
.iz-field { display: grid; gap: var(--gap-field); }
.iz-field > label, .iz-field__label { color: var(--iz-ink); font: var(--text-body-s); font-weight: 600; }
.iz-field__label small, .iz-field > label small { color: var(--iz-ink-soft); font-weight: 400; }
.iz-input, .iz-select, .iz-textarea {
	width: 100%; min-height: 48px; padding: var(--space-1) var(--space-3); /* the height is the 48px floor, not a padding sum (spacing standard, rule 3) */
	border: 1.5px solid var(--iz-line); border-radius: 12px; background: #fff;
	color: var(--iz-ink); font: var(--text-body-s);
	transition: border-color .16s var(--iz-ease), box-shadow .16s var(--iz-ease), background-color .16s var(--iz-ease);
}
.iz-textarea { min-height: 132px; padding-block: var(--space-2); resize: vertical; field-sizing: content; max-height: 420px; }
.iz-select { appearance: none; padding-inline-end: calc(var(--space-3) + 12px + var(--space-2)); /* the arrow's inset, its 12px width, and a gap before the text */ background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none'%3E%3Cpath d='M1 1.5l5 5 5-5' stroke='%23435b63' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat left 16px center; }
.iz-input::placeholder, .iz-textarea::placeholder { color: var(--iz-ink-soft); }
.iz-input:focus, .iz-select:focus, .iz-textarea:focus { outline: none; border-color: var(--primary-400); box-shadow: var(--iz-focus); }
.iz-field__help { margin: 0; color: var(--iz-ink-soft); font: var(--text-caption); }
.iz-field__error { display: flex; gap: var(--gap-inline); align-items: center; margin: 0; color: var(--accent-700); font: var(--text-caption); font-weight: 600; }
.iz-field.is-invalid .iz-input, .iz-field.is-invalid .iz-textarea, .iz-field.is-invalid .iz-select { border-color: var(--accent-500); background-color: var(--accent-50); } /* `background-color`, not the shorthand: the shorthand reset `background-image` and an invalid select lost its arrow */
.iz-field__row { display: flex; justify-content: space-between; gap: var(--gap-inline); }
.iz-field__count { color: var(--iz-ink-soft); font: var(--text-caption); font-weight: 500; font-variant-numeric: tabular-nums; }
.iz-ltr { direction: ltr; unicode-bidi: isolate; text-align: left; }

/* choice chips (radio / checkbox as chips) */
.iz-choices { display: flex; flex-wrap: wrap; gap: var(--gap-inline); margin: 0; padding: 0; border: 0; }
.iz-choice { position: relative; }
.iz-choice input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
/* `> span`: the chip is the input's sibling. As a descendant selector this reached any span inside
 * the chip too and drew a second pill around a nested count (search.css had to undo it). */
.iz-choice > span {
	display: inline-flex; align-items: center; gap: var(--gap-inline); min-height: 44px; padding: var(--space-1) var(--space-3);
	border: 1.5px solid var(--iz-line); border-radius: 999px; background: #fff; color: var(--iz-text);
	font: var(--text-body-s); font-weight: 600;
	transition: border-color .16s var(--iz-ease), background-color .16s var(--iz-ease), color .16s var(--iz-ease), transform .16s var(--iz-ease-out);
}
.iz-choice > span i { font-size: var(--iz-icon-m); color: var(--primary-500); }
.iz-choice input:checked + span { border-color: var(--secondary-500); background: var(--secondary-50); color: var(--secondary-700); }
.iz-choice input:checked + span i { color: var(--secondary-600); }
.iz-choice input:focus-visible + span { box-shadow: var(--iz-focus); }
.iz-choice input:active + span { transform: scale(var(--iz-press)); }
/* The option card below had a hover and the chip, the same control smaller, did not. */
@media (hover: hover) and (pointer: fine) { .iz-choice:hover input:not(:checked, :disabled) + span { border-color: var(--primary-200); } }

/* option cards (bigger radios: booking type, test answers) */
.iz-option { position: relative; display: block; }
.iz-option input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
.iz-option__body {
	display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--space-2); align-items: center;
	min-height: 60px; padding: var(--pad-row); border: 1.5px solid var(--iz-line); border-radius: var(--iz-r); background: #fff;
	transition: border-color .18s var(--iz-ease), background-color .18s var(--iz-ease), box-shadow .18s var(--iz-ease), transform .16s var(--iz-ease-out);
}
.iz-option__mark { width: 22px; height: 22px; border: 2px solid #b8c7ca; border-radius: 50%; display: grid; place-items: center; transition: border-color .18s var(--iz-ease); }
.iz-option__mark::after { content: ""; width: 10px; height: 10px; border-radius: 50%; background: var(--secondary-500); scale: 0; transition: scale .22s var(--iz-ease-out); }
.iz-option__title { color: var(--iz-ink); font: var(--text-body-s); font-weight: 600; }
.iz-option__meta { display: block; color: var(--iz-ink-soft); font: var(--text-caption); }
.iz-option__key { color: var(--iz-ink-soft); font-family: var(--font-body); font-size: var(--text-micro-size); line-height: 1; font-weight: 600; padding: var(--space-0) var(--space-1); border-radius: 6px; background: var(--iz-sunk); }
.iz-option input:checked + .iz-option__body { border-color: var(--secondary-500); background: var(--secondary-50); box-shadow: 0 0 0 1px var(--secondary-500) inset; }
.iz-option input:checked + .iz-option__body .iz-option__mark { border-color: var(--secondary-500); }
.iz-option input:checked + .iz-option__body .iz-option__mark::after { scale: 1; }
.iz-option input:focus-visible + .iz-option__body { box-shadow: var(--iz-focus); }
.iz-option input:active + .iz-option__body { transform: scale(var(--iz-press-lg)); }
@media (hover: hover) and (pointer: fine) { .iz-option:hover .iz-option__body { border-color: var(--primary-200); } }

/* file drop
 * Moved here from account.css 2026-09-26: `.iz-drop` is a kit primitive (documented in
 * design-system.md's component list) but its functional half — the real, absolutely-positioned
 * <input type="file"> that makes the whole card a hit area and keeps the control in the tab order,
 * plus the focus ring that answers it — lived only in account.css. Any future page that rendered
 * `.iz-drop` without loading account.css would have shown a raw, unstyled file input on top of the
 * card. The look and the function are one component now. */
.iz-drop { position: relative; display: grid; justify-items: center; gap: var(--space-1); padding: var(--space-4) var(--pad-row); border: 1.5px dashed #b8c7ca; border-radius: var(--iz-r); background: var(--iz-sunk); color: var(--iz-ink-soft); font: var(--text-body-s); text-align: center; cursor: pointer; transition: border-color .16s var(--iz-ease), background-color .16s var(--iz-ease), transform .16s var(--iz-ease-out); }
.iz-drop:active { transform: scale(var(--iz-press-lg)); }
@media (hover: hover) and (pointer: fine) { .iz-drop:hover { border-color: var(--primary-300); } }
.iz-drop i { font-size: var(--iz-icon-xl); color: var(--primary-500); }
.iz-drop b { color: var(--primary-700); font-weight: 600; }
/* A titled drop zone: the title on its own line above the sentence, on the card-title tier so it is
 * bolder than the 600 `<b>` lead it replaces (owner review, 2026-09-29). The zone's own 8px gap
 * would part them like two items; they are one label, so the sentence tucks up under it. */
.iz-drop__title { color: var(--primary-700); font: var(--text-h4); }
.iz-drop__text { margin-top: calc(-1 * var(--space-0)); color: var(--iz-ink-soft); font: var(--text-caption); } /* set here, not inherited: in the panel `.iz-field > label` (account.css) makes the whole zone 13/600, which left the old lead no bolder than its sentence */
.iz-drop.is-over, .iz-drop:focus-within { border-color: var(--primary-400); background: var(--primary-50); }
/* The real <input type="file"> covers the whole card at zero opacity rather than being hidden: the
 * card stays the hit area, the control stays in the tab order (a display:none input is unreachable
 * by keyboard), and a file dropped anywhere on it lands on the input and is handled natively — the
 * page's own script only adds the hover wash and the chips. */
.iz-drop input[type="file"] { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; margin: 0; cursor: pointer; }
.iz-drop:has(input:focus-visible) { box-shadow: var(--iz-focus); }
.iz-files { display: flex; flex-wrap: wrap; gap: var(--gap-inline); margin: 0; padding: 0; list-style: none; }
.iz-file { display: inline-flex; align-items: center; gap: var(--gap-inline); min-height: 40px; padding-block: var(--space-0); padding-inline: var(--space-2) var(--space-1); /* logical: the roomier side with the file icon, the tighter one with the remove control */ border: 1px solid var(--iz-line); border-radius: 10px; background: #fff; color: var(--iz-ink); font: var(--text-caption); font-weight: 500; text-decoration: none; }
.iz-file i { color: var(--primary-500); font-size: var(--iz-icon-m); }
.iz-file small { color: var(--iz-ink-soft); }
/* An image attachment shows as a thumbnail, never at its own pixel size (owner, 2026-10-01): it fits the
   message bubble's width and stops at 240px tall, whole picture kept. */
.iz-file { max-width: 100%; min-width: 0; }
.iz-file img { display: block; width: auto; height: auto; max-width: 100%; max-height: 240px; object-fit: contain; border-radius: 8px; }
/* A saved attachment is a download link; the chips tickets.js draws for a file not yet sent are
 * plain list items and stay as they are. The link was 40px tall, under the 44px floor, and had
 * neither the kit's focus ring nor a press. */
a.iz-file { min-height: 44px; transition: border-color .16s var(--iz-ease), background-color .16s var(--iz-ease), transform .16s var(--iz-ease-out); }
a.iz-file:active { transform: scale(var(--iz-press)); }
a.iz-file:focus-visible { outline: none; box-shadow: var(--iz-focus); }
@media (hover: hover) and (pointer: fine) { a.iz-file:hover { border-color: var(--primary-200); background: var(--primary-50); } }

/* OTP */
/* Six fixed-width boxes plus five gaps is a min-content floor the card cannot go below, so on a
 * narrow phone the row pushed the card wider than the screen and the first box was clipped off the
 * edge. The boxes shrink instead: a width that is a share of the row with a floor, so the group
 * always fits whatever it is given. 2.5rem keeps the tap target at 40px, which is the smallest the
 * row reaches before flex-basis takes over. */
.iz-otp { display: flex; gap: var(--gap-inline); direction: ltr; justify-content: center; min-width: 0; }
.iz-otp input { flex: 0 1 48px; min-width: 2.5rem; width: 48px; height: 56px; padding: 0; border: 1.5px solid var(--iz-line); border-radius: 12px; background: #fff; color: var(--iz-ink); font: var(--text-number-l); text-align: center; caret-color: var(--secondary-500); transition: border-color .16s var(--iz-ease), box-shadow .16s var(--iz-ease), transform .2s var(--iz-ease-out); }
.iz-otp input:focus { outline: none; border-color: var(--primary-400); box-shadow: var(--iz-focus); }
.iz-otp input:not(:placeholder-shown) { border-color: var(--secondary-400); }
@media (max-width: 400px) { .iz-otp { gap: var(--space-0); } .iz-otp input { flex-basis: 42px; width: 42px; min-width: 2rem; height: 52px; font-size: var(--text-number-m-size); } }

/* ------------------------------------------------------------- tabs (segmented, link-based) */
.iz-tabs { position: relative; display: inline-flex; gap: 2px; max-width: 100%; padding: var(--space-0); overflow-x: auto; scrollbar-width: none; border-radius: 14px; background: var(--iz-sunk); border: 1px solid var(--iz-line-soft); }
.iz-tabs::-webkit-scrollbar { display: none; }
.iz-tabs a, .iz-tabs button {
	position: relative; z-index: 1; display: inline-flex; align-items: center; gap: var(--gap-inline); min-height: 44px; padding: var(--space-0) var(--space-3);
	border: 0; border-radius: 10px; background: none; color: var(--iz-text); font: var(--text-body-s); font-weight: 600; text-decoration: none; white-space: nowrap; cursor: pointer;
	transition: color .16s var(--iz-ease), transform .16s var(--iz-ease-out);
}
.iz-tabs a:active, .iz-tabs button:active { transform: scale(var(--iz-press)); }
@media (hover: hover) and (pointer: fine) { .iz-tabs :is(a, button):not([aria-current="page"], [aria-selected="true"]):hover { color: var(--iz-ink); } }
.iz-tabs [aria-current="page"], .iz-tabs [aria-selected="true"] { color: var(--iz-ink); }
.iz-tabs__pill { position: absolute; z-index: 0; top: var(--space-0); bottom: var(--space-0); border-radius: 10px; background: #fff; box-shadow: var(--iz-shadow-1); transition: inset-inline-start .32s var(--iz-ease-out), width .32s var(--iz-ease-out); }
.iz-tabs:not(:has(.iz-tabs__pill)) [aria-current="page"], .iz-tabs:not(:has(.iz-tabs__pill)) [aria-selected="true"] { background: #fff; box-shadow: var(--iz-shadow-1); }
.iz-tabs a:focus-visible, .iz-tabs button:focus-visible { outline: none; box-shadow: var(--iz-focus); }
/* The selected tab's resting shadow above outranks the plain focus rule, so tabbing onto the current
   tab changed nothing on screen. Same specificity plus :focus-visible: the ring wins. */
.iz-tabs:not(:has(.iz-tabs__pill)) [aria-current="page"]:focus-visible, .iz-tabs:not(:has(.iz-tabs__pill)) [aria-selected="true"]:focus-visible { box-shadow: var(--iz-focus); }

/* ------------------------------------------------------------- toolbar (search + filters + sort) */
.iz-toolbar { display: flex; flex-wrap: wrap; gap: var(--gap-inline); align-items: center; }
.iz-search { position: relative; flex: 1 1 260px; }
/* The field without a submit of its own (a filter row that applies with its form's button): a
 * leading glyph, decoration only. `> i` so it never reaches the glyph inside `.iz-search__go`. */
.iz-search > i { position: absolute; inset-inline-start: var(--space-3); top: 50%; translate: 0 -50%; color: var(--iz-ink-soft); font-size: var(--iz-icon-m); pointer-events: none; }
/* The search inputs carry dir="auto" so a Latin query reads left-to-right. While the field is
 * empty there is no strong character to infer from, so the input resolves to LTR — which put its
 * icon gutter on the left while the icon itself, positioned inside the RTL wrapper, painted on the
 * right, and left-aligned the Persian placeholder on an RTL page. `direction: rtl` fixes the box's
 * inline axis; `unicode-bidi: plaintext` keeps the per-line inference dir="auto" was there for. */
.iz-search .iz-input { direction: rtl; unicode-bidi: plaintext; padding-inline-start: calc(var(--space-3) + var(--iz-icon-m) + var(--space-1)); background: #fff; }
/* The search field that submits (2026-09-29, owner: "move the zoom icon to the left and make it
 * clickable and use it instead of the button"). The magnifier IS the submit: a real
 * `<button type="submit" aria-label="جست‌وجو">` at the field's inline end (the left, on this RTL
 * site), 44x44 inside the 48px field, so Enter and a form with no script work as before and the
 * separate text button is gone. One pattern for the search page, the 404 and every toolbar. */
.iz-search__go { position: absolute; inset-inline-end: 2px; top: 50%; translate: 0 -50%; display: grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 0; border-radius: var(--iz-r-sm); background: none; color: var(--primary-700); font-size: var(--iz-icon-m); line-height: 1; cursor: pointer; transition: background-color .16s var(--iz-ease), color .16s var(--iz-ease), transform .16s var(--iz-ease-out); }
.iz-search__go:active { transform: scale(var(--iz-press)); }
.iz-search__go:focus-visible { outline: none; box-shadow: var(--iz-focus); }
@media (hover: hover) and (pointer: fine) { .iz-search__go:hover { background: var(--primary-50); color: var(--primary-800); } }
.iz-search:has(> .iz-search__go) .iz-input { padding-inline: var(--space-3) calc(44px + var(--space-0)); } /* 44px is the button, a control size */
/* The browser's own clear control would sit under the button. */
.iz-search:has(> .iz-search__go) .iz-input::-webkit-search-cancel-button { display: none; }
.iz-toolbar .iz-select { flex: 0 1 200px; width: auto; }
.iz-toolbar__filter { display: none; }
@media (max-width: 720px) {
	.iz-toolbar .iz-select { display: none; }
	.iz-toolbar__filter { display: inline-flex; }
}

/* ------------------------------------------------------------- notice */
.iz-notice { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--space-2); align-items: start; padding: var(--pad-row); border-radius: 14px; background: var(--tone-open-bg); color: var(--tone-open-fg); font: var(--text-body-s); }
.iz-notice > i { font-size: var(--iz-icon-m); margin-top: var(--space-0); }
.iz-notice > .iz-brand-illustration { font-size: var(--icon-l); margin-top: 2px; }
.iz-notice p { margin: 0; }
/* Titled (2026-09-29, owner review): a larger icon and a bolder title share the first row, the text
 * runs below both at the full width, and the action closes the notice instead of hanging in a third
 * column. The title is a label for this one box, not a section heading, so it stays out of the
 * document outline; it takes the card-title tier because the owner asked for it bolder than the
 * `<b>` lead it replaces. */
.iz-notice--titled { grid-template-columns: minmax(0, 1fr); gap: var(--gap-title); padding: var(--pad-row); }
.iz-notice__head { display: flex; align-items: center; gap: var(--gap-inline); }
.iz-notice__head > i { flex: none; font-size: var(--iz-icon-xl); }
.iz-notice__head > .iz-brand-illustration { font-size: var(--icon-xl); }
.iz-notice .iz-notice__title { color: inherit; font: var(--text-h4); }
.iz-notice--quiet .iz-notice__title { color: var(--iz-ink); }
.iz-notice--titled > a { justify-self: start; display: inline-flex; align-items: center; min-height: 44px; margin-block: calc(-1 * var(--space-0)) calc(-1 * var(--space-1)); } /* the 44px target is taller than the line it holds; the negative margins keep it from adding room */
.iz-notice b { font-weight: 600; }
.iz-notice a { color: inherit; font-weight: 600; }
.iz-notice--success { background: var(--tone-success-bg); color: var(--tone-success-fg); }
.iz-notice--attention { background: var(--tone-attention-bg); color: var(--tone-attention-fg); }
.iz-notice--quiet { background: var(--iz-sunk); color: var(--iz-text); }

/* ------------------------------------------------------------- empty state */
.iz-empty { display: grid; justify-items: center; gap: var(--gap-title); padding: clamp(var(--space-4), 5vw, var(--space-6)) var(--pad-card); border-radius: var(--iz-r-lg); background: #fff; border: 1px solid var(--iz-line-soft); text-align: center; }
.iz-empty .art { width: 132px; height: 120px; margin-bottom: var(--space-4); }
/* 2026-09-29, owner review: the title a tier up (h4 → h3) with more room above it, and the sentence
 * at the card's full width instead of a 42ch column. The inline variant (a dashboard widget) keeps
 * the card-title tier and no extra room — it sits beside its art, not under it. */
.iz-empty h2, .iz-empty h3 { margin: 0; color: var(--iz-ink); font: var(--text-h3); }
.iz-empty p { max-width: none; width: 100%; margin: 0; color: var(--iz-text); font: var(--text-body-s); text-wrap: pretty; }
.iz-empty--inline h2, .iz-empty--inline h3 { margin: 0; font: var(--text-h4); }
.iz-empty__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--gap-inline); margin-top: var(--space-2); }
.iz-empty .iz-btn { margin-top: 0; }
.iz-empty--inline { grid-template-columns: auto minmax(0, 1fr) auto; justify-items: start; align-items: center; gap: var(--gap-title) var(--space-3); padding: var(--pad-row); text-align: start; }
/* The title and the sentence are placed, not left to auto-placement. Auto-placed, the sentence took
 * the next free cell: beside the title when the state had no art (measured 69-130px wide in a
 * dashboard widget) and in the action's column when it had art and no action. */
.iz-empty--inline > :is(h2, h3, p) { grid-column: 2; }
.iz-empty--inline:not(:has(> .art)) { grid-template-columns: minmax(0, 1fr) auto; }
.iz-empty--inline:not(:has(> .art)) > :is(h2, h3, p) { grid-column: 1; }
.iz-empty--inline .art { grid-row: span 2; width: 72px; height: 64px; margin: 0; }
.iz-empty--inline .iz-empty__actions { grid-row: 1 / span 2; grid-column: 3; margin: 0; }
.iz-empty--inline:not(:has(> .art)) .iz-empty__actions { grid-column: 2; }
@media (max-width: 560px) {
	.iz-empty--inline { grid-template-columns: auto minmax(0, 1fr); }
	.iz-empty--inline:not(:has(> .art)) { grid-template-columns: minmax(0, 1fr); }
	.iz-empty--inline .iz-empty__actions, .iz-empty--inline:not(:has(> .art)) .iz-empty__actions { grid-column: 1 / -1; grid-row: auto; justify-content: start; margin-top: var(--space-1); }
}

/* ------------------------------------------------------------- skeleton */
.iz-skel { display: block; border-radius: 8px; background: linear-gradient(90deg, #edf2f2 0%, #f6f9f9 40%, #edf2f2 80%) 0 0 / 300% 100%; }
@media (prefers-reduced-motion: no-preference) { .iz-skel { animation: iz-shimmer 1.6s linear infinite; } @keyframes iz-shimmer { to { background-position: -150% 0; } } }

/* ------------------------------------------------------------- pagination */
.iz-pager { display: flex; justify-content: center; align-items: center; gap: var(--gap-inline); margin-top: var(--space-block); }
.iz-pager a, .iz-pager span { display: inline-grid; place-items: center; min-width: 44px; height: 44px; padding: 0 var(--space-1); border-radius: 12px; color: var(--iz-text); font: var(--text-body-s); font-weight: 600; text-decoration: none; transition: background-color .16s var(--iz-ease), color .16s var(--iz-ease), transform .16s var(--iz-ease-out); }
.iz-pager a:active { transform: scale(var(--iz-press)); }
.iz-pager [aria-current="page"] { background: var(--primary-700); color: #fff; }
.iz-pager .is-edge, .iz-pager .prev, .iz-pager .next { border: 1px solid var(--iz-line); background: #fff; }
/* paginate_links( 'type' => 'list' ) wraps its links in a <ul class="page-numbers">. Flatten it so
 * the row above lays the links out rather than the list. */
.iz-pager ul { display: contents; margin: 0; padding: 0; list-style: none; }
.iz-pager li { display: contents; }
.iz-pager .dots { min-width: 24px; color: var(--iz-ink-soft); }
/* Every other interactive kit component gets the token ring; the pager's own links were falling
 * through to the browser's default outline instead — not invisible, but the one control on the
 * page not carrying the site's focus indicator. */
.iz-pager a:focus-visible { outline: none; box-shadow: var(--iz-focus); }
@media (hover: hover) and (pointer: fine) { .iz-pager a:not([aria-current]):hover { background: var(--primary-50); color: var(--primary-700); } }

/* ------------------------------------------------------------- card + section title (inner pages) */
.iz-card { padding: var(--pad-card); border: 1px solid var(--iz-line-soft); border-radius: var(--iz-r-lg); background: #fff; box-shadow: var(--iz-shadow-1); }
.iz-card--sunk { background: var(--surface-blue); box-shadow: none; }
.iz-h2 { display: flex; align-items: center; gap: var(--gap-inline); margin: 0 0 var(--space-head); color: var(--iz-ink); font: var(--text-h2); }
.iz-h2 svg { width: 18px; height: 18px; color: var(--secondary-500); flex: none; }
.iz-h2 small { margin-inline-start: auto; color: var(--iz-ink-soft); font: var(--text-caption); font-weight: 500; }

/* ------------------------------------------------------------- icon tile (rows) */
.iz-tile { display: grid; place-items: center; width: 48px; height: 48px; flex: none; border-radius: 14px; background: var(--primary-50); color: var(--primary-600); font-size: var(--iz-icon-l); }
.iz-tile--green { background: var(--secondary-50); color: var(--secondary-600); }
.iz-tile--coral { background: var(--accent-50); color: var(--accent-600); }
.iz-brand-illustration { flex: none; line-height: 1; }
.iz-tile .iz-brand-illustration { font-size: var(--icon-l); }

/* ------------------------------------------------------------- date tile (appointments, workshops, behavior) */
.iz-date { display: grid; justify-items: center; align-content: center; width: 64px; min-height: 72px; padding: var(--space-0); border-radius: 14px; background: var(--primary-700); color: #fff; text-align: center; flex: none; }
.iz-date small { font: var(--text-micro); opacity: .82; }
.iz-date b { font: var(--text-number-l); }
.iz-date--soft { background: var(--primary-50); color: var(--primary-700); }
.iz-date--past { background: var(--iz-sunk); color: var(--iz-ink-soft); }

/* ------------------------------------------------------------- meter */
.iz-meter { position: relative; display: block; height: 8px; border-radius: 999px; background: #e6eeee; overflow: hidden; }
.iz-meter > span { position: absolute; inset-block: 0; inset-inline-start: 0; width: var(--v, 0%); border-radius: inherit; background: linear-gradient(90deg, var(--secondary-400), var(--secondary-600)); transition: width .9s var(--iz-ease-out); }
.iz-meter--teal > span { background: linear-gradient(90deg, var(--primary-300), var(--primary-600)); }
.iz-meter--coral > span { background: linear-gradient(90deg, var(--accent-300), var(--accent-500)); }

/* ------------------------------------------------------------- rail (the vine that ties ordered things together) */
.iz-rail { position: relative; display: grid; gap: var(--space-stack); margin: 0; padding: 0; list-style: none; }
.iz-rail::before { content: ""; position: absolute; inset-block: 22px; inset-inline-start: 21px; width: 2px; border-radius: 2px; background: repeating-linear-gradient(180deg, var(--secondary-200) 0 6px, transparent 6px 11px); }
.iz-rail::after { content: ""; position: absolute; top: 22px; inset-inline-start: 21px; width: 2px; height: var(--rail-done, 0%); border-radius: 2px; background: var(--secondary-500); transition: height .9s var(--iz-ease-out); }
.iz-rail__node { position: relative; z-index: 1; display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; background: #fff; border: 2px solid var(--secondary-200); color: var(--secondary-700); font: var(--text-number-s); flex: none; }
.iz-rail__node.is-done { background: var(--secondary-500); border-color: var(--secondary-500); color: #fff; }
.iz-rail__node.is-now { border-color: var(--secondary-500); box-shadow: 0 0 0 5px var(--secondary-50); }

/* icon button */
.iz-iconbtn { display: inline-grid; place-items: center; width: 44px; height: 44px; border: 1px solid var(--iz-line); border-radius: 12px; background: #fff; color: var(--iz-text); font-size: var(--iz-icon-m); cursor: pointer; transition: background-color .16s var(--iz-ease), color .16s var(--iz-ease), transform .16s var(--iz-ease-out); }
.iz-iconbtn:active { transform: scale(var(--iz-press)); }
.iz-iconbtn:focus-visible { outline: none; box-shadow: var(--iz-focus); }
@media (hover: hover) and (pointer: fine) { .iz-iconbtn:hover { background: var(--primary-50); color: var(--primary-700); } }

/* stretched link helper for row-cards */
.iz-stretch::after { content: ""; position: absolute; inset: 0; z-index: 1; border-radius: inherit; }
.iz-rowcard { position: relative; }
.iz-rowcard:has(.iz-stretch:focus-visible) { box-shadow: var(--iz-focus); }
.iz-stretch:focus-visible { outline: none; }

/* ------------------------------------------------------------- catalogue bar
 * The spec files these under learning, but the course archive, the workshops page and the
 * assessments catalogue all draw the same bar, and two of the three never load learning.css.
 * The class names are the spec's, unchanged — only the file they live in differs. */
.learning-catalog__bar { display: grid; gap: var(--space-stack); margin: var(--space-block) 0 var(--space-head); }
.learning-catalog__head { display: flex; justify-content: space-between; align-items: center; gap: var(--gap-inline); color: var(--iz-ink-soft); font: var(--text-body-s); font-weight: 500; }
.learning-catalog__head b { color: var(--iz-ink); }
.iz-chips-scroll { display: flex; gap: var(--gap-inline); overflow-x: auto; scrollbar-width: none; padding: 2px; margin: -2px; }
.iz-chips-scroll::-webkit-scrollbar { display: none; }

@media (prefers-reduced-motion: reduce) {
	.learning-module::details-content, .iz-faq__row::details-content, .iz-tabs__pill, .learning-buybar, .acct-nav,
	.iz-meter > span, .iz-rail::after, .test-grow__fill, .test-grow__sprout, .test-ring .fg, .auth__step, .iz-toast, .cart-line { transition: none !important; }
}

/* ---------------------------------------------------------------------
 * v3 — the booking and checkout stepper, and the review list. Ported from Claude outputs/design-system-v3/css/public-v3.css,
 * which is one file for every public surface; the theme serves them on different
 * routes, so it is split the way the site is actually loaded.
 * --------------------------------------------------------------------- */
.iz-steps { position: relative; display: grid; grid-template-columns: repeat(var(--n, 4), minmax(0, 1fr)); margin: 0; padding: 0; list-style: none; counter-reset: s; }
.iz-steps li { position: relative; display: grid; justify-items: center; gap: var(--space-1); color: var(--iz-ink-soft); font: var(--text-caption); font-weight: 600; counter-increment: s; text-align: center; }
.iz-steps li::before { content: counter(s, persian); position: relative; z-index: 1; display: grid; place-items: center; width: 36px; height: 36px; border-radius: 50%; border: 2px solid var(--secondary-200); background: #fff; color: var(--secondary-700); font-family: var(--font-body); font-size: var(--text-number-s-size); line-height: var(--text-number-lh); font-weight: var(--text-number-weight); transition: background-color .3s var(--iz-ease), border-color .3s var(--iz-ease), color .3s var(--iz-ease), box-shadow .3s var(--iz-ease); }
.iz-steps li + li::after { content: ""; position: absolute; top: 17px; inset-inline-end: calc(50% + 22px); width: calc(100% - 44px); height: 2px; background: repeating-linear-gradient(90deg, var(--secondary-200) 0 6px, transparent 6px 11px); }
.iz-steps li.is-done::before { content: "✓"; background: var(--secondary-500); border-color: var(--secondary-500); color: #fff; font-family: var(--font-body); }
.iz-steps li.is-done + li::after, .iz-steps li.is-done + li.is-done::after { background: var(--secondary-500); }
.iz-steps li.is-now { color: var(--iz-ink); }
.iz-steps li.is-now::before { border-color: var(--secondary-500); box-shadow: 0 0 0 5px var(--secondary-50); }
@media (max-width: 520px) {
	/* 12px is the theme's floor for rendered text; the step labels were the last thing below it. */
	.iz-steps li { font-size: var(--text-micro-size); }
	.iz-steps li::before { width: 30px; height: 30px; font-size: var(--text-caption-size); }
	.iz-steps li + li::after { top: 14px; inset-inline-end: calc(50% + 18px); width: calc(100% - 36px); }
}
.iz-review { display: grid; gap: 0; margin: 0; padding: var(--space-0) var(--pad-row); border: 1px solid var(--iz-line-soft); border-radius: 18px; background: #fff; }
.iz-review div { display: grid; grid-template-columns: 22px 120px minmax(0, 1fr) auto; gap: var(--space-2); align-items: center; min-height: 52px; }
.iz-review div + div { border-top: 1px dashed var(--iz-line-soft); }
.iz-review i { color: var(--primary-500); font-size: var(--iz-icon-m); }
.iz-review dt { color: var(--iz-ink-soft); font: var(--text-caption); font-weight: 500; }
.iz-review dd { margin: 0; color: var(--iz-ink); font: var(--text-body-s); font-weight: 600; }
.iz-review :is(a, button) { color: var(--primary-700); font: var(--text-button-s); }
@media (max-width: 520px) {
	.iz-review div { grid-template-columns: 22px minmax(0, 1fr) auto; }
	.iz-review dt { grid-column: 2; grid-row: 1; }
	.iz-review dd { grid-column: 2; grid-row: 2; padding-bottom: var(--space-1); }
	.iz-review :is(a, button) { grid-row: 1 / span 2; grid-column: 3; }
}

/* ---------------------------------------------------------------- the FAQ accordion
 * One component for a course, a workshop, a test, a service and the booking policy — its own
 * docblock in template-parts/learning/faq.php names all five. It lived in learning.css, which
 * only the learning routes load, so a test page that used the shared part rendered it unstyled
 * and the test page grew a hand-copy instead. kit.css already reduced its motion here, which is
 * the same admission: a component five routes render belongs in the global sheet.
 */
.iz-faq { display: grid; grid-template-columns: minmax(220px, .8fr) minmax(0, 1.6fr); gap: clamp(20px, 4vw, 48px); align-items: start; }
.iz-faq__intro { position: sticky; top: 96px; display: grid; gap: var(--gap-title); }
.iz-faq__intro h2 { margin: 0; color: var(--iz-ink); font: var(--text-h2); }
.iz-faq__intro p { margin: 0; color: var(--iz-text); font: var(--text-body-s); }
.iz-faq__intro .art { width: 120px; height: 150px; margin-bottom: var(--space-2); } /* first in the column since 2026-09-29 */
.iz-faq__list { display: grid; gap: var(--gap-list); }
.iz-faq__row { border: 1px solid var(--iz-line-soft); border-radius: 18px; background: #fff; transition: background-color .24s var(--iz-ease), border-color .24s var(--iz-ease), box-shadow .24s var(--iz-ease); interpolate-size: allow-keywords; }
.iz-faq__row[open] { background: #fff; border-color: var(--iz-line-soft); } /* white like a closed row, owner review 2026-09-29; the open state is the turned icon and the answer */
.iz-faq__row > summary { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--space-2); align-items: center; min-height: 64px; padding: var(--space-2) var(--pad-row); cursor: pointer; list-style: none; border-radius: 18px; color: var(--iz-ink); font: var(--text-body); font-weight: 600; }
.iz-faq__row > summary::-webkit-details-marker { display: none; }
.iz-faq__row > summary:focus-visible { outline: none; box-shadow: var(--iz-focus); }
/* iz-faq__num is a numeral (§2.2), so it comes off Pinar onto the number tier rather than the display face. */
.iz-faq__num { color: var(--secondary-500); font-family: var(--font-body); font-size: var(--text-number-s-size); line-height: var(--text-number-lh); font-weight: var(--text-number-weight); font-variant-numeric: tabular-nums; min-width: 22px; }
.iz-faq__icon { position: relative; width: 32px; height: 32px; border-radius: 50%; background: var(--iz-sunk); transition: background-color .24s var(--iz-ease), rotate .34s var(--iz-ease-out), scale .16s var(--iz-ease-out); }
/* The press lands on the disc, the row's visible handle: a full-width row drawing in by 3% reads as
 * the page flinching, and the summary alone cannot scale without leaving its own border behind. */
.iz-faq__row > summary:active .iz-faq__icon { scale: .9; }
.iz-faq__icon::before, .iz-faq__icon::after { content: ""; position: absolute; inset-block-start: 50%; inset-inline-start: 50%; width: 12px; height: 2px; margin-block-start: -1px; margin-inline-start: -6px; border-radius: 2px; background: var(--primary-700); transition: rotate .34s var(--iz-ease-out), opacity .2s var(--iz-ease); }
.iz-faq__icon::after { rotate: 90deg; }
.iz-faq__row[open] .iz-faq__icon { background: var(--primary-50); rotate: 180deg; }
.iz-faq__row[open] .iz-faq__icon::after { rotate: 0deg; opacity: 0; }
.iz-faq__row::details-content { block-size: 0; overflow: clip; transition: block-size .34s var(--iz-ease-out), content-visibility .34s allow-discrete; }
.iz-faq__row[open]::details-content { block-size: auto; }
.iz-faq__answer { padding: 0 var(--pad-row) var(--pad-row); padding-inline-start: calc(var(--pad-row) + 22px + var(--space-2)); /* under the question: the row's padding, the numeral's 22px column, the gap */ color: var(--iz-text); font: var(--text-body-s); }
.iz-faq__answer p { margin: 0 0 var(--space-1); } /* flow content */
@media (hover: hover) and (pointer: fine) {.iz-faq__row:not([open]):hover { border-color: var(--primary-100); box-shadow: var(--iz-shadow-1); }
}
@media (max-width: 820px) {.iz-faq { grid-template-columns: 1fr; }
.iz-faq__intro { position: static; grid-template-columns: minmax(0, 1fr) auto; align-items: end; }
.iz-faq__intro .art { grid-row: 1 / span 2; grid-column: 2; width: 72px; height: 90px; margin-bottom: 0; }
.iz-faq__answer { padding-inline-start: var(--pad-row); }
}

/* ---------------------------------------------------------------- the audio player
 * The v3 specimen draws a decorative waveform. This keeps the real <input type="range">
 * audio-player.js builds instead — it is the only keyboard-operable way to scrub, and bars that do
 * not correspond to the sound would be decoration pretending to be data. The slider wears the
 * specimen's clothes: round eucalyptus play button, a slim filled track, tabular time remaining,
 * and the dark variant for the cover dock. Every hook audio-player.js reads is unchanged
 * (`.iz-audio__el`, `.iz-audio__ui`, `.iz-audio__play`, `.iz-audio__seek`, `.iz-audio__time`,
 * `.is-playing`, `--played`, `data-iz-audio`, `data-iz-audio-ready`). decisions.md 2026-09-11.
 *
 * Here rather than in learning.css since 2026-09-19: a course page and an article both render it,
 * and the article route does not load learning.css — the same reason the FAQ accordion is here. */
.iz-audio { display: grid; gap: var(--space-1); padding: var(--space-2) var(--pad-row); border-radius: 16px; background: #fff; border: 1px solid var(--iz-line-soft); }
.iz-audio__el { width: 100%; }
.iz-audio[data-iz-audio-ready] .iz-audio__el { display: none; }
/* Left to right on a right-to-left page, on purpose: play, then the track filling from the left,
 * then the time. A timeline is not a sentence, and mirrored it read as a player running backwards. */
.iz-audio__ui { display: grid; grid-template-columns: 44px minmax(0, 1fr) auto; gap: var(--space-2); align-items: center; direction: ltr; }
.iz-audio__play { display: grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 50%; background: var(--secondary-500); color: #fff; font-family: var(--font-body); font-size: var(--iz-icon-m); cursor: pointer; transition: transform .16s var(--iz-ease-out), background-color .16s var(--iz-ease); }
.iz-audio__play:active { transform: scale(var(--iz-press)); }
.iz-audio__play:focus-visible { outline: none; box-shadow: var(--iz-focus); }
.iz-audio__seek { --played: 0%; width: 100%; height: 6px; margin: 0; padding: 0; border-radius: 999px; cursor: pointer; -webkit-appearance: none; appearance: none; background: linear-gradient(to right, var(--secondary-500) var(--played), var(--primary-100) var(--played)); }
.iz-audio__seek::-webkit-slider-thumb { -webkit-appearance: none; width: 14px; height: 14px; border: 2px solid #fff; border-radius: 50%; background: var(--secondary-600); box-shadow: 0 1px 3px rgb(22 75 96 / .4); }
.iz-audio__seek::-moz-range-thumb { width: 14px; height: 14px; border: 2px solid #fff; border-radius: 50%; background: var(--secondary-600); }
.iz-audio__seek:focus-visible { outline: none; box-shadow: var(--iz-focus); }
.iz-audio__time { color: var(--iz-ink-soft); font-family: var(--font-body); font-size: var(--text-micro-size); line-height: 1; font-weight: 600; font-variant-numeric: tabular-nums; direction: ltr; }
.iz-audio--onDark { background: rgb(255 255 255 / .08); border-color: rgb(255 255 255 / .12); }
.iz-audio--onDark .iz-audio__play { background: #fff; color: var(--primary-800); }
.iz-audio--onDark .iz-audio__seek { background: linear-gradient(to right, #fff var(--played), rgb(255 255 255 / .28) var(--played)); }
.iz-audio--onDark .iz-audio__seek::-webkit-slider-thumb { border-color: var(--primary-700); background: #fff; }
.iz-audio--onDark .iz-audio__seek::-moz-range-thumb { border-color: var(--primary-700); background: #fff; }
.iz-audio--onDark .iz-audio__time { color: rgb(255 255 255 / .75); }
@media (hover: hover) and (pointer: fine) { .iz-audio__play:hover { background: var(--secondary-600); } }

/* ---------------------------------------------------------------- the time chip
 * A bookable time, on the booking calendar and on an appointment's change form. It lived in
 * booking.css and account.css byte-for-byte identically, and both sheets load together on the
 * appointment detail page — two copies of one component, which is how the card drift started.
 * A time is always isolated LTR, whatever the page's direction.
 */
.iz-slots { display: flex; flex-wrap: wrap; gap: var(--gap-inline); margin-top: var(--space-stack); }
.iz-slot { min-width: 88px; min-height: 44px; padding: var(--space-1) var(--space-3); border: 1.5px solid var(--iz-line); border-radius: 12px; background: #fff; color: var(--iz-ink); font: var(--text-button); font-variant-numeric: tabular-nums; direction: ltr; cursor: pointer; transition: border-color .16s var(--iz-ease), background-color .16s var(--iz-ease), transform .16s var(--iz-ease-out); }
.iz-slot[aria-pressed="true"] { border-color: var(--secondary-500); background: var(--secondary-50); color: var(--secondary-700); box-shadow: 0 0 0 1px var(--secondary-500) inset; }
.iz-slot:disabled { color: #a9b7ba; text-decoration: line-through; background: var(--iz-sunk); border-color: transparent; cursor: not-allowed; }
.iz-slot:active:not(:disabled) { transform: scale(var(--iz-press)); }
.iz-slot:focus-visible { outline: none; box-shadow: var(--iz-focus); }
@media (hover: hover) and (pointer: fine) { .iz-slot:not(:disabled, [aria-pressed="true"]):hover { border-color: var(--primary-200); } }

/* ---------------------------------------------------------------- the toast
 * One bar at the bottom of the viewport, for an undo after a removal: the cart's line and the
 * behaviour log's entry. It lived in commerce.css and behavior.css byte-for-byte identically and
 * both can load on one page after a soft navigation, so it is said once here. `a` as well as
 * `button`: the cart's undo is WooCommerce's own `undo_item` URL, so the control that carries it
 * has to be a link to keep working with no JavaScript. The four-value padding as logical values:
 * the roomier side stays with the sentence and the tighter one with the control, in either
 * writing mode. `.is-gone` is the six-second exit; it mirrors the @starting-style entry. */
.iz-toast { position: fixed; inset-inline: 0; bottom: 20px; z-index: 80; width: max-content; max-width: calc(100% - 32px); margin-inline: auto; display: flex; align-items: center; gap: var(--space-2); padding-block: var(--space-1); padding-inline: var(--space-3) var(--space-1); border-radius: 14px; background: var(--neutral-dark); color: #fff; font: var(--text-body-s); font-weight: 500; box-shadow: 0 16px 40px -12px rgb(13 47 61 / .5); transition: translate .36s var(--iz-ease-out), opacity .36s var(--iz-ease-out); }
.iz-toast button, .iz-toast a { display: inline-flex; align-items: center; min-height: 44px; padding: var(--pad-chip-y) var(--pad-chip-x); /* 44px: it was 36, under the touch floor */ border: 0; border-radius: 10px; background: rgb(255 255 255 / .12); color: #fff; font: var(--text-button-s); text-decoration: none; white-space: nowrap; cursor: pointer; }
.iz-toast a:focus-visible, .iz-toast button:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.iz-toast.is-gone { translate: 0 16px; opacity: 0; }
@media (hover: hover) and (pointer: fine) { .iz-toast button:hover, .iz-toast a:hover { background: rgb(255 255 255 / .22); } }
@starting-style { .iz-toast { translate: 0 16px; opacity: 0; } }

/* ---------------------------------------------------------------- press guard
 * A disabled control does not answer a press. Native :disabled buttons mostly never match :active,
 * but an `aria-disabled` link does, and so does a disabled control inside a label the pointer
 * lands on — so the kit says it once for every pressable it defines. `.iz-btn`'s own guard is in
 * chrome.css beside it. */
:is(.iz-iconbtn, .iz-search__go, .iz-tabs a, .iz-tabs button, .iz-pager a, .iz-slot, .iz-audio__play, a.iz-file):is(:disabled, [aria-disabled="true"]):active,
:is(.iz-choice, .iz-option) input:disabled:active + * { transform: none; }

/* Workshop venue map (isazadeh_venue_map(), 2026-09-30): a grey-bordered box, no shadow. */
.iz-venue-map { overflow: hidden; margin-top: var(--space-1); border: 1px solid var(--iz-line-soft); border-radius: var(--radius-input); background: #eef0f2; aspect-ratio: 16 / 9; min-height: 200px; max-height: 260px; width: 100%; }
.iz-venue-map iframe { display: block; width: 100%; height: 100%; border: 0; }
