/*
 * Base elements and the controls every module uses: buttons (one kind of raised round button, one kind of pill),
 * flat rows, cards, fields (switches, segmented choices and settings rows: css/controls.css). A module writes only what is its own, with its own prefix
 * (.eo-…, .gr-…); everything here is unprefixed and belongs to the frame (css/tokens.css has the values).
 */
*,
*::before,
*::after {
	box-sizing: border-box;
}

html {
	-webkit-text-size-adjust: 100%;
	-webkit-tap-highlight-color: transparent; /* our buttons show their own press */
}

@media (hover: none) {
	:focus:not(:focus-visible) {
		outline: none;
	}
}

body {
	margin: 0;
	background: var(--bg);
	color: var(--text);
	font-family: var(--font);
	font-size: calc(14px * var(--ui-scale));
	line-height: 1.5;
}

a {
	color: var(--text-strong);
	font-weight: 500;
	text-underline-offset: 2px;
}

button,
input,
select,
textarea {
	font: inherit;
	color: inherit;
}

[hidden] {
	display: none !important;
}

:focus-visible {
	outline: 2px solid var(--border-strong);
	outline-offset: 2px;
}

/* ---- buttons ----
   .round                a raised round button: the avatar, ☰, ⋯, "?" (32 px; .round--sm 26 px)
   .btn                  a raised pill with words (.btn-secondary says the same: the programs' name for it)
   .btn--solid           the one thing to do (.btn-primary: the same, as wide as its form unless .btn-auto)
   .btn--danger          words in red;  .btn--danger-solid / .btn-danger-solid: red, for "delete" in a question
   .icon-btn             a flat square icon button (in toolbars), .icon-btn-sm smaller; .log-lang a log box's 「EN」
   .more-btn             the 「⋯」 on a row or in a box (its menu): flat and round, one look wherever it is
   One look for all of them: lit from the top left, sinking while pressed. */

.round,
.btn {
	display: inline-flex;
	flex: none;
	align-items: center;
	justify-content: center;
	gap: 6px;
	border: 1px solid var(--border);
	border-top-color: var(--edge-top);
	border-bottom-color: var(--edge-bottom);
	background: var(--face), var(--surface);
	color: var(--text);
	box-shadow: var(--edge-light), var(--elev-1);
	text-decoration: none;
	cursor: pointer;
	transition:
		background-color var(--dur-quick),
		color var(--dur-quick),
		box-shadow var(--dur-quick),
		scale var(--dur) var(--ease-grow);
}

.round {
	width: 32px;
	height: 32px;
	padding: 0;
	border-radius: 50%;
	color: var(--muted);
}

.round--sm {
	width: 26px;
	height: 26px;
}

.round:hover {
	color: var(--text-strong);
}

.btn {
	min-height: 34px;
	padding: 6px 14px;
	border-radius: 999px;
	font-size: calc(14px * var(--ui-scale));
	font-weight: 500;
	white-space: nowrap;
}

/* a button's picture keeps its size: a label too long for the button squeezed it to nothing (Reassurance's panel
   2026-11-01: a dot, then the words off the middle) */
.btn > svg {
	flex: none;
}

.btn:hover:not(:disabled) {
	background: var(--face), var(--surface-2);
}

.btn--solid,
.btn-primary {
	border-color: var(--accent);
	background: var(--face-solid), var(--accent);
	color: var(--accent-text);
	box-shadow: var(--btn-solid-shadow);
}

.btn--solid:hover:not(:disabled),
.btn-primary:hover:not(:disabled) {
	background: var(--face-solid), var(--accent-hover);
}

.btn-primary {
	width: 100%;
}

.btn-auto {
	width: auto;
	align-self: flex-start;
}

.btn--solid:disabled,
.btn-primary:disabled {
	border-color: var(--well-top) var(--well-bottom) var(--well-bottom) var(--well-top);
	background: var(--well-bg);
	color: var(--faint);
	box-shadow: var(--well-shadow);
	opacity: 1;
	cursor: not-allowed;
}

.btn--danger,
.btn-danger {
	color: var(--danger);
}

.btn--danger-solid,
.btn-danger-solid {
	border-color: var(--danger);
	background: var(--face-solid), var(--danger);
	color: var(--on-fill);
	box-shadow: var(--btn-solid-shadow);
}

.btn--danger-solid:hover:not(:disabled),
.btn-danger-solid:hover:not(:disabled) {
	background: var(--face-solid), var(--danger);
	filter: brightness(1.08);
}

.btn-sm {
	min-height: 28px;
	padding: 3px 10px;
	font-size: calc(12px * var(--ui-scale));
}

.round:active:not(:disabled),
.btn:active:not(:disabled) {
	border-top-color: var(--edge-bottom);
	border-bottom-color: var(--edge-top);
	box-shadow: var(--btn-pressed);
	scale: 0.96;
	transition-duration: 80ms;
}

.round:disabled,
.btn:disabled {
	opacity: 0.5;
	cursor: default;
}

