@layer theme { /* baseline, not center: a taller field (help sentence under the control) would push a * centered label off the control's first line */ .cbi-value { justify-content: space-between; gap: var(--fs-space-4); padding: var(--fs-space-2) 0; margin: 0; border-bottom: var(--fs-hairline); } /* stacked controls need a gap, a raw
collapses it; password-reveal excluded, must stay seamless */ .cbi-value-field > .control-group { margin-top: var(--fs-space-2); } .cbi-value-field > .control-group:not(:has(.cbi-input-password)) { display: inline-flex; flex-wrap: wrap; gap: var(--fs-space-2); align-items: center; } /* hairline separates a row from the NEXT one, so it drops whenever none follows, not only at the section's end */ .cbi-value:not(:has(+ .cbi-value)) { border-bottom: 0; } /* .cbi-checkbox has no text baseline (synthesised at its bottom edge, floats ~5px above the label) — centred, except with a help sentence under it (see the baseline note above) */ .cbi-value:not(:has(.cbi-value-description)):has(> .cbi-value-field > .cbi-checkbox, > .cbi-value-field > div > .cbi-radio) { align-items: center; } /* absorbed from base; ONLY the transition — typography stays in base (theme/45-misc.css). border-COLOR not the shorthand, which also animates width */ input, button { transition: var(--fs-field-transition); } .cbi-value-title { color: var(--fs-dim); font-size: var(--fs-type); font-weight: var(--fs-weight); /* stated not inherited: this is TEXT, the control rule hands labels line-height: normal (measured 18px -> normal without this) */ line-height: var(--fs-leading); } /* mono is for VALUES: buttons, the help sentence and `` LABELS excluded — a label * fed to mono also goes bold, 227 elements/20 KB of face for nothing. theme/45-misc.css's * label rule must ASSIGN sans; excluding `` here alone still inherits mono */ .cbi-value-field, .cbi-value-field *:where(:not(.btn, .cbi-button, .cbi-value-description)) { font-family: var(--fs-font-mono); } .cbi-value-description { font-family: var(--fs-font-sans); text-wrap: pretty; } /* not base's fixed 210px: mono + padded --fs-space-3, 210px clipped a URL mid-domain (issue #5); elastic, capped to the dynlist's ceiling */ .cbi-value-field input[type="text"], .cbi-value-field input[type="url"], .cbi-value-field input[type="search"] { width: 100%; max-width: var(--fs-field-max); } /* base assumes ONE title+field pair; stack full-width on a SECOND title (not a second field — a runtime-appended field would re-stack under the user's finger, measured: a button moved 31px) */ .cbi-value:has(.cbi-value-title ~ .cbi-value-title) > .cbi-value-title, .cbi-value:has(.cbi-value-title ~ .cbi-value-title) > .cbi-value-field { flex: 1 1 100%; margin-inline-start: 0; text-align: start; } .td > input[type="text"], .td > input[type="password"], .td > select, .td > .cbi-dropdown:not(.btn):not(.cbi-button), .cbi-dynlist > .add-item > .cbi-dropdown { width: 100%; } .cbi-section-create > * > input { width: 100%; } /* --- live components that bypassed the theme --- */ /* a CBI row is
on a form, in a table — same , theme had claimed only the table half */ div.cbi-value var, .td.cbi-value-field var { color: var(--fs-accent); } .td.cbi-value-field var.cbi-tooltip-container { border-bottom-color: var(--fs-accent); } .cbi-filebrowser { border-color: var(--fs-border); background: var(--fs-panel); border-radius: var(--fs-radius-lg); } .cbi-filebrowser > ul > li:hover { background: var(--fs-panel2); } .cbi-filebrowser .upload { border-top-color: var(--fs-border); } /* base sizes a row by proportion for its own ~20px buttons; this theme's 36px button (3 per * row) does not fit at 23% and `overflow: hidden` clips the corners — size actions to content, * let the name ellipsize, wrap when that is not enough */ .cbi-filebrowser > * { border-bottom-color: var(--fs-border); padding: var(--fs-space-1-5) var(--fs-space-2); } .cbi-filebrowser > ul { display: flex; flex-direction: column; gap: var(--fs-space-1); } .cbi-filebrowser > ul > li { align-items: center; flex-wrap: wrap; gap: var(--fs-space-2); } .cbi-filebrowser > ul > li > div:first-child { flex: 1 1 auto; min-width: 0; } /* `0 1 auto`: may wrap but not shrink below min-content, or it sticks out (measured 23px past the box at 320px before min-width: 0) */ .cbi-filebrowser > ul > li > div:last-child { flex: 0 1 auto; min-width: 0; display: flex; flex-wrap: wrap; gap: var(--fs-space-2); justify-content: flex-end; } .cbi-filebrowser > ul > li > div:last-child > button { margin: 0; } .cbi-filebrowser .upload > div > input { width: 100%; } /* Form widgets — toggles, file input. Applies to every CBI form. */ /* base zeroes checkbox margin; inside a .btn label only a literal space separated ✓ from text * (issue #5.1). toggle switch below unaffected, its own margin:0 wins on a different ancestor */ .btn > input[type="checkbox"], .btn > input[type="radio"] { margin-inline-end: .5em; } /* checkbox -> toggle switch, drawn on the INPUT — docs/css.md "Inputs: the toggle switch, * drawn on the input" has the forum regression this replaced. density-scaled local tokens. */ /* overflow-wrap: anywhere for the one caption word too long even at full width (pseudo-loc: a * 14-letter Russian compound grown to 20 pushed the row 24.6px past the field at 320px/Large) */ .cbi-checkbox { display: inline-flex; align-items: center; gap: var(--fs-space-2); overflow-wrap: anywhere; } /* label[for] stays in the DOM but draws nothing: out of flow, out of the flex item count, so gap opens only on the switch input + an optional caption */ .cbi-checkbox > label[for] { position: absolute; opacity: 0; width: 0; height: 0; margin: 0; } .cbi-checkbox > input[type="checkbox"] { --sw-w: calc(40px * var(--fs-density-box)); --sw-h: calc(22px * var(--fs-density-box)); --sw-knob: calc(16px * var(--fs-density-box)); --sw-pad: calc(2px * var(--fs-density-box)); /* appearance/--bd-color/--fg-color come from the shared input[type=checkbox] rule below; * flex-shrink: 0 keeps the pill at its width beside a caption (task 0145 has the numbers) */ display: inline-block; position: relative; margin: 0; flex-shrink: 0; width: var(--sw-w); height: var(--sw-h); border-radius: var(--fs-radius-pill); background: var(--fs-track); border: var(--fs-hairline); cursor: pointer; transition: background var(--fs-dur), border-color var(--fs-dur); vertical-align: middle; } /* hit-target overlay to 44x30 (WCAG 2.5.8 floor 24px, pill is 22px); inset stays literal, not * density-scaled — a floor that shrinks with Density is not one */ .cbi-checkbox > input[type="checkbox"]::before { inset: -4px -2px; } .cbi-checkbox > input[type="checkbox"]::after { top: var(--sw-pad); inset-inline-start: var(--sw-pad); width: var(--sw-knob); height: var(--sw-knob); border-radius: 50%; background: var(--fs-dim); /* transform not `left`: left re-lays out the row every frame, translateX is composited */ transform: translateX(0); transition: transform var(--fs-dur-move), background var(--fs-dur); } .cbi-checkbox > input[type="checkbox"]:checked { background: var(--fs-accent); border-color: transparent; } /* derived so it cannot drift from the sizes above; -2px is the pill's two 1px borders (the knob sits against the padding box, so it has 2px less room — travel is 18px not 20) */ .cbi-checkbox > input[type="checkbox"]:checked::after { transform: translateX(calc(var(--sw-w) - var(--sw-knob) - var(--sw-pad) * 2 - 2px)); background: var(--fs-on-accent); } /* the input IS the switch, ring goes here; -solo: checked switch already spends its border channel on accent, only the tinted shadow shows */ .cbi-checkbox > input[type="checkbox"]:focus-visible { border-color: var(--fs-accent); box-shadow: var(--fs-focus-ring-solo); } .cbi-checkbox > input[type="checkbox"]:disabled { opacity: var(--fs-disabled-opacity); cursor: not-allowed; } /* raw checkbox/radio, absorbed from base: undoes the generic input box below. 16px box on the * grid, mark inset FROM it. `.cbi-checkbox > input` also matches the switch's own input * (unscoped, it wants this rule's appearance:none) — selectors that WOULD paint the switch * exclude it individually below instead. */ input[type="checkbox"], input[type="radio"] { --bd-color: var(--fs-border); --fg-color: var(--fs-text); /* box tier not space tier: --fs-space-4 gave 16px at Normal but 10.4px at Compact (smaller than any control) and never grew at Large */ --box: calc(16px * var(--fs-density-box)); --mark-inset: 3px; /* WCAG 2.5.8's 24px spacing floor holds only while the theme owns the layout; ELEMENT is * 24px (drawing stays 16px, centred), max() so it never shrinks under --box at Large */ --hit: max(24px, var(--box)); appearance: none; width: var(--hit); height: var(--hit); /* negative margin pulls the extra hit area back out of flow (without it, rows measured 42px -> 51px) */ margin: calc((var(--box) - var(--hit)) / 2); color: var(--fg-color); position: relative; display: inline-block; cursor: pointer; background: none; border: none; /* padding/border-radius not reset: land on an appearance-none box whose pseudo-elements are absolute, invisible either way */ } input[type="checkbox"]::before, input[type="checkbox"]::after, input[type="radio"]::before, input[type="radio"]::after { position: absolute; content: ""; } input[type="checkbox"]:not(:where(.cbi-checkbox > input))::before, input[type="radio"]::before { /* inset:0; margin:auto centres a fixed box the same in RTL as LTR; a translate pair would not */ inset: 0; margin: auto; width: var(--box); height: var(--box); background: linear-gradient(var(--fs-panel), var(--fs-panel2)); border: 1px solid var(--bd-color); transition: var(--fs-field-transition); } input[type="checkbox"]::before { border-radius: 2px; } input[type="radio"], input[type="radio"]::before { border-radius: 50%; } /* keyboard/click focus ring on the DRAWN box, the theme's one ring token */ input[type="checkbox"]:not(:where(.cbi-checkbox > input))::after, input[type="radio"]::after { /* mark inset from the DRAWING, which is centred in the target, not from the target's own edge */ inset: 0; margin: auto; width: calc(var(--box) - var(--mark-inset) * 2); height: calc(var(--box) - var(--mark-inset) * 2); } input[type="checkbox"]:not(:where(.cbi-checkbox > input)):checked::after, input[type="radio"]:checked::after { /* OURS: stroked path (this theme's icon language), replacing a fill byte-identical to luci-theme-bootstrap's; mask keys on alpha so a stroke masks like a fill did */ --checkmark-icon: url("data:image/svg+xml,"); -webkit-mask: var(--checkmark-icon) center/cover no-repeat; mask: var(--checkmark-icon) center/cover no-repeat; background: var(--fg-color); } input[type="radio"]:checked:after { /* radio dot filled, not ringed — a ring reads as "not selected" */ --checkmark-icon: url("data:image/svg+xml,"); } input[type="checkbox"].cbi-input-invalid, input[type="radio"].cbi-input-invalid { --bd-color: var(--fs-danger); --fg-color: var(--fs-danger); } /* generic field box, absorbed from base; bare input keeps the historical 210px fallback for types the list below does not name */ input { display: inline-block; width: 210px; height: var(--fs-control-h); padding: var(--fs-space-1) var(--fs-space-2); background: var(--fs-panel); color: var(--fs-text); border: var(--fs-hairline); border-radius: var(--fs-radius); } /* base's old #localtime{width:300px} media rule not moved here: the elastic field width above already out-layers it (measured 440px, not 300) */ input[type="file"] { color: var(--fs-dim); font-size: var(--fs-type); padding: initial; border: initial; line-height: initial; box-shadow: none; /* no !important: width:auto out-specifies the generic input{width:210px} alone */ width: auto; } /* native stays native */ @supports (appearance: base-select) { .cbi-value-field select { appearance: base-select; } .cbi-value-field select::picker-icon { display: none; } ::picker(select) { appearance: base-select; background: var(--fs-panel); border: var(--fs-hairline); border-radius: var(--fs-radius-lg); box-shadow: var(--fs-shadow-pop); padding: var(--fs-space-1-5); margin-top: var(--fs-space-1-5); } .cbi-value-field select option { padding: var(--fs-space-2) var(--fs-space-3); border-radius: var(--fs-radius-sm); font-size: var(--fs-type); /* background:transparent undoes `select option`'s --fs-panel so the row's own hover shows */ background: transparent; min-height: 0; } .cbi-value-field select option::checkmark { display: none; } .cbi-value-field select option:hover, .cbi-value-field select option:focus-visible { background: var(--fs-panel2); } /* same shape as the open .cbi-dropdown's selected row (theme/65-dropdown.css): accent on --fs-accent-soft measures 4.21:1 in dark, under AA */ .cbi-value-field select option:checked { /* @mirror selected-row/paint */ background: var(--fs-panel2); color: var(--fs-accent); box-shadow: var(--fs-row-rail); /* @endmirror */ } } /* .cbi-select — legacy luci-compat shell around a native , which cannot draw the ::before chevron */ .cbi-select:not(select) { display: inline-block; width: 210px; /* height not min-height: the child's height:100% falls back to content height against an auto-height parent (measured collapse 30px -> 15px in a 38px shell) */ height: var(--fs-ctl-h); color: var(--fs-text); font-size: var(--fs-type); border: var(--fs-hairline); border-radius: var(--fs-radius); padding: 0; position: relative; background-color: var(--fs-panel2); background-image: var(--fs-select-chevron); background-repeat: no-repeat; background-size: 6px 6px; background-position: right calc(var(--fs-space-3) - 1px) center, right calc(var(--fs-space-3) + 5px) center; transition: var(--fs-field-transition); } /* base/30-forms.css only dims the old ▾ plate; with the plate gone the disabled state had no visual, so the shell carries it now */ .cbi-select[disabled]:not(select) { opacity: var(--fs-disabled-opacity); pointer-events: none; } /* invisible, filling the shell, clearing the plate by the same --fs-space-8 inset the themed select uses */ .cbi-select select, .cbi-select select:focus { appearance: none; outline: none; border: none; background: transparent; box-shadow: none; height: 100%; min-height: 0; width: 100%; padding: 0 var(--fs-space-8) 0 var(--fs-space-3); font-size: var(--fs-type); line-height: normal; cursor: pointer; } .spinning, .cbi-value em, em.spinning { color: var(--fs-dim); } /* type list must be EXHAUSTIVE: an omission falls back to BASE's stock field beside a themed one, not to "unstyled" */ .cbi-input-text, .cbi-input-password, .cbi-input-textarea, .cbi-section-create-name, .cbi-value-field input.create-item-input, input[type="text"], input[type="password"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="date"], input[type="time"], input[type="datetime-local"], input[type="month"], input[type="week"], input[type="color"], textarea { background: var(--fs-panel2); border: var(--fs-hairline); border-radius: var(--fs-radius); color: var(--fs-text); padding: var(--fs-space-2) var(--fs-space-3); min-height: var(--fs-ctl-h); box-shadow: none; transition: var(--fs-field-transition); } /* max-width:100% beside the fixed 210px: a textarea's intrinsic width comes from `cols` (default 20), which put two textareas 19px outside their card at 300px before this */ textarea { min-height: 84px; line-height: var(--fs-leading); width: 210px; max-width: 100%; font-size: var(--fs-type); } /* a square native scrollbar is not clipped by a rounded corner; self-rounded thumb + transparent track fixes it. no scrollbar-width/-color: either switches Chromium to the square standard bar */ textarea::-webkit-scrollbar { width: 16px; height: 16px; } textarea::-webkit-scrollbar-track { background: transparent; margin: var(--fs-space-4) 0 var(--fs-space-2-5); } textarea::-webkit-scrollbar-thumb { background: var(--fs-dim); border-radius: var(--fs-radius-pill); border: 5px solid transparent; background-clip: padding-box; } textarea::-webkit-scrollbar-thumb:hover { background: var(--fs-text); } textarea::-webkit-scrollbar-corner { background: transparent; } /* accent arc traces the frame's own radius (two borders shrunk to 16px - radius); mirrored by * hand below, ::-webkit-resizer ignores logical properties */ textarea::-webkit-resizer { background: transparent; border-right: 2px solid var(--fs-accent); border-bottom: 2px solid var(--fs-accent); border-bottom-right-radius: var(--fs-radius); margin: calc(16px - var(--fs-radius)) 0 0 calc(16px - var(--fs-radius)); } :root[dir="rtl"] textarea::-webkit-resizer { border-right: 0; border-left: 2px solid var(--fs-accent); border-bottom-right-radius: 0; border-bottom-left-radius: var(--fs-radius); margin: calc(16px - var(--fs-radius)) calc(16px - var(--fs-radius)) 0 0; } .cbi-input-text:hover, .cbi-input-password:hover, .cbi-input-textarea:hover, input[type="text"]:hover, input[type="password"]:hover, input[type="number"]:hover, input[type="email"]:hover, input[type="url"]:hover, input[type="search"]:hover, textarea:hover { border-color: var(--fs-dim); } /* fallback ring for untyped inputs; excludes the toggle switch, whose :focus-visible-only ring must not double up */ .cbi-input-text:focus, .cbi-input-password:focus, .cbi-input-textarea:focus, .cbi-section-create-name:focus, input:focus:not(:where(.cbi-checkbox > input)), input[type="text"]:focus, input[type="password"]:focus, input[type="number"]:focus, input[type="email"]:focus, input[type="url"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="date"]:focus, input[type="time"]:focus, textarea:focus, select:focus, .cbi-dynlist > .item:focus { border-color: var(--fs-accent); box-shadow: var(--fs-focus-ring); outline: none; } /* same ring, shared by 4 selectors that cannot join the list above; :is() around :has() keeps the list forgiving — unwrapped, a :has() compound sharing a list fails the WHOLE rule below the floor */ input[type="checkbox"]:not(:where(.cbi-checkbox > input)):focus::before, input[type="radio"]:focus::before, .cbi-select.focus, .cbi-dynlist > .add-item:focus-within, .control-group:is(:has(> .cbi-input-password)):focus-within { border-color: var(--fs-accent); box-shadow: var(--fs-focus-ring); } /* .cbi-value-error input (Lua-CBI) must live HERE: base's red border-color is a longhand and * this rule's border shorthand wipes it by layer regardless of specificity */ input[type="checkbox"].cbi-input-invalid:focus::before, input[type="radio"].cbi-input-invalid:focus::before, .cbi-select.cbi-input-invalid.focus, .cbi-input-invalid, input.cbi-input-invalid, textarea.cbi-input-invalid, .cbi-value-error input, .cbi-value-error textarea, .cbi-input-invalid:focus { border-color: var(--fs-danger); box-shadow: var(--fs-focus-ring-invalid); } /* same rejected value shown by a ui.Dropdown: base carried the widget and its closed
  • , theme only the input half */ .cbi-input-invalid.cbi-dropdown:not(.btn):not(.cbi-button), .cbi-input-invalid.cbi-dropdown:not([open]) > ul > li { border-color: var(--fs-danger); } /* doubled [readonly] states intent at (0,2,1): at (0,1,1) it only tied the typed input rules above and silently lost */ :is(input, select, textarea)[readonly][readonly] { border-color: color-mix(in srgb, var(--fs-border) calc(var(--fs-disabled-opacity) * 100%), transparent); pointer-events: auto; cursor: auto; } /* keep base's layout (inline-flex chips + add-item row); only colours, rounding, a compact + button, narrow cap so a chip's × sits near its text */ .cbi-dynlist { gap: var(--fs-space-1-5); background: transparent; border: 0; padding: 0; /* min(240px,100%) not a bare 240: a floor that exceeds the room is an overflow (measured 29px outside a 210px field at 320px) */ min-height: 0; min-width: min(240px, 100%); max-width: var(--fs-field-max); width: 100%; vertical-align: top; } .cbi-dynlist > .item { background: var(--fs-panel); border: var(--fs-hairline); border-radius: var(--fs-radius-sm); color: var(--fs-text); box-shadow: none; margin: 0; transition: var(--fs-field-transition); } .item::after { display: inline-block; cursor: pointer; background: linear-gradient(var(--fs-panel), var(--fs-panel) 25%, var(--fs-panel2)); padding: 0 var(--fs-space-3); color: var(--fs-text); line-height: 2em; border: var(--fs-hairline); border-radius: var(--fs-radius); transition: var(--fs-field-transition); } .item:hover::after { filter: var(--fs-hover-lift); } .cbi-dynlist > .item::after { display: inline-flex; padding: 0 var(--fs-space-2); color: var(--fs-danger); border-radius: 0 var(--fs-radius-sm) var(--fs-radius-sm) 0; } .cbi-dynlist > .add-item { align-items: stretch; background: var(--fs-panel2); border: var(--fs-hairline); border-radius: var(--fs-radius-sm); overflow: hidden; transition: var(--fs-field-transition); } .cbi-dynlist > .add-item > input, /* width:auto keeps the flex basis in charge — this input sits inside .cbi-value-field, the elastic width above would otherwise hand it 100% on top of flex:1 1 auto */ .cbi-dynlist > .add-item > .cbi-input-text { flex: 1 1 auto; min-width: 0; width: auto; border: 0; background: transparent; box-shadow: none; min-height: var(--fs-ctl-h-sm); border-radius: 0; } /* input + button as ONE seamless group; gap:0 is load-bearing — base gives every .control-group a gap, this is the one whose members must touch */ .control-group:has(> .cbi-input-password) { display: inline-flex; align-items: stretch; gap: 0; background: var(--fs-panel2); border: var(--fs-hairline); border-radius: var(--fs-radius); overflow: hidden; transition: var(--fs-field-transition); } .control-group:has(> .cbi-input-password) > .cbi-input-password { border: 0; border-radius: 0; background: transparent; box-shadow: none; min-height: var(--fs-ctl-h); } .cbi-section-create, .cbi-section-create.cbi-tblsection-create { margin-top: var(--fs-space-3); } /* `.hidden.hidden` outranks every component rule without !important (which would invert layer * order later) and covers the Enter-key submit legacy Lua pages carry (issue #12). * :not([class*=":"]) excludes a Tailwind/UnoCSS class fs-sheets.js re-hosts into this layer — * docs/css.md "Inputs: `.hidden.hidden`, and the Tailwind/UnoCSS exception". */ .hidden.hidden:not([class*=":"]) { display: none; } /* the WCAG 2.5.8 target (24px min) split from the 6px track — docs/css.md "Inputs: the range * slider's hit target and its line-box" has the two-part fix and its numbers */ input[type="range"] { appearance: none; width: 100%; height: 24px; min-height: 0; padding: 0; margin-block: -9px; background: transparent; border: 0; border-radius: 0; outline: none; box-shadow: none; cursor: pointer; } input[type="range"]::-webkit-slider-runnable-track { width: 100%; height: 6px; background: var(--fs-track); border: 0; border-radius: var(--fs-radius-pill); } input[type="range"]::-moz-range-track { width: 100%; height: 6px; background: var(--fs-track); border: 0; border-radius: var(--fs-radius-pill); } input[type="range"]::-webkit-slider-thumb { appearance: none; width: 16px; height: 16px; border-radius: 50%; background: var(--fs-accent); border: 2px solid var(--fs-panel); cursor: pointer; /* WebKit centres on the INPUT's box not the track: (6-16)/2 = -5px */ margin-top: -5px; } input[type="range"]::-moz-range-thumb { width: 16px; height: 16px; border-radius: 50%; background: var(--fs-accent); border: 2px solid var(--fs-panel); cursor: pointer; } input[type="range"]:focus::-webkit-slider-runnable-track { box-shadow: var(--fs-focus-ring-solo); } input[type="range"]:focus::-moz-range-track { box-shadow: var(--fs-focus-ring-solo); } /* same ceiling as the elastic text inputs; vertical-align:middle decouples the line-box from the input's own edge, which moved 6px -> 24px above */ .cbi-range-slider { display: inline-flex; align-items: center; vertical-align: middle; gap: var(--fs-space-3); width: 100%; max-width: var(--fs-field-max); } .cbi-range-slider-value { background: var(--fs-panel2); border: var(--fs-hairline); border-radius: var(--fs-radius-sm); padding: var(--fs-space-1) var(--fs-space-2); color: var(--fs-accent); font-family: var(--fs-font-mono); /* not 600: no bold mono face bundled, drags in 20 KB or fakes it with synthetic emboldening */ font-weight: var(--fs-weight-normal); font-size: var(--fs-type); white-space: nowrap; } .cbi-range-slider-calc, .cbi-range-slider-calc-units { color: var(--fs-dim); font-size: var(--fs-type); } }