.icon-btn {
	display: inline-flex;
	flex: none;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	padding: 0;
	border: 0;
	border-radius: var(--radius-sm);
	background: none;
	color: var(--muted);
	cursor: pointer;
	transition:
		background-color var(--dur-quick),
		color var(--dur-quick),
		scale var(--dur) var(--ease-grow);
}

.icon-btn:hover:not(:disabled) {
	background: var(--surface-2);
	color: var(--text-strong);
}

.icon-btn:active:not(:disabled) {
	scale: 0.92;
	transition-duration: 80ms;
}

.icon-btn:disabled {
	opacity: 0.35;
	cursor: default;
}

.icon-btn-sm {
	width: 28px;
	height: 28px;
}

/* a log box's 「EN」 (components/log-lang.js): two letters in place of an icon; lit while the box is in English */
.icon-btn.log-lang {
	width: auto;
	min-width: 28px;
	padding: 0 6px;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.04em;
}

.icon-btn.log-lang[aria-pressed="true"] {
	background: var(--surface-2);
	color: var(--text-strong);
}

/* 「⋯」 (one look: the user 2026-10-27 — the search box's and AI 助手's looked unlike when pointed at): no face until pointed
   at or its menu is open; its size is where it is (28 px unless said) */
.more-btn {
	display: inline-flex;
	flex: none;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: none;
	color: var(--muted);
	cursor: pointer;
	transition:
		background-color var(--dur-quick),
		color var(--dur-quick),
		scale var(--dur) var(--ease-grow);
}

/* (a veil, not a color of its own: on a row already lit by the pointer — AI 助手's — a gray of the row's own was not seen) */
.more-btn:hover:not(:disabled),
.more-btn[aria-expanded="true"] {
	background: color-mix(in srgb, var(--text-strong) 9%, transparent);
	color: var(--text-strong);
}

.more-btn:active:not(:disabled) {
	scale: 0.92;
	transition-duration: 80ms;
}

/* Words that are a link or a button, with no frame or face (「‹ 返回」, 「进阶 ›」, 「回到首页」, 「去账户管理 ›」…; UI-RULES
   第 4 条, the user 2026-10-28: 这一类文字链接全部要有鼠标悬停效果): their colour is their own (muted, the accent, a link's
   blue); under the mouse they darken to --text-strong (a module's own: --text-link-hover, e.g. a blue one staying blue)
   and an underline comes in under the words (one in a sentence keeps a faint one at rest, --text-link-line; a dotted
   one at rest turns solid). Not on a phone: no hover there. */
/* (a <button> with it has no face of its own: it looks like words. Zero specificity: a page's own rule wins) */
:where(button.text-link) {
	padding: 0;
	border: 0;
	background: none;
	color: inherit;
	font: inherit;
}

.text-link {
	text-decoration-line: underline;
	text-decoration-color: var(--text-link-line, transparent);
	text-decoration-thickness: 1px;
	text-underline-offset: 3px;
	cursor: pointer;
	transition:
		color var(--dur-quick),
		text-decoration-color var(--dur-quick);
}

@media (hover: hover) {
	.text-link:hover {
		color: var(--text-link-hover, var(--text-strong));
		text-decoration-color: currentColor;
		text-decoration-style: solid;
	}
}

.text-link:focus-visible {
	outline: 2px solid var(--border-strong);
	outline-offset: 2px;
	border-radius: 2px;
}

/* a flat button inside a card or window (a row of a menu, a list's entry): no face of its own until hovered */
.flat {
	display: flex;
	align-items: center;
	gap: 10px;
	width: 100%;
	min-height: 36px;
	padding: 6px 10px;
	border: 0;
	border-radius: var(--radius-sm);
	background: none;
	color: var(--text);
	text-align: left;
	text-decoration: none;
	cursor: pointer;
	transition: background-color var(--dur-quick), color var(--dur-quick);
}

.flat:hover {
	background: var(--surface-2);
	color: var(--text-strong);
}

.flat.is-current {
	background: var(--surface-2);
	color: var(--text-strong);
	font-weight: 600;
}

.flat svg {
	flex: none;
	color: var(--muted);
}

.flat.is-current svg {
	color: var(--text-strong);
}

.flat > span:not([class]),
.flat > .flat-label {
	flex: 1;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* ---- cards ---- */

.card {
	padding: 16px 18px;
	border: 1px solid var(--border);
	border-top-color: var(--edge-top);
	border-bottom-color: var(--edge-bottom);
	border-radius: var(--radius-card);
	background: var(--surface);
	box-shadow: var(--edge-light), var(--elev-1);
}

.card + .card {
	margin-top: 12px;
}

.card-title {
	margin: 0 0 4px;
	font-size: calc(15px * var(--ui-scale));
	font-weight: 600;
	color: var(--text-strong);
}

.muted {
	color: var(--muted);
}

/* ---- a small rounded label (.pill-on: something switched on) ---- */

.pill {
	flex: none;
	padding: 2px 10px;
	border-radius: 999px;
	background: var(--surface-2);
	color: var(--muted);
	font-size: calc(12px * var(--ui-scale));
}

.pill-on {
	background: var(--ok-bg);
	color: var(--ok);
}

/* ---- an arrow pointing right (lib/arrows.js: 幻灯片's head): a 2 px line stopping halfway into the 10 px head, on
   whole pixels (a 1.5 px line came out 1 px here and 2 px there); the program sets its width and margins, and its
   colour (currentColor) ---- */

.arrow {
	position: relative;
	display: inline-block;
	flex: 0 1 auto;
	width: 30px;
	min-width: 14px;
	height: 10px;
	color: var(--muted);
	vertical-align: middle;
}

.arrow::before {
	content: "";
	position: absolute;
	top: 4px;
	right: 5px;
	left: 0;
	height: 2px;
	background: currentColor;
}

/* dashed as 幻灯片's "dash": 4 widths on, 3 off */
.arrow.is-dashed::before {
	background: repeating-linear-gradient(to right, currentColor 0 8px, transparent 8px 14px);
}

.arrow-head {
	position: absolute;
	top: 0;
	right: 0;
	display: block;
}

/* ending in a square on its corner (12 px across): taller than the head, the line stopping at its middle */
.arrow.is-diamond {
	height: 12px;
}

.arrow.is-diamond::before {
	top: 5px;
	right: 6px;
}

/* the half head: the line runs to its tip; the hollow one: the line stops at its back */
.arrow.is-half::before {
	right: 0;
}

.arrow.is-hollow::before {
	right: 9px;
}

/* ---- text field (.input: the programs' name for it) ---- */

.field,
.input {
	width: 100%;
	min-height: 36px;
	padding: 7px 12px;
	border: 1px solid var(--border);
	border-top-color: var(--edge-bottom);
	border-radius: var(--radius);
	background: var(--surface);
	box-shadow: var(--sunken);
	outline: none;
	transition: border-color var(--dur-quick);
}

.field::placeholder,
.input::placeholder {
	color: var(--faint);
}

.field:focus,
.input:focus {
	border-color: var(--border-strong);
	box-shadow: var(--sunken), 0 0 0 3px var(--focus-ring);
}

.field:disabled,
.input:disabled {
	opacity: 0.5;
	cursor: default;
}

/* a form: its fields one under another; what went wrong in red */
.form {
	display: flex;
	flex-direction: column;
	gap: var(--form-gap);
}

.form > .btn-primary {
	margin-top: 8px;
}

.form-error {
	margin: 0;
	color: var(--danger);
}

/* a choice from a list: a field with a drawn arrow (the system's own looks different everywhere) */
select.field,
select.input {
	padding-right: 32px;
	border-radius: 999px;
	appearance: none;
	-webkit-appearance: none;
	background:
		linear-gradient(45deg, transparent 50%, var(--muted) 50%) calc(100% - 17px) 50% / 5px 5px no-repeat,
		linear-gradient(-45deg, transparent 50%, var(--muted) 50%) calc(100% - 12px) 50% / 5px 5px no-repeat,
		var(--surface);
	cursor: pointer;
}

/* ---- the user's picture, or the name's first letter ---- */

.avatar {
	display: inline-flex;
	flex: none;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	color: var(--on-fill);
	font-weight: 600;
	line-height: 1;
	user-select: none;
}

.avatar-img {
	object-fit: cover;
	background: var(--surface-2);
}

/* a box that folds (lib/motion.js foldSlide): its frame and ground drawn as one shape behind what is in it, so that the
   shape's bottom edge can go along with what is under the fold (the box itself is its full height all the while) */
.fold-shape {
	position: relative;
	isolation: isolate;
	border: 1px solid transparent;
}

.fold-shape::before {
	content: "";
	position: absolute;
	inset: -1px;
	z-index: -1;
	border: 1px solid var(--fold-shape-border, var(--border));
	border-radius: var(--fold-shape-radius, var(--radius));
	background: var(--fold-shape-bg, var(--surface));
	pointer-events: none;
}

/* a row of components/fold-list.js: shut, 0fr; open, 1fr (slid by lib/motion.js slideBody) */
.fold-list-row {
	display: grid;
	grid-template-rows: 0fr;
}

.fold-list-row.is-open {
	grid-template-rows: 1fr;
}

/* (a box of its own: shut, nothing of what is in it stands, its padding and margins included) */
.fold-list-clip {
	min-height: 0;
	overflow: hidden;
}

/* 没有东西时页面中间那一块（图标 + 一两句话 + 也许一个按钮）。全项目这一份（UI-RULES 6，用户 2026-11-02）：程序不自己写居中，只定图标的样子。
   .empty-state--fill：在工作区正中，不管上面有多少标题和按钮（工作区要是定位的：.eo-drive 是）；不加：放在页面的流里，自己水平居中 */
.empty-state {
	grid-column: 1 / -1;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: var(--form-row-gap);
	padding: 60px 20px;
	color: var(--muted);
	text-align: center;
}

.empty-state p {
	margin: 0;
}

.empty-state--fill {
	position: absolute;
	inset: 0;
	padding: 20px;
	pointer-events: none;
}

.empty-state--fill :is(a, button) {
	pointer-events: auto;
}
