@uniweb/runtime 0.8.41 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1012,275 +1012,6 @@ var require_react = __commonJS({
1012
1012
  }
1013
1013
  });
1014
1014
 
1015
- // ../../node_modules/.pnpm/react@19.2.5/node_modules/react/cjs/react-jsx-runtime.development.js
1016
- var require_react_jsx_runtime_development = __commonJS({
1017
- "../../node_modules/.pnpm/react@19.2.5/node_modules/react/cjs/react-jsx-runtime.development.js"(exports) {
1018
- "use strict";
1019
- (function() {
1020
- function getComponentNameFromType(type) {
1021
- if (null == type) return null;
1022
- if ("function" === typeof type)
1023
- return type.$$typeof === REACT_CLIENT_REFERENCE ? null : type.displayName || type.name || null;
1024
- if ("string" === typeof type) return type;
1025
- switch (type) {
1026
- case REACT_FRAGMENT_TYPE:
1027
- return "Fragment";
1028
- case REACT_PROFILER_TYPE:
1029
- return "Profiler";
1030
- case REACT_STRICT_MODE_TYPE:
1031
- return "StrictMode";
1032
- case REACT_SUSPENSE_TYPE:
1033
- return "Suspense";
1034
- case REACT_SUSPENSE_LIST_TYPE:
1035
- return "SuspenseList";
1036
- case REACT_ACTIVITY_TYPE:
1037
- return "Activity";
1038
- }
1039
- if ("object" === typeof type)
1040
- switch ("number" === typeof type.tag && console.error(
1041
- "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
1042
- ), type.$$typeof) {
1043
- case REACT_PORTAL_TYPE:
1044
- return "Portal";
1045
- case REACT_CONTEXT_TYPE:
1046
- return type.displayName || "Context";
1047
- case REACT_CONSUMER_TYPE:
1048
- return (type._context.displayName || "Context") + ".Consumer";
1049
- case REACT_FORWARD_REF_TYPE:
1050
- var innerType = type.render;
1051
- type = type.displayName;
1052
- type || (type = innerType.displayName || innerType.name || "", type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef");
1053
- return type;
1054
- case REACT_MEMO_TYPE:
1055
- return innerType = type.displayName || null, null !== innerType ? innerType : getComponentNameFromType(type.type) || "Memo";
1056
- case REACT_LAZY_TYPE:
1057
- innerType = type._payload;
1058
- type = type._init;
1059
- try {
1060
- return getComponentNameFromType(type(innerType));
1061
- } catch (x) {
1062
- }
1063
- }
1064
- return null;
1065
- }
1066
- function testStringCoercion(value) {
1067
- return "" + value;
1068
- }
1069
- function checkKeyStringCoercion(value) {
1070
- try {
1071
- testStringCoercion(value);
1072
- var JSCompiler_inline_result = false;
1073
- } catch (e) {
1074
- JSCompiler_inline_result = true;
1075
- }
1076
- if (JSCompiler_inline_result) {
1077
- JSCompiler_inline_result = console;
1078
- var JSCompiler_temp_const = JSCompiler_inline_result.error;
1079
- var JSCompiler_inline_result$jscomp$0 = "function" === typeof Symbol && Symbol.toStringTag && value[Symbol.toStringTag] || value.constructor.name || "Object";
1080
- JSCompiler_temp_const.call(
1081
- JSCompiler_inline_result,
1082
- "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
1083
- JSCompiler_inline_result$jscomp$0
1084
- );
1085
- return testStringCoercion(value);
1086
- }
1087
- }
1088
- function getTaskName(type) {
1089
- if (type === REACT_FRAGMENT_TYPE) return "<>";
1090
- if ("object" === typeof type && null !== type && type.$$typeof === REACT_LAZY_TYPE)
1091
- return "<...>";
1092
- try {
1093
- var name = getComponentNameFromType(type);
1094
- return name ? "<" + name + ">" : "<...>";
1095
- } catch (x) {
1096
- return "<...>";
1097
- }
1098
- }
1099
- function getOwner() {
1100
- var dispatcher = ReactSharedInternals.A;
1101
- return null === dispatcher ? null : dispatcher.getOwner();
1102
- }
1103
- function UnknownOwner() {
1104
- return Error("react-stack-top-frame");
1105
- }
1106
- function hasValidKey(config) {
1107
- if (hasOwnProperty.call(config, "key")) {
1108
- var getter = Object.getOwnPropertyDescriptor(config, "key").get;
1109
- if (getter && getter.isReactWarning) return false;
1110
- }
1111
- return void 0 !== config.key;
1112
- }
1113
- function defineKeyPropWarningGetter(props, displayName) {
1114
- function warnAboutAccessingKey() {
1115
- specialPropKeyWarningShown || (specialPropKeyWarningShown = true, console.error(
1116
- "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
1117
- displayName
1118
- ));
1119
- }
1120
- warnAboutAccessingKey.isReactWarning = true;
1121
- Object.defineProperty(props, "key", {
1122
- get: warnAboutAccessingKey,
1123
- configurable: true
1124
- });
1125
- }
1126
- function elementRefGetterWithDeprecationWarning() {
1127
- var componentName = getComponentNameFromType(this.type);
1128
- didWarnAboutElementRef[componentName] || (didWarnAboutElementRef[componentName] = true, console.error(
1129
- "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
1130
- ));
1131
- componentName = this.props.ref;
1132
- return void 0 !== componentName ? componentName : null;
1133
- }
1134
- function ReactElement(type, key, props, owner, debugStack, debugTask) {
1135
- var refProp = props.ref;
1136
- type = {
1137
- $$typeof: REACT_ELEMENT_TYPE,
1138
- type,
1139
- key,
1140
- props,
1141
- _owner: owner
1142
- };
1143
- null !== (void 0 !== refProp ? refProp : null) ? Object.defineProperty(type, "ref", {
1144
- enumerable: false,
1145
- get: elementRefGetterWithDeprecationWarning
1146
- }) : Object.defineProperty(type, "ref", { enumerable: false, value: null });
1147
- type._store = {};
1148
- Object.defineProperty(type._store, "validated", {
1149
- configurable: false,
1150
- enumerable: false,
1151
- writable: true,
1152
- value: 0
1153
- });
1154
- Object.defineProperty(type, "_debugInfo", {
1155
- configurable: false,
1156
- enumerable: false,
1157
- writable: true,
1158
- value: null
1159
- });
1160
- Object.defineProperty(type, "_debugStack", {
1161
- configurable: false,
1162
- enumerable: false,
1163
- writable: true,
1164
- value: debugStack
1165
- });
1166
- Object.defineProperty(type, "_debugTask", {
1167
- configurable: false,
1168
- enumerable: false,
1169
- writable: true,
1170
- value: debugTask
1171
- });
1172
- Object.freeze && (Object.freeze(type.props), Object.freeze(type));
1173
- return type;
1174
- }
1175
- function jsxDEVImpl(type, config, maybeKey, isStaticChildren, debugStack, debugTask) {
1176
- var children = config.children;
1177
- if (void 0 !== children)
1178
- if (isStaticChildren)
1179
- if (isArrayImpl(children)) {
1180
- for (isStaticChildren = 0; isStaticChildren < children.length; isStaticChildren++)
1181
- validateChildKeys(children[isStaticChildren]);
1182
- Object.freeze && Object.freeze(children);
1183
- } else
1184
- console.error(
1185
- "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
1186
- );
1187
- else validateChildKeys(children);
1188
- if (hasOwnProperty.call(config, "key")) {
1189
- children = getComponentNameFromType(type);
1190
- var keys = Object.keys(config).filter(function(k) {
1191
- return "key" !== k;
1192
- });
1193
- isStaticChildren = 0 < keys.length ? "{key: someKey, " + keys.join(": ..., ") + ": ...}" : "{key: someKey}";
1194
- didWarnAboutKeySpread[children + isStaticChildren] || (keys = 0 < keys.length ? "{" + keys.join(": ..., ") + ": ...}" : "{}", console.error(
1195
- 'A props object containing a "key" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />',
1196
- isStaticChildren,
1197
- children,
1198
- keys,
1199
- children
1200
- ), didWarnAboutKeySpread[children + isStaticChildren] = true);
1201
- }
1202
- children = null;
1203
- void 0 !== maybeKey && (checkKeyStringCoercion(maybeKey), children = "" + maybeKey);
1204
- hasValidKey(config) && (checkKeyStringCoercion(config.key), children = "" + config.key);
1205
- if ("key" in config) {
1206
- maybeKey = {};
1207
- for (var propName in config)
1208
- "key" !== propName && (maybeKey[propName] = config[propName]);
1209
- } else maybeKey = config;
1210
- children && defineKeyPropWarningGetter(
1211
- maybeKey,
1212
- "function" === typeof type ? type.displayName || type.name || "Unknown" : type
1213
- );
1214
- return ReactElement(
1215
- type,
1216
- children,
1217
- maybeKey,
1218
- getOwner(),
1219
- debugStack,
1220
- debugTask
1221
- );
1222
- }
1223
- function validateChildKeys(node) {
1224
- isValidElement(node) ? node._store && (node._store.validated = 1) : "object" === typeof node && null !== node && node.$$typeof === REACT_LAZY_TYPE && ("fulfilled" === node._payload.status ? isValidElement(node._payload.value) && node._payload.value._store && (node._payload.value._store.validated = 1) : node._store && (node._store.validated = 1));
1225
- }
1226
- function isValidElement(object) {
1227
- return "object" === typeof object && null !== object && object.$$typeof === REACT_ELEMENT_TYPE;
1228
- }
1229
- var React2 = require_react(), REACT_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = /* @__PURE__ */ Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = /* @__PURE__ */ Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = /* @__PURE__ */ Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = /* @__PURE__ */ Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = /* @__PURE__ */ Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = /* @__PURE__ */ Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = /* @__PURE__ */ Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = /* @__PURE__ */ Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = /* @__PURE__ */ Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = /* @__PURE__ */ Symbol.for("react.memo"), REACT_LAZY_TYPE = /* @__PURE__ */ Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = /* @__PURE__ */ Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = /* @__PURE__ */ Symbol.for("react.client.reference"), ReactSharedInternals = React2.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
1230
- return null;
1231
- };
1232
- React2 = {
1233
- react_stack_bottom_frame: function(callStackForError) {
1234
- return callStackForError();
1235
- }
1236
- };
1237
- var specialPropKeyWarningShown;
1238
- var didWarnAboutElementRef = {};
1239
- var unknownOwnerDebugStack = React2.react_stack_bottom_frame.bind(
1240
- React2,
1241
- UnknownOwner
1242
- )();
1243
- var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
1244
- var didWarnAboutKeySpread = {};
1245
- exports.Fragment = REACT_FRAGMENT_TYPE;
1246
- exports.jsx = function(type, config, maybeKey) {
1247
- var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
1248
- return jsxDEVImpl(
1249
- type,
1250
- config,
1251
- maybeKey,
1252
- false,
1253
- trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack,
1254
- trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask
1255
- );
1256
- };
1257
- exports.jsxs = function(type, config, maybeKey) {
1258
- var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
1259
- return jsxDEVImpl(
1260
- type,
1261
- config,
1262
- maybeKey,
1263
- true,
1264
- trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack,
1265
- trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask
1266
- );
1267
- };
1268
- })();
1269
- }
1270
- });
1271
-
1272
- // ../../node_modules/.pnpm/react@19.2.5/node_modules/react/jsx-runtime.js
1273
- var require_jsx_runtime = __commonJS({
1274
- "../../node_modules/.pnpm/react@19.2.5/node_modules/react/jsx-runtime.js"(exports, module) {
1275
- "use strict";
1276
- if (false) {
1277
- module.exports = null;
1278
- } else {
1279
- module.exports = require_react_jsx_runtime_development();
1280
- }
1281
- }
1282
- });
1283
-
1284
1015
  // ../../node_modules/.pnpm/react-dom@19.2.5_react@19.2.5/node_modules/react-dom/cjs/react-dom.development.js
1285
1016
  var require_react_dom_development = __commonJS({
1286
1017
  "../../node_modules/.pnpm/react-dom@19.2.5_react@19.2.5/node_modules/react-dom/cjs/react-dom.development.js"(exports) {
@@ -1489,51 +1220,320 @@ var require_react_dom_development = __commonJS({
1489
1220
  media: "string" === typeof options.media ? options.media : void 0
1490
1221
  });
1491
1222
  }
1492
- };
1493
- exports.preloadModule = function(href, options) {
1494
- var encountered = "";
1495
- "string" === typeof href && href || (encountered += " The `href` argument encountered was " + getValueDescriptorExpectingObjectForWarning(href) + ".");
1496
- void 0 !== options && "object" !== typeof options ? encountered += " The `options` argument encountered was " + getValueDescriptorExpectingObjectForWarning(options) + "." : options && "as" in options && "string" !== typeof options.as && (encountered += " The `as` option encountered was " + getValueDescriptorExpectingObjectForWarning(options.as) + ".");
1497
- encountered && console.error(
1498
- 'ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, an `options` object with an `as` property valid for a `<link rel="modulepreload" as="..." />` tag.%s',
1499
- encountered
1223
+ };
1224
+ exports.preloadModule = function(href, options) {
1225
+ var encountered = "";
1226
+ "string" === typeof href && href || (encountered += " The `href` argument encountered was " + getValueDescriptorExpectingObjectForWarning(href) + ".");
1227
+ void 0 !== options && "object" !== typeof options ? encountered += " The `options` argument encountered was " + getValueDescriptorExpectingObjectForWarning(options) + "." : options && "as" in options && "string" !== typeof options.as && (encountered += " The `as` option encountered was " + getValueDescriptorExpectingObjectForWarning(options.as) + ".");
1228
+ encountered && console.error(
1229
+ 'ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, an `options` object with an `as` property valid for a `<link rel="modulepreload" as="..." />` tag.%s',
1230
+ encountered
1231
+ );
1232
+ "string" === typeof href && (options ? (encountered = getCrossOriginStringAs(
1233
+ options.as,
1234
+ options.crossOrigin
1235
+ ), Internals.d.m(href, {
1236
+ as: "string" === typeof options.as && "script" !== options.as ? options.as : void 0,
1237
+ crossOrigin: encountered,
1238
+ integrity: "string" === typeof options.integrity ? options.integrity : void 0
1239
+ })) : Internals.d.m(href));
1240
+ };
1241
+ exports.requestFormReset = function(form) {
1242
+ Internals.d.r(form);
1243
+ };
1244
+ exports.unstable_batchedUpdates = function(fn, a) {
1245
+ return fn(a);
1246
+ };
1247
+ exports.useFormState = function(action, initialState, permalink) {
1248
+ return resolveDispatcher().useFormState(action, initialState, permalink);
1249
+ };
1250
+ exports.useFormStatus = function() {
1251
+ return resolveDispatcher().useHostTransitionStatus();
1252
+ };
1253
+ exports.version = "19.2.5";
1254
+ "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
1255
+ })();
1256
+ }
1257
+ });
1258
+
1259
+ // ../../node_modules/.pnpm/react-dom@19.2.5_react@19.2.5/node_modules/react-dom/index.js
1260
+ var require_react_dom = __commonJS({
1261
+ "../../node_modules/.pnpm/react-dom@19.2.5_react@19.2.5/node_modules/react-dom/index.js"(exports, module) {
1262
+ "use strict";
1263
+ if (false) {
1264
+ checkDCE();
1265
+ module.exports = null;
1266
+ } else {
1267
+ module.exports = require_react_dom_development();
1268
+ }
1269
+ }
1270
+ });
1271
+
1272
+ // ../../node_modules/.pnpm/react@19.2.5/node_modules/react/cjs/react-jsx-runtime.development.js
1273
+ var require_react_jsx_runtime_development = __commonJS({
1274
+ "../../node_modules/.pnpm/react@19.2.5/node_modules/react/cjs/react-jsx-runtime.development.js"(exports) {
1275
+ "use strict";
1276
+ (function() {
1277
+ function getComponentNameFromType(type) {
1278
+ if (null == type) return null;
1279
+ if ("function" === typeof type)
1280
+ return type.$$typeof === REACT_CLIENT_REFERENCE ? null : type.displayName || type.name || null;
1281
+ if ("string" === typeof type) return type;
1282
+ switch (type) {
1283
+ case REACT_FRAGMENT_TYPE:
1284
+ return "Fragment";
1285
+ case REACT_PROFILER_TYPE:
1286
+ return "Profiler";
1287
+ case REACT_STRICT_MODE_TYPE:
1288
+ return "StrictMode";
1289
+ case REACT_SUSPENSE_TYPE:
1290
+ return "Suspense";
1291
+ case REACT_SUSPENSE_LIST_TYPE:
1292
+ return "SuspenseList";
1293
+ case REACT_ACTIVITY_TYPE:
1294
+ return "Activity";
1295
+ }
1296
+ if ("object" === typeof type)
1297
+ switch ("number" === typeof type.tag && console.error(
1298
+ "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
1299
+ ), type.$$typeof) {
1300
+ case REACT_PORTAL_TYPE:
1301
+ return "Portal";
1302
+ case REACT_CONTEXT_TYPE:
1303
+ return type.displayName || "Context";
1304
+ case REACT_CONSUMER_TYPE:
1305
+ return (type._context.displayName || "Context") + ".Consumer";
1306
+ case REACT_FORWARD_REF_TYPE:
1307
+ var innerType = type.render;
1308
+ type = type.displayName;
1309
+ type || (type = innerType.displayName || innerType.name || "", type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef");
1310
+ return type;
1311
+ case REACT_MEMO_TYPE:
1312
+ return innerType = type.displayName || null, null !== innerType ? innerType : getComponentNameFromType(type.type) || "Memo";
1313
+ case REACT_LAZY_TYPE:
1314
+ innerType = type._payload;
1315
+ type = type._init;
1316
+ try {
1317
+ return getComponentNameFromType(type(innerType));
1318
+ } catch (x) {
1319
+ }
1320
+ }
1321
+ return null;
1322
+ }
1323
+ function testStringCoercion(value) {
1324
+ return "" + value;
1325
+ }
1326
+ function checkKeyStringCoercion(value) {
1327
+ try {
1328
+ testStringCoercion(value);
1329
+ var JSCompiler_inline_result = false;
1330
+ } catch (e) {
1331
+ JSCompiler_inline_result = true;
1332
+ }
1333
+ if (JSCompiler_inline_result) {
1334
+ JSCompiler_inline_result = console;
1335
+ var JSCompiler_temp_const = JSCompiler_inline_result.error;
1336
+ var JSCompiler_inline_result$jscomp$0 = "function" === typeof Symbol && Symbol.toStringTag && value[Symbol.toStringTag] || value.constructor.name || "Object";
1337
+ JSCompiler_temp_const.call(
1338
+ JSCompiler_inline_result,
1339
+ "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
1340
+ JSCompiler_inline_result$jscomp$0
1341
+ );
1342
+ return testStringCoercion(value);
1343
+ }
1344
+ }
1345
+ function getTaskName(type) {
1346
+ if (type === REACT_FRAGMENT_TYPE) return "<>";
1347
+ if ("object" === typeof type && null !== type && type.$$typeof === REACT_LAZY_TYPE)
1348
+ return "<...>";
1349
+ try {
1350
+ var name = getComponentNameFromType(type);
1351
+ return name ? "<" + name + ">" : "<...>";
1352
+ } catch (x) {
1353
+ return "<...>";
1354
+ }
1355
+ }
1356
+ function getOwner() {
1357
+ var dispatcher = ReactSharedInternals.A;
1358
+ return null === dispatcher ? null : dispatcher.getOwner();
1359
+ }
1360
+ function UnknownOwner() {
1361
+ return Error("react-stack-top-frame");
1362
+ }
1363
+ function hasValidKey(config) {
1364
+ if (hasOwnProperty.call(config, "key")) {
1365
+ var getter = Object.getOwnPropertyDescriptor(config, "key").get;
1366
+ if (getter && getter.isReactWarning) return false;
1367
+ }
1368
+ return void 0 !== config.key;
1369
+ }
1370
+ function defineKeyPropWarningGetter(props, displayName) {
1371
+ function warnAboutAccessingKey() {
1372
+ specialPropKeyWarningShown || (specialPropKeyWarningShown = true, console.error(
1373
+ "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
1374
+ displayName
1375
+ ));
1376
+ }
1377
+ warnAboutAccessingKey.isReactWarning = true;
1378
+ Object.defineProperty(props, "key", {
1379
+ get: warnAboutAccessingKey,
1380
+ configurable: true
1381
+ });
1382
+ }
1383
+ function elementRefGetterWithDeprecationWarning() {
1384
+ var componentName = getComponentNameFromType(this.type);
1385
+ didWarnAboutElementRef[componentName] || (didWarnAboutElementRef[componentName] = true, console.error(
1386
+ "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
1387
+ ));
1388
+ componentName = this.props.ref;
1389
+ return void 0 !== componentName ? componentName : null;
1390
+ }
1391
+ function ReactElement(type, key, props, owner, debugStack, debugTask) {
1392
+ var refProp = props.ref;
1393
+ type = {
1394
+ $$typeof: REACT_ELEMENT_TYPE,
1395
+ type,
1396
+ key,
1397
+ props,
1398
+ _owner: owner
1399
+ };
1400
+ null !== (void 0 !== refProp ? refProp : null) ? Object.defineProperty(type, "ref", {
1401
+ enumerable: false,
1402
+ get: elementRefGetterWithDeprecationWarning
1403
+ }) : Object.defineProperty(type, "ref", { enumerable: false, value: null });
1404
+ type._store = {};
1405
+ Object.defineProperty(type._store, "validated", {
1406
+ configurable: false,
1407
+ enumerable: false,
1408
+ writable: true,
1409
+ value: 0
1410
+ });
1411
+ Object.defineProperty(type, "_debugInfo", {
1412
+ configurable: false,
1413
+ enumerable: false,
1414
+ writable: true,
1415
+ value: null
1416
+ });
1417
+ Object.defineProperty(type, "_debugStack", {
1418
+ configurable: false,
1419
+ enumerable: false,
1420
+ writable: true,
1421
+ value: debugStack
1422
+ });
1423
+ Object.defineProperty(type, "_debugTask", {
1424
+ configurable: false,
1425
+ enumerable: false,
1426
+ writable: true,
1427
+ value: debugTask
1428
+ });
1429
+ Object.freeze && (Object.freeze(type.props), Object.freeze(type));
1430
+ return type;
1431
+ }
1432
+ function jsxDEVImpl(type, config, maybeKey, isStaticChildren, debugStack, debugTask) {
1433
+ var children = config.children;
1434
+ if (void 0 !== children)
1435
+ if (isStaticChildren)
1436
+ if (isArrayImpl(children)) {
1437
+ for (isStaticChildren = 0; isStaticChildren < children.length; isStaticChildren++)
1438
+ validateChildKeys(children[isStaticChildren]);
1439
+ Object.freeze && Object.freeze(children);
1440
+ } else
1441
+ console.error(
1442
+ "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
1443
+ );
1444
+ else validateChildKeys(children);
1445
+ if (hasOwnProperty.call(config, "key")) {
1446
+ children = getComponentNameFromType(type);
1447
+ var keys = Object.keys(config).filter(function(k) {
1448
+ return "key" !== k;
1449
+ });
1450
+ isStaticChildren = 0 < keys.length ? "{key: someKey, " + keys.join(": ..., ") + ": ...}" : "{key: someKey}";
1451
+ didWarnAboutKeySpread[children + isStaticChildren] || (keys = 0 < keys.length ? "{" + keys.join(": ..., ") + ": ...}" : "{}", console.error(
1452
+ 'A props object containing a "key" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />',
1453
+ isStaticChildren,
1454
+ children,
1455
+ keys,
1456
+ children
1457
+ ), didWarnAboutKeySpread[children + isStaticChildren] = true);
1458
+ }
1459
+ children = null;
1460
+ void 0 !== maybeKey && (checkKeyStringCoercion(maybeKey), children = "" + maybeKey);
1461
+ hasValidKey(config) && (checkKeyStringCoercion(config.key), children = "" + config.key);
1462
+ if ("key" in config) {
1463
+ maybeKey = {};
1464
+ for (var propName in config)
1465
+ "key" !== propName && (maybeKey[propName] = config[propName]);
1466
+ } else maybeKey = config;
1467
+ children && defineKeyPropWarningGetter(
1468
+ maybeKey,
1469
+ "function" === typeof type ? type.displayName || type.name || "Unknown" : type
1500
1470
  );
1501
- "string" === typeof href && (options ? (encountered = getCrossOriginStringAs(
1502
- options.as,
1503
- options.crossOrigin
1504
- ), Internals.d.m(href, {
1505
- as: "string" === typeof options.as && "script" !== options.as ? options.as : void 0,
1506
- crossOrigin: encountered,
1507
- integrity: "string" === typeof options.integrity ? options.integrity : void 0
1508
- })) : Internals.d.m(href));
1509
- };
1510
- exports.requestFormReset = function(form) {
1511
- Internals.d.r(form);
1471
+ return ReactElement(
1472
+ type,
1473
+ children,
1474
+ maybeKey,
1475
+ getOwner(),
1476
+ debugStack,
1477
+ debugTask
1478
+ );
1479
+ }
1480
+ function validateChildKeys(node) {
1481
+ isValidElement(node) ? node._store && (node._store.validated = 1) : "object" === typeof node && null !== node && node.$$typeof === REACT_LAZY_TYPE && ("fulfilled" === node._payload.status ? isValidElement(node._payload.value) && node._payload.value._store && (node._payload.value._store.validated = 1) : node._store && (node._store.validated = 1));
1482
+ }
1483
+ function isValidElement(object) {
1484
+ return "object" === typeof object && null !== object && object.$$typeof === REACT_ELEMENT_TYPE;
1485
+ }
1486
+ var React2 = require_react(), REACT_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = /* @__PURE__ */ Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = /* @__PURE__ */ Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = /* @__PURE__ */ Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = /* @__PURE__ */ Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = /* @__PURE__ */ Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = /* @__PURE__ */ Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = /* @__PURE__ */ Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = /* @__PURE__ */ Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = /* @__PURE__ */ Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = /* @__PURE__ */ Symbol.for("react.memo"), REACT_LAZY_TYPE = /* @__PURE__ */ Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = /* @__PURE__ */ Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = /* @__PURE__ */ Symbol.for("react.client.reference"), ReactSharedInternals = React2.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
1487
+ return null;
1512
1488
  };
1513
- exports.unstable_batchedUpdates = function(fn, a) {
1514
- return fn(a);
1489
+ React2 = {
1490
+ react_stack_bottom_frame: function(callStackForError) {
1491
+ return callStackForError();
1492
+ }
1515
1493
  };
1516
- exports.useFormState = function(action, initialState, permalink) {
1517
- return resolveDispatcher().useFormState(action, initialState, permalink);
1494
+ var specialPropKeyWarningShown;
1495
+ var didWarnAboutElementRef = {};
1496
+ var unknownOwnerDebugStack = React2.react_stack_bottom_frame.bind(
1497
+ React2,
1498
+ UnknownOwner
1499
+ )();
1500
+ var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
1501
+ var didWarnAboutKeySpread = {};
1502
+ exports.Fragment = REACT_FRAGMENT_TYPE;
1503
+ exports.jsx = function(type, config, maybeKey) {
1504
+ var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
1505
+ return jsxDEVImpl(
1506
+ type,
1507
+ config,
1508
+ maybeKey,
1509
+ false,
1510
+ trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack,
1511
+ trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask
1512
+ );
1518
1513
  };
1519
- exports.useFormStatus = function() {
1520
- return resolveDispatcher().useHostTransitionStatus();
1514
+ exports.jsxs = function(type, config, maybeKey) {
1515
+ var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
1516
+ return jsxDEVImpl(
1517
+ type,
1518
+ config,
1519
+ maybeKey,
1520
+ true,
1521
+ trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack,
1522
+ trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask
1523
+ );
1521
1524
  };
1522
- exports.version = "19.2.5";
1523
- "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
1524
1525
  })();
1525
1526
  }
1526
1527
  });
1527
1528
 
1528
- // ../../node_modules/.pnpm/react-dom@19.2.5_react@19.2.5/node_modules/react-dom/index.js
1529
- var require_react_dom = __commonJS({
1530
- "../../node_modules/.pnpm/react-dom@19.2.5_react@19.2.5/node_modules/react-dom/index.js"(exports, module) {
1529
+ // ../../node_modules/.pnpm/react@19.2.5/node_modules/react/jsx-runtime.js
1530
+ var require_jsx_runtime = __commonJS({
1531
+ "../../node_modules/.pnpm/react@19.2.5/node_modules/react/jsx-runtime.js"(exports, module) {
1531
1532
  "use strict";
1532
1533
  if (false) {
1533
- checkDCE();
1534
1534
  module.exports = null;
1535
1535
  } else {
1536
- module.exports = require_react_dom_development();
1536
+ module.exports = require_react_jsx_runtime_development();
1537
1537
  }
1538
1538
  }
1539
1539
  });
@@ -16354,8 +16354,9 @@ var require_server_browser = __commonJS({
16354
16354
  });
16355
16355
 
16356
16356
  // dist/worker-runtime-entry.js
16357
- var __PlatformReact = __toESM(require_react(), 1);
16358
- var __PlatformJsxRuntime = __toESM(require_jsx_runtime(), 1);
16357
+ var __P0 = __toESM(require_react(), 1);
16358
+ var __P1 = __toESM(require_react_dom(), 1);
16359
+ var __P2 = __toESM(require_jsx_runtime(), 1);
16359
16360
 
16360
16361
  // ../core/src/index.js
16361
16362
  var src_exports = {};
@@ -16373,11 +16374,17 @@ __export(src_exports, {
16373
16374
  deriveCacheKey: () => deriveCacheKey,
16374
16375
  evaluateWhere: () => evaluate,
16375
16376
  getUniweb: () => getUniweb,
16377
+ hasDarkScheme: () => hasDarkScheme,
16376
16378
  isRichSchema: () => isRichSchema,
16379
+ isWildcardLanguages: () => isWildcardLanguages,
16377
16380
  listRequestStyleNames: () => listStyleNames,
16378
16381
  matchWhere: () => match,
16382
+ normalizeLanguageList: () => normalizeLanguageList,
16383
+ resolveDefaultLocale: () => resolveDefaultLocale,
16384
+ resolvePublishableLocales: () => resolvePublishableLocales,
16379
16385
  resolveRequestStyle: () => resolveStyle,
16380
- substitutePlaceholders: () => substitutePlaceholders
16386
+ substitutePlaceholders: () => substitutePlaceholders,
16387
+ validateLanguageConfig: () => validateLanguageConfig
16381
16388
  });
16382
16389
 
16383
16390
  // ../../node_modules/.pnpm/yaml@2.8.3/node_modules/yaml/browser/dist/nodes/identity.js
@@ -22716,6 +22723,15 @@ function createSequenceElement(node, options = {}) {
22716
22723
  }),
22717
22724
  attrs
22718
22725
  };
22726
+ case "inset_block": {
22727
+ const { component, ...params } = attrs || {};
22728
+ return {
22729
+ type: "inset_block",
22730
+ component,
22731
+ params,
22732
+ children: processSequence({ content })
22733
+ };
22734
+ }
22719
22735
  case "dataBlock":
22720
22736
  return {
22721
22737
  type: "dataBlock",
@@ -22839,10 +22855,64 @@ function createSequenceElement(node, options = {}) {
22839
22855
  };
22840
22856
  }
22841
22857
  }
22858
+ var FILE_LINK_EXTENSIONS = [
22859
+ "pdf",
22860
+ "doc",
22861
+ "docx",
22862
+ "xls",
22863
+ "xlsx",
22864
+ "ppt",
22865
+ "pptx",
22866
+ "jpg",
22867
+ "jpeg",
22868
+ "png",
22869
+ "webp",
22870
+ "gif",
22871
+ "svg",
22872
+ "mp4",
22873
+ "mp3",
22874
+ "wav",
22875
+ "mov",
22876
+ "zip"
22877
+ ];
22878
+ function getLinkMark(node) {
22879
+ return (node?.marks || []).find((mark) => mark.type === "link") || null;
22880
+ }
22881
+ function sameLink(a, b) {
22882
+ if (!a || !b) return false;
22883
+ return JSON.stringify(a.attrs || {}) === JSON.stringify(b.attrs || {});
22884
+ }
22885
+ function wrapLink(inner, linkMark) {
22886
+ const href = linkMark.attrs.href;
22887
+ const target = linkMark.attrs.target || "_self";
22888
+ const extension = href.split(".").pop()?.toLowerCase();
22889
+ const isFileLink = FILE_LINK_EXTENSIONS.includes(extension);
22890
+ return `<a href="${href}" target="${target}"${isFileLink ? " download" : ""}>${inner}</a>`;
22891
+ }
22842
22892
  function getTextContent(content, options = {}) {
22843
22893
  if (!content) return "";
22844
- return content.reduce((prev, curr) => {
22845
- const { type, marks = [], text } = curr;
22894
+ const groups = [];
22895
+ for (const node of content) {
22896
+ const link = node?.type === "text" ? getLinkMark(node) : null;
22897
+ const last = groups[groups.length - 1];
22898
+ if (link && last?.link && sameLink(last.link, link)) {
22899
+ last.nodes.push(node);
22900
+ } else {
22901
+ groups.push({ link, nodes: [node] });
22902
+ }
22903
+ }
22904
+ return groups.reduce((prev, group) => {
22905
+ const inner = group.nodes.reduce(
22906
+ (acc, node) => acc + renderInlineNode(node),
22907
+ ""
22908
+ );
22909
+ if (!inner && !group.link) return prev;
22910
+ return prev + (group.link ? wrapLink(inner, group.link) : inner);
22911
+ }, "").trim();
22912
+ }
22913
+ function renderInlineNode(curr) {
22914
+ return [curr].reduce((prev, curr2) => {
22915
+ const { type, marks = [], text } = curr2;
22846
22916
  if (type === "text") {
22847
22917
  let styledText = text || "";
22848
22918
  if (marks.some((mark) => mark.type === "textStyle")) {
@@ -22879,47 +22949,22 @@ function getTextContent(content, options = {}) {
22879
22949
  const attrString = attrParts.length > 0 ? ` ${attrParts.join(" ")}` : "";
22880
22950
  styledText = `<span${attrString}>${styledText}</span>`;
22881
22951
  }
22952
+ if (marks.some((mark) => mark.type === "code")) {
22953
+ styledText = `<code>${styledText}</code>`;
22954
+ }
22882
22955
  if (marks.some((mark) => mark.type === "bold")) {
22883
22956
  styledText = `<strong>${styledText}</strong>`;
22884
22957
  }
22885
22958
  if (marks.some((mark) => mark.type === "italic")) {
22886
22959
  styledText = `<em>${styledText}</em>`;
22887
22960
  }
22888
- if (marks.some((mark) => mark.type === "link")) {
22889
- const linkMark = marks.find((mark) => mark.type === "link");
22890
- const href = linkMark.attrs.href;
22891
- const target = linkMark.attrs.target || "_self";
22892
- const fileExtensions = [
22893
- "pdf",
22894
- "doc",
22895
- "docx",
22896
- "xls",
22897
- "xlsx",
22898
- "ppt",
22899
- "pptx",
22900
- "jpg",
22901
- "jpeg",
22902
- "png",
22903
- "webp",
22904
- "gif",
22905
- "svg",
22906
- "mp4",
22907
- "mp3",
22908
- "wav",
22909
- "mov",
22910
- "zip"
22911
- ];
22912
- const extension = href.split(".").pop()?.toLowerCase();
22913
- const isFileLink = fileExtensions.includes(extension);
22914
- styledText = `<a href="${href}" target="${target}"${isFileLink ? " download" : ""}>${styledText}</a>`;
22915
- }
22916
22961
  return prev + styledText;
22917
22962
  } else if (type === "math_inline") {
22918
- const latex = escapeAttr(curr.attrs?.latex || "");
22919
- const mathml = curr.attrs?.mathml || "";
22963
+ const latex = escapeAttr(curr2.attrs?.latex || "");
22964
+ const mathml = curr2.attrs?.mathml || "";
22920
22965
  return prev + `<span data-type="math" data-latex="${latex}" data-display="false">${mathml}</span>`;
22921
22966
  } else if (type === "inset_placeholder") {
22922
- const refId = curr.attrs?.refId;
22967
+ const refId = curr2.attrs?.refId;
22923
22968
  if (!refId) return prev;
22924
22969
  return prev + `<uniweb-inset data-ref-id="${refId}"></uniweb-inset>`;
22925
22970
  } else if (type === "hardBreak") {
@@ -22927,7 +22972,7 @@ function getTextContent(content, options = {}) {
22927
22972
  } else {
22928
22973
  return prev;
22929
22974
  }
22930
- }, "").trim();
22975
+ }, "");
22931
22976
  }
22932
22977
  function processInlineElements(content) {
22933
22978
  if (!content) return [];
@@ -23021,8 +23066,15 @@ function parseUniwebIcon(itemAttrs) {
23021
23066
  if (preserveColors) icon.preserveColors = preserveColors;
23022
23067
  if (href) icon.href = href;
23023
23068
  if (target) icon.target = target;
23024
- if (library) icon.library = library;
23025
- if (name) icon.name = name;
23069
+ let resolvedLibrary = library;
23070
+ let resolvedName = name;
23071
+ if (!resolvedLibrary && typeof name === "string" && name.includes(":")) {
23072
+ const [family, ...rest] = name.split(":");
23073
+ resolvedLibrary = family;
23074
+ resolvedName = rest.join(":");
23075
+ }
23076
+ if (resolvedLibrary) icon.library = resolvedLibrary;
23077
+ if (resolvedName) icon.name = resolvedName;
23026
23078
  return icon;
23027
23079
  }
23028
23080
  function parseIconBlock(itemAttrs) {
@@ -23925,18 +23977,489 @@ function generatePalettes(colors, options = {}) {
23925
23977
  continue;
23926
23978
  }
23927
23979
  }
23928
- if (typeof colorConfig === "object" && colorConfig !== null && colorConfig.base) {
23929
- const { base, ...colorOptions } = colorConfig;
23930
- palettes[name] = generateShades(base, { ...options, ...colorOptions });
23931
- } else if (typeof colorConfig === "string") {
23932
- palettes[name] = generateShades(colorConfig, options);
23980
+ if (typeof colorConfig === "object" && colorConfig !== null && colorConfig.base) {
23981
+ const { base, ...colorOptions } = colorConfig;
23982
+ palettes[name] = generateShades(base, { ...options, ...colorOptions });
23983
+ } else if (typeof colorConfig === "string") {
23984
+ palettes[name] = generateShades(colorConfig, options);
23985
+ }
23986
+ }
23987
+ return palettes;
23988
+ }
23989
+ function isValidColor(color) {
23990
+ try {
23991
+ parseColor(color);
23992
+ return true;
23993
+ } catch {
23994
+ return false;
23995
+ }
23996
+ }
23997
+
23998
+ // ../theming/src/css-generator.js
23999
+ var DEFAULT_CONTEXT_TOKENS = {
24000
+ light: {
24001
+ "section": "var(--neutral-50)",
24002
+ "card": "var(--neutral-100)",
24003
+ "muted": "var(--neutral-200)",
24004
+ "body": "var(--neutral-950)",
24005
+ "heading": "var(--neutral-900)",
24006
+ "subtle": "var(--neutral-600)",
24007
+ "border": "var(--neutral-200)",
24008
+ "ring": "var(--primary-500)",
24009
+ "link": "var(--primary-600)",
24010
+ "link-hover": "var(--primary-700)",
24011
+ // Shade 500 is the site's colour exactly as authored (the palette anchors
24012
+ // the input there). `link` and `primary` sit at 600 because they carry the
24013
+ // strict contrast burden — body-size links, and white text on a fill. An
24014
+ // accent is decorative emphasis, usually at display size, so it keeps the
24015
+ // brand colour unmuddied instead of paying for contrast it doesn't need.
24016
+ "accent": "var(--accent-500)",
24017
+ "primary": "var(--primary-600)",
24018
+ "primary-foreground": "white",
24019
+ "primary-hover": "var(--primary-700)",
24020
+ "primary-border": "transparent",
24021
+ "secondary": "white",
24022
+ "secondary-foreground": "var(--neutral-900)",
24023
+ "secondary-hover": "var(--neutral-100)",
24024
+ "secondary-border": "var(--neutral-300)",
24025
+ "success": "#16a34a",
24026
+ "success-subtle": "#f0fdf4",
24027
+ "warning": "#d97706",
24028
+ "warning-subtle": "#fffbeb",
24029
+ "error": "#dc2626",
24030
+ "error-subtle": "#fef2f2",
24031
+ "info": "#2563eb",
24032
+ "info-subtle": "#eff6ff"
24033
+ },
24034
+ medium: {
24035
+ "section": "var(--neutral-100)",
24036
+ "card": "var(--neutral-200)",
24037
+ "muted": "var(--neutral-300)",
24038
+ "body": "var(--neutral-950)",
24039
+ "heading": "var(--neutral-900)",
24040
+ "subtle": "var(--neutral-700)",
24041
+ "border": "var(--neutral-300)",
24042
+ "ring": "var(--primary-500)",
24043
+ "link": "var(--primary-600)",
24044
+ "link-hover": "var(--primary-700)",
24045
+ "accent": "var(--accent-500)",
24046
+ // exact brand — see the light context
24047
+ "primary": "var(--primary-600)",
24048
+ "primary-foreground": "white",
24049
+ "primary-hover": "var(--primary-700)",
24050
+ "primary-border": "transparent",
24051
+ "secondary": "white",
24052
+ "secondary-foreground": "var(--neutral-900)",
24053
+ "secondary-hover": "var(--neutral-100)",
24054
+ "secondary-border": "var(--neutral-300)",
24055
+ "success": "#16a34a",
24056
+ "success-subtle": "#f0fdf4",
24057
+ "warning": "#d97706",
24058
+ "warning-subtle": "#fffbeb",
24059
+ "error": "#dc2626",
24060
+ "error-subtle": "#fef2f2",
24061
+ "info": "#2563eb",
24062
+ "info-subtle": "#eff6ff"
24063
+ },
24064
+ dark: {
24065
+ "section": "var(--neutral-950)",
24066
+ "card": "var(--neutral-800)",
24067
+ "muted": "var(--neutral-700)",
24068
+ "body": "var(--neutral-50)",
24069
+ "heading": "white",
24070
+ "subtle": "var(--neutral-400)",
24071
+ "border": "var(--neutral-700)",
24072
+ "ring": "var(--primary-500)",
24073
+ "link": "var(--primary-400)",
24074
+ "link-hover": "var(--primary-300)",
24075
+ // Stays lightened, unlike the light/medium contexts which use the exact
24076
+ // brand at 500. Every text token here is lightened (body, subtle, link)
24077
+ // because a mid-brand hue on a near-black surface often isn't legible —
24078
+ // a navy or forest-green accent at 500 would effectively disappear. A site
24079
+ // whose brand does read on dark can set `contexts.dark.accent` to it.
24080
+ "accent": "var(--accent-400)",
24081
+ "primary": "var(--primary-500)",
24082
+ "primary-foreground": "white",
24083
+ "primary-hover": "var(--primary-400)",
24084
+ "primary-border": "transparent",
24085
+ "secondary": "var(--neutral-800)",
24086
+ "secondary-foreground": "var(--neutral-100)",
24087
+ "secondary-hover": "var(--neutral-700)",
24088
+ "secondary-border": "var(--neutral-600)",
24089
+ "success": "#4ade80",
24090
+ "success-subtle": "#052e16",
24091
+ "warning": "#fbbf24",
24092
+ "warning-subtle": "#451a03",
24093
+ "error": "#f87171",
24094
+ "error-subtle": "#450a0a",
24095
+ "info": "#60a5fa",
24096
+ "info-subtle": "#172554"
24097
+ }
24098
+ };
24099
+ var DEFAULT_COLORS = {
24100
+ primary: "#3b82f6",
24101
+ // Blue
24102
+ secondary: "#64748b",
24103
+ // Slate
24104
+ // Last resort only. A site that names no accent inherits its primary (see
24105
+ // processTheme) — this literal is reached solely when the primary is unusable.
24106
+ accent: "#8b5cf6",
24107
+ // Purple
24108
+ neutral: "#78716c"
24109
+ // Stone
24110
+ };
24111
+ var SHADE_LEVELS2 = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
24112
+ function generateVarDeclarations(vars, indent = " ") {
24113
+ return Object.entries(vars).map(([name, value]) => `${indent}--${name}: ${value};`).join("\n");
24114
+ }
24115
+ function generatePaletteVars(palettes) {
24116
+ const lines = [];
24117
+ for (const [name, shades] of Object.entries(palettes)) {
24118
+ for (const level of SHADE_LEVELS2) {
24119
+ if (shades[level]) {
24120
+ lines.push(` --${name}-${level}: ${shades[level]};`);
24121
+ }
24122
+ }
24123
+ }
24124
+ return lines.join("\n");
24125
+ }
24126
+ function generateContextCSS(context, tokens = {}, colorVars = {}) {
24127
+ const defaultTokens = DEFAULT_CONTEXT_TOKENS[context] || DEFAULT_CONTEXT_TOKENS.light;
24128
+ const mergedTokens = { ...defaultTokens, ...tokens };
24129
+ const contextColorVars = colorVars[context] || {};
24130
+ const allVars = { ...mergedTokens, ...contextColorVars };
24131
+ const vars = generateVarDeclarations(allVars);
24132
+ return `.context-${context} {
24133
+ ${vars}
24134
+ }`;
24135
+ }
24136
+ function generateDarkSchemeCSS(config = {}, darkOverrides = {}, colorVars = {}) {
24137
+ const respectSystemPreference = config.default === "system";
24138
+ const darkColorVars = colorVars.dark || {};
24139
+ const darkTokens = { ...DEFAULT_CONTEXT_TOKENS.dark, ...darkOverrides, ...darkColorVars };
24140
+ const vars = generateVarDeclarations(darkTokens);
24141
+ let css = `/* Dark scheme (user preference) */
24142
+ `;
24143
+ css += `.scheme-dark {
24144
+ ${vars}
24145
+ }
24146
+ `;
24147
+ if (respectSystemPreference) {
24148
+ css += `
24149
+ @media (prefers-color-scheme: dark) {
24150
+ `;
24151
+ css += ` :root:not(.scheme-light) {
24152
+ `;
24153
+ for (const [name, value] of Object.entries(darkTokens)) {
24154
+ css += ` --${name}: ${value};
24155
+ `;
24156
+ }
24157
+ css += ` }
24158
+ `;
24159
+ css += `}
24160
+ `;
24161
+ }
24162
+ return css;
24163
+ }
24164
+ var GENERIC_FAMILIES = /* @__PURE__ */ new Set([
24165
+ "serif",
24166
+ "sans-serif",
24167
+ "monospace",
24168
+ "cursive",
24169
+ "fantasy",
24170
+ "system-ui",
24171
+ "ui-monospace",
24172
+ "ui-serif",
24173
+ "ui-sans-serif",
24174
+ "ui-rounded",
24175
+ "math",
24176
+ "emoji",
24177
+ "fangsong",
24178
+ "inherit",
24179
+ "initial",
24180
+ "revert",
24181
+ "unset"
24182
+ ]);
24183
+ function extractUsedFamilies(fontRoles = {}) {
24184
+ const used = /* @__PURE__ */ new Set();
24185
+ const addFamiliesFrom = (value) => {
24186
+ if (typeof value !== "string") return;
24187
+ for (const segment of value.split(",")) {
24188
+ const name = segment.trim().replace(/^["']|["']$/g, "").toLowerCase();
24189
+ if (!name || GENERIC_FAMILIES.has(name) || /^\d/.test(name)) continue;
24190
+ used.add(name);
24191
+ }
24192
+ };
24193
+ for (const role of Object.values(fontRoles)) {
24194
+ if (role && role.load) addFamiliesFrom(role.value);
24195
+ }
24196
+ return used;
24197
+ }
24198
+ function filterGoogleFontsUrl(url, usedFamilies) {
24199
+ try {
24200
+ const parsed = new URL(url);
24201
+ const familyParams = parsed.searchParams.getAll("family");
24202
+ if (familyParams.length === 0) return url;
24203
+ const kept = familyParams.filter((param) => {
24204
+ const name = param.split(":")[0].trim().toLowerCase();
24205
+ return usedFamilies.has(name);
24206
+ });
24207
+ if (kept.length === 0) return null;
24208
+ parsed.searchParams.delete("family");
24209
+ for (const f of kept) {
24210
+ parsed.searchParams.append("family", f);
24211
+ }
24212
+ return parsed.toString();
24213
+ } catch {
24214
+ return url;
24215
+ }
24216
+ }
24217
+ function withBase(url, base) {
24218
+ if (!url || !base || base === "/") return url;
24219
+ if (!url.startsWith("/") || url.startsWith("//")) return url;
24220
+ const prefix = base.endsWith("/") ? base.slice(0, -1) : base;
24221
+ if (url === prefix || url.startsWith(prefix + "/")) return url;
24222
+ return prefix + url;
24223
+ }
24224
+ function isGoogleFontsUrl(url) {
24225
+ try {
24226
+ return new URL(url).hostname === "fonts.googleapis.com";
24227
+ } catch {
24228
+ return false;
24229
+ }
24230
+ }
24231
+ function generateFontCSS(fontRoles = {}, fonts = {}, base = "/") {
24232
+ const cssLines = [];
24233
+ const linkTags = [];
24234
+ const usedFamilies = extractUsedFamilies(fontRoles);
24235
+ const PRELOAD_TYPE = { woff2: "font/woff2", woff: "font/woff", truetype: "font/ttf", opentype: "font/otf" };
24236
+ if (fonts.faces && Array.isArray(fonts.faces)) {
24237
+ for (const face of fonts.faces) {
24238
+ if (!face.family || !face.src) continue;
24239
+ if (!usedFamilies.has(face.family.toLowerCase())) continue;
24240
+ const format = face.format || (face.src.endsWith(".woff2") ? "woff2" : "woff");
24241
+ const src = withBase(face.src, base);
24242
+ cssLines.push(
24243
+ `@font-face {`,
24244
+ ` font-family: ${face.family};`,
24245
+ ` src: url('${src}') format('${format}');`,
24246
+ ` font-weight: ${face.weight || 400};`,
24247
+ ` font-style: ${face.style || "normal"};`,
24248
+ ` font-display: swap;`,
24249
+ `}`
24250
+ );
24251
+ const mimeType = PRELOAD_TYPE[format];
24252
+ if (mimeType) {
24253
+ linkTags.push(`<link rel="preload" href="${src}" as="font" type="${mimeType}" crossorigin>`);
24254
+ }
24255
+ }
24256
+ if (cssLines.length > 0) {
24257
+ cssLines.push("");
24258
+ }
24259
+ }
24260
+ const googleUrls = [];
24261
+ const otherOrigins = /* @__PURE__ */ new Set();
24262
+ if (fonts.import && Array.isArray(fonts.import)) {
24263
+ for (const entry of fonts.import) {
24264
+ if (!entry.url) continue;
24265
+ if (isGoogleFontsUrl(entry.url)) {
24266
+ const filtered = filterGoogleFontsUrl(entry.url, usedFamilies);
24267
+ if (filtered) googleUrls.push(filtered);
24268
+ } else {
24269
+ linkTags.push(`<link rel="stylesheet" href="${entry.url}">`);
24270
+ try {
24271
+ otherOrigins.add(new URL(entry.url).origin);
24272
+ } catch {
24273
+ }
24274
+ }
24275
+ }
24276
+ }
24277
+ for (const origin of otherOrigins) {
24278
+ linkTags.unshift(`<link rel="preconnect" href="${origin}">`);
24279
+ }
24280
+ if (googleUrls.length > 0) {
24281
+ const allFamilies = [];
24282
+ let display = "swap";
24283
+ for (const url of googleUrls) {
24284
+ try {
24285
+ const parsed = new URL(url);
24286
+ allFamilies.push(...parsed.searchParams.getAll("family"));
24287
+ if (parsed.searchParams.get("display")) {
24288
+ display = parsed.searchParams.get("display");
24289
+ }
24290
+ } catch {
24291
+ }
24292
+ }
24293
+ if (allFamilies.length > 0) {
24294
+ const familyQuery = allFamilies.map((f) => `family=${f.trim().replace(/\s+/g, "+")}`).join("&");
24295
+ const href = `https://fonts.googleapis.com/css2?${familyQuery}&display=${display}`;
24296
+ linkTags.unshift(
24297
+ `<link rel="preconnect" href="https://fonts.googleapis.com">`,
24298
+ `<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>`,
24299
+ `<link rel="stylesheet" href="${href}">`
24300
+ );
24301
+ }
24302
+ }
24303
+ const fontVars = [];
24304
+ for (const [name, role] of Object.entries(fontRoles)) {
24305
+ if (role.value) {
24306
+ fontVars.push(` --font-${name}: ${role.value};`);
24307
+ }
24308
+ }
24309
+ if (fontVars.length > 0) {
24310
+ cssLines.push(":root {");
24311
+ cssLines.push(...fontVars);
24312
+ cssLines.push("}");
24313
+ }
24314
+ const applyRules = [];
24315
+ for (const [name, role] of Object.entries(fontRoles)) {
24316
+ if (!role.apply || !role.applyTo?.length) continue;
24317
+ const selector = role.applyTo.join(", ");
24318
+ applyRules.push(`${selector} { font-family: var(--font-${name}); }`);
24319
+ }
24320
+ if (applyRules.length > 0) {
24321
+ cssLines.push("");
24322
+ cssLines.push(...applyRules);
24323
+ }
24324
+ return {
24325
+ css: cssLines.join("\n"),
24326
+ links: linkTags.join("\n")
24327
+ };
24328
+ }
24329
+ var RESERVED_VAR_NAMES = /* @__PURE__ */ new Set([
24330
+ // Semantic color tokens
24331
+ "section",
24332
+ "card",
24333
+ "muted",
24334
+ "body",
24335
+ "heading",
24336
+ "subtle",
24337
+ "border",
24338
+ "ring",
24339
+ "link",
24340
+ "link-hover",
24341
+ "accent",
24342
+ // Action tokens
24343
+ "primary",
24344
+ "primary-foreground",
24345
+ "primary-hover",
24346
+ "primary-border",
24347
+ "secondary",
24348
+ "secondary-foreground",
24349
+ "secondary-hover",
24350
+ "secondary-border",
24351
+ // Status tokens
24352
+ "success",
24353
+ "success-subtle",
24354
+ "warning",
24355
+ "warning-subtle",
24356
+ "error",
24357
+ "error-subtle",
24358
+ "info",
24359
+ "info-subtle"
24360
+ ]);
24361
+ var PALETTE_SHADE_RE = /^(primary|secondary|accent|neutral)-\d+$/;
24362
+ function generateFoundationVars(vars = {}) {
24363
+ if (!vars || Object.keys(vars).length === 0) {
24364
+ return "";
24365
+ }
24366
+ const declarations = [];
24367
+ for (const [name, config] of Object.entries(vars)) {
24368
+ if (RESERVED_VAR_NAMES.has(name) || PALETTE_SHADE_RE.test(name)) {
24369
+ console.warn(
24370
+ `Warning: Foundation var '${name}' collides with a theme token. Rename it to avoid unexpected behavior (e.g., '${name}-value' or '${name}-size').`
24371
+ );
24372
+ }
24373
+ const value = typeof config === "object" ? config.default : config;
24374
+ if (value !== void 0) {
24375
+ declarations.push(` --${name}: ${value};`);
24376
+ }
24377
+ }
24378
+ if (declarations.length === 0) {
24379
+ return "";
24380
+ }
24381
+ return `:root {
24382
+ ${declarations.join("\n")}
24383
+ }`;
24384
+ }
24385
+ function generateThemeCSS(config = {}, options = {}) {
24386
+ const { base = "/" } = options;
24387
+ const {
24388
+ colors = DEFAULT_COLORS,
24389
+ contexts = {},
24390
+ fonts = {},
24391
+ fontRoles = {},
24392
+ appearance = {},
24393
+ foundationVars = {},
24394
+ colorVars = {}
24395
+ } = config;
24396
+ const sections = [];
24397
+ const fontResult = generateFontCSS(fontRoles, fonts, base);
24398
+ if (fontResult.css) {
24399
+ sections.push("/* Typography */\n" + fontResult.css);
24400
+ }
24401
+ const palettes = generatePalettes(colors);
24402
+ const paletteVars = generatePaletteVars(palettes);
24403
+ sections.push(`/* Color Palettes */
24404
+ :root {
24405
+ ${paletteVars}
24406
+ }`);
24407
+ const lightColorVars = colorVars.light || {};
24408
+ const defaultTokens = { ...DEFAULT_CONTEXT_TOKENS.light, ...contexts.light || {}, ...lightColorVars };
24409
+ const defaultVars = generateVarDeclarations(defaultTokens);
24410
+ sections.push(`/* Default Semantic Tokens */
24411
+ :root {
24412
+ ${defaultVars}
24413
+ }
24414
+
24415
+ /* Section backgrounds \u2014 applied once, resolves via context tokens */
24416
+ [id^="section-"] {
24417
+ background-color: var(--section);
24418
+ }`);
24419
+ const contextCSS = [
24420
+ generateContextCSS("light", contexts.light, colorVars),
24421
+ generateContextCSS("medium", contexts.medium, colorVars),
24422
+ generateContextCSS("dark", contexts.dark, colorVars)
24423
+ ];
24424
+ sections.push("/* Color Contexts */\n" + contextCSS.join("\n\n"));
24425
+ const foundationCSS = generateFoundationVars(foundationVars);
24426
+ if (foundationCSS) {
24427
+ sections.push("/* Foundation Variables */\n" + foundationCSS);
24428
+ }
24429
+ if (appearance.allowToggle || appearance.default === "dark" || appearance.default === "system" || appearance.schemes?.includes("dark")) {
24430
+ sections.push(generateDarkSchemeCSS(appearance, contexts.dark, colorVars));
24431
+ }
24432
+ sections.push(
24433
+ `/* Site Background */
24434
+ body {
24435
+ background: ${config.background || "var(--section)"};
24436
+ }`
24437
+ );
24438
+ if (config.inline && typeof config.inline === "object") {
24439
+ const rules = Object.entries(config.inline).filter(([, styles]) => styles && typeof styles === "object").map(([name, styles]) => {
24440
+ const declarations = Object.entries(styles).map(([prop, value]) => ` ${prop}: ${value};`).join("\n");
24441
+ return `span[${name}] {
24442
+ ${declarations}
24443
+ }`;
24444
+ });
24445
+ if (rules.length > 0) {
24446
+ sections.push("/* Inline Text Styles */\n" + rules.join("\n\n"));
23933
24447
  }
23934
24448
  }
23935
- return palettes;
24449
+ return {
24450
+ css: sections.join("\n\n"),
24451
+ links: fontResult.links
24452
+ };
24453
+ }
24454
+ function getDefaultContextTokens() {
24455
+ return JSON.parse(JSON.stringify(DEFAULT_CONTEXT_TOKENS));
24456
+ }
24457
+ function getDefaultColors() {
24458
+ return { ...DEFAULT_COLORS };
23936
24459
  }
23937
24460
 
23938
24461
  // ../theming/src/normalize.js
23939
- var SHADE_LEVELS2 = /* @__PURE__ */ new Set([50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950]);
24462
+ var SHADE_LEVELS3 = /* @__PURE__ */ new Set([50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950]);
23940
24463
  var PALETTE_REF_RE = /^([a-z][a-z0-9]*)-(\d+)$/;
23941
24464
  var PALETTE_REF_OPACITY_RE = /^([a-z][a-z0-9]*-\d+)\/(\d+)$/;
23942
24465
  var RGBA_VAR_RE = /^rgba\(\s*(var\(--[^)]+\))\s*\/\s*([\d.]+)\s*\)$/;
@@ -23957,7 +24480,7 @@ function normalizeTokenValue(value) {
23957
24480
  const ref = opacityMatch[1];
23958
24481
  const pct = parseInt(opacityMatch[2], 10);
23959
24482
  const refMatch = ref.match(PALETTE_REF_RE);
23960
- if (refMatch && SHADE_LEVELS2.has(parseInt(refMatch[2], 10))) {
24483
+ if (refMatch && SHADE_LEVELS3.has(parseInt(refMatch[2], 10))) {
23961
24484
  if (pct >= 100) return `var(--${ref})`;
23962
24485
  return `color-mix(in srgb, var(--${ref}) ${pct}%, transparent)`;
23963
24486
  }
@@ -23965,13 +24488,413 @@ function normalizeTokenValue(value) {
23965
24488
  const paletteMatch = bare.match(PALETTE_REF_RE);
23966
24489
  if (paletteMatch) {
23967
24490
  const shade = parseInt(paletteMatch[2], 10);
23968
- if (SHADE_LEVELS2.has(shade)) {
24491
+ if (SHADE_LEVELS3.has(shade)) {
23969
24492
  return `var(--${bare})`;
23970
24493
  }
23971
24494
  }
23972
24495
  return value;
23973
24496
  }
23974
24497
 
24498
+ // ../theming/src/processor.js
24499
+ var NEUTRAL_PRESETS = {
24500
+ stone: "#78716c",
24501
+ zinc: "#71717a",
24502
+ gray: "#6b7280",
24503
+ slate: "#64748b",
24504
+ neutral: "#737373"
24505
+ };
24506
+ var DEFAULT_INLINE = {
24507
+ accent: {
24508
+ color: "var(--accent)",
24509
+ "font-weight": "600"
24510
+ },
24511
+ callout: {
24512
+ color: "var(--accent)",
24513
+ "font-weight": "600"
24514
+ },
24515
+ muted: {
24516
+ color: "var(--subtle)"
24517
+ }
24518
+ };
24519
+ var DEFAULT_APPEARANCE = {
24520
+ default: "light",
24521
+ // Default color scheme
24522
+ allowToggle: false,
24523
+ // Whether to show scheme toggle
24524
+ respectSystemPreference: true
24525
+ // Honor prefers-color-scheme
24526
+ };
24527
+ var DEFAULT_FONTS = {
24528
+ body: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
24529
+ heading: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
24530
+ code: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, monospace'
24531
+ };
24532
+ var DEFAULT_FONT_ROLES = {
24533
+ body: ["body"],
24534
+ heading: ["h1", "h2", "h3"],
24535
+ code: ["code", "pre", "kbd", "samp"]
24536
+ };
24537
+ var NON_FAMILY_FONT_VARS = /* @__PURE__ */ new Set([
24538
+ "font-weight",
24539
+ "font-style",
24540
+ "font-size",
24541
+ "font-stretch",
24542
+ "font-feature-settings",
24543
+ "font-variation-settings",
24544
+ "font-variant",
24545
+ "font-kerning",
24546
+ "font-optical-sizing",
24547
+ "font-synthesis",
24548
+ "font-size-adjust",
24549
+ "font-smoothing",
24550
+ "font-palette",
24551
+ "font-language-override"
24552
+ ]);
24553
+ function isFontVar(name, config) {
24554
+ const type = typeof config === "object" ? config?.type : void 0;
24555
+ if (type === "font") return true;
24556
+ return name.startsWith("font-") && !NON_FAMILY_FONT_VARS.has(name);
24557
+ }
24558
+ function normalizeFontRoleName(name) {
24559
+ return name.startsWith("font-") ? name.slice(5) : name;
24560
+ }
24561
+ function normalizeApplyTo(applyTo) {
24562
+ if (applyTo == null) return null;
24563
+ const list = Array.isArray(applyTo) ? applyTo : String(applyTo).split(",");
24564
+ const cleaned = list.map((s) => String(s).trim()).filter(Boolean);
24565
+ return cleaned.length ? cleaned : null;
24566
+ }
24567
+ function validateColors(colors) {
24568
+ const errors = [];
24569
+ if (!colors || typeof colors !== "object") {
24570
+ return { valid: true, errors };
24571
+ }
24572
+ for (const [name, value] of Object.entries(colors)) {
24573
+ if (typeof value === "object" && value !== null) {
24574
+ continue;
24575
+ }
24576
+ if (typeof value !== "string") {
24577
+ errors.push(`Color "${name}" must be a string or shade object, got ${typeof value}`);
24578
+ continue;
24579
+ }
24580
+ if (name === "neutral" && NEUTRAL_PRESETS[value]) {
24581
+ continue;
24582
+ }
24583
+ if (!isValidColor(value)) {
24584
+ errors.push(`Color "${name}" has invalid value: ${value}`);
24585
+ }
24586
+ }
24587
+ return { valid: errors.length === 0, errors };
24588
+ }
24589
+ function validateContexts(contexts) {
24590
+ const errors = [];
24591
+ if (!contexts || typeof contexts !== "object") {
24592
+ return { valid: true, errors };
24593
+ }
24594
+ const validContexts = ["light", "medium", "dark"];
24595
+ for (const [context, tokens] of Object.entries(contexts)) {
24596
+ if (!validContexts.includes(context)) {
24597
+ errors.push(`Unknown context "${context}". Valid contexts: ${validContexts.join(", ")}`);
24598
+ continue;
24599
+ }
24600
+ if (typeof tokens !== "object" || tokens === null) {
24601
+ errors.push(`Context "${context}" must be an object`);
24602
+ }
24603
+ }
24604
+ return { valid: errors.length === 0, errors };
24605
+ }
24606
+ function validateFonts(fonts) {
24607
+ const errors = [];
24608
+ if (!fonts || typeof fonts !== "object") {
24609
+ return { valid: true, errors };
24610
+ }
24611
+ if (fonts.import !== void 0) {
24612
+ if (!Array.isArray(fonts.import)) {
24613
+ errors.push("fonts.import must be an array");
24614
+ } else {
24615
+ for (const [index, item] of fonts.import.entries()) {
24616
+ if (typeof item !== "object" || !item.url) {
24617
+ errors.push(`fonts.import[${index}] must have a "url" property`);
24618
+ }
24619
+ }
24620
+ }
24621
+ }
24622
+ return { valid: errors.length === 0, errors };
24623
+ }
24624
+ function validateAppearance(appearance) {
24625
+ const errors = [];
24626
+ if (!appearance || typeof appearance !== "object") {
24627
+ if (typeof appearance === "string") {
24628
+ if (!["light", "dark", "system"].includes(appearance)) {
24629
+ errors.push(`Invalid appearance value: ${appearance}. Must be "light", "dark", or "system"`);
24630
+ }
24631
+ }
24632
+ return { valid: errors.length === 0, errors };
24633
+ }
24634
+ if (appearance.default && !["light", "dark", "system"].includes(appearance.default)) {
24635
+ errors.push(`Invalid appearance.default: ${appearance.default}`);
24636
+ }
24637
+ if (appearance.schemes !== void 0) {
24638
+ if (!Array.isArray(appearance.schemes)) {
24639
+ errors.push("appearance.schemes must be an array");
24640
+ } else {
24641
+ const validSchemes = ["light", "dark"];
24642
+ for (const scheme of appearance.schemes) {
24643
+ if (!validSchemes.includes(scheme)) {
24644
+ errors.push(`Invalid scheme: ${scheme}. Valid schemes: ${validSchemes.join(", ")}`);
24645
+ }
24646
+ }
24647
+ }
24648
+ }
24649
+ return { valid: errors.length === 0, errors };
24650
+ }
24651
+ function validateCodeTheme(code) {
24652
+ const errors = [];
24653
+ if (!code || typeof code !== "object") {
24654
+ return { valid: true, errors };
24655
+ }
24656
+ for (const [name, value] of Object.entries(code)) {
24657
+ if (typeof value !== "string") {
24658
+ errors.push(`code.${name} must be a string, got ${typeof value}`);
24659
+ continue;
24660
+ }
24661
+ if (!isValidColor(value)) {
24662
+ errors.push(`code.${name} has invalid color value: ${value}`);
24663
+ }
24664
+ }
24665
+ return { valid: errors.length === 0, errors };
24666
+ }
24667
+ var CONTEXT_AWARE_TYPES = /* @__PURE__ */ new Set(["color", "gradient"]);
24668
+ function validateFoundationVars(vars) {
24669
+ const errors = [];
24670
+ if (!vars || typeof vars !== "object") {
24671
+ return { valid: true, errors };
24672
+ }
24673
+ for (const [name, config] of Object.entries(vars)) {
24674
+ if (!/^[a-z][a-z0-9-]*$/i.test(name)) {
24675
+ errors.push(`Invalid variable name "${name}". Use lowercase letters, numbers, and hyphens.`);
24676
+ }
24677
+ if (typeof config !== "object" && typeof config !== "string" && typeof config !== "number") {
24678
+ errors.push(`Variable "${name}" must have a string, number, or config object value`);
24679
+ }
24680
+ }
24681
+ return { valid: errors.length === 0, errors };
24682
+ }
24683
+ function validateThemeConfig(config) {
24684
+ const allErrors = [];
24685
+ if (!config || typeof config !== "object") {
24686
+ return { valid: true, errors: [] };
24687
+ }
24688
+ const colorValidation = validateColors(config.colors);
24689
+ const contextValidation = validateContexts(config.contexts);
24690
+ const fontValidation = validateFonts(config.fonts);
24691
+ const appearanceValidation = validateAppearance(config.appearance);
24692
+ const codeValidation = validateCodeTheme(config.code);
24693
+ allErrors.push(...colorValidation.errors);
24694
+ allErrors.push(...contextValidation.errors);
24695
+ allErrors.push(...fontValidation.errors);
24696
+ allErrors.push(...appearanceValidation.errors);
24697
+ allErrors.push(...codeValidation.errors);
24698
+ return {
24699
+ valid: allErrors.length === 0,
24700
+ errors: allErrors
24701
+ };
24702
+ }
24703
+ function mergeInlineStyles(defaults, overrides) {
24704
+ const merged = { ...defaults };
24705
+ for (const [name, style] of Object.entries(overrides || {})) {
24706
+ merged[name] = style && typeof style === "object" && !Array.isArray(style) ? { ...defaults[name] || {}, ...style } : style;
24707
+ }
24708
+ return merged;
24709
+ }
24710
+ function normalizeAppearance(appearance) {
24711
+ if (!appearance) {
24712
+ return { ...DEFAULT_APPEARANCE };
24713
+ }
24714
+ if (typeof appearance === "string") {
24715
+ return {
24716
+ default: appearance,
24717
+ allowToggle: false,
24718
+ respectSystemPreference: appearance === "system"
24719
+ };
24720
+ }
24721
+ return {
24722
+ ...DEFAULT_APPEARANCE,
24723
+ ...appearance
24724
+ };
24725
+ }
24726
+ function mergeFoundationVars(foundationVars = {}, siteVars = {}) {
24727
+ const flat = {};
24728
+ const colorVars = {};
24729
+ for (const [name, config] of Object.entries(foundationVars)) {
24730
+ const cfg = typeof config === "object" ? { ...config } : { default: config };
24731
+ const isContextAware = CONTEXT_AWARE_TYPES.has(cfg.type);
24732
+ if (isContextAware) {
24733
+ const defaultVal = cfg.default || "";
24734
+ colorVars[name] = { light: defaultVal, dark: defaultVal };
24735
+ } else {
24736
+ flat[name] = cfg;
24737
+ }
24738
+ }
24739
+ for (const [name, value] of Object.entries(siteVars)) {
24740
+ const schemaCfg = foundationVars[name];
24741
+ const type = typeof schemaCfg === "object" ? schemaCfg?.type : void 0;
24742
+ const isContextAware = CONTEXT_AWARE_TYPES.has(type);
24743
+ if (isContextAware) {
24744
+ if (typeof value === "object" && value !== null && (value.light || value.dark)) {
24745
+ colorVars[name] = { ...colorVars[name] || {}, ...value };
24746
+ } else {
24747
+ const strVal = String(value);
24748
+ colorVars[name] = { light: strVal, dark: strVal };
24749
+ }
24750
+ } else {
24751
+ if (flat[name]) {
24752
+ flat[name].default = value;
24753
+ } else {
24754
+ flat[name] = { default: value };
24755
+ }
24756
+ }
24757
+ }
24758
+ return { flat, colorVars };
24759
+ }
24760
+ function processTheme(rawConfig = {}, options = {}) {
24761
+ const { foundationVars = {}, strict = false } = options;
24762
+ const errors = [];
24763
+ const warnings = [];
24764
+ const validation = validateThemeConfig(rawConfig);
24765
+ if (!validation.valid) {
24766
+ errors.push(...validation.errors);
24767
+ if (strict) {
24768
+ throw new Error(`Theme configuration errors:
24769
+ ${errors.join("\n")}`);
24770
+ }
24771
+ }
24772
+ const defaultColors = getDefaultColors();
24773
+ const rawColors = { ...rawConfig.colors || {} };
24774
+ if (typeof rawColors.neutral === "string" && NEUTRAL_PRESETS[rawColors.neutral]) {
24775
+ rawColors.neutral = NEUTRAL_PRESETS[rawColors.neutral];
24776
+ }
24777
+ const brandColor = rawColors.primary ?? defaultColors.primary;
24778
+ const isUsableColor = (v) => typeof v === "object" && v !== null || isValidColor(v);
24779
+ if (rawColors.accent === void 0 && isUsableColor(brandColor)) {
24780
+ rawColors.accent = brandColor;
24781
+ }
24782
+ const validColors = {};
24783
+ for (const [name, value] of Object.entries({ ...defaultColors, ...rawColors })) {
24784
+ if (typeof value === "object" && value !== null) {
24785
+ validColors[name] = value;
24786
+ } else if (isValidColor(value)) {
24787
+ validColors[name] = value;
24788
+ }
24789
+ }
24790
+ const colors = validColors;
24791
+ const palettes = generatePalettes(colors);
24792
+ if (!rawConfig.colors?.primary) {
24793
+ warnings.push("No primary color specified, using default blue (#3b82f6)");
24794
+ }
24795
+ if (!rawConfig.colors?.neutral) {
24796
+ warnings.push("No neutral color specified, using default stone (#78716c)");
24797
+ }
24798
+ const defaultContexts = getDefaultContextTokens();
24799
+ const rawContexts = rawConfig.contexts || {};
24800
+ const contexts = {};
24801
+ for (const name of ["light", "medium", "dark"]) {
24802
+ const overrides = rawContexts[name] || {};
24803
+ const normalized = {};
24804
+ for (const [token, value] of Object.entries(overrides)) {
24805
+ normalized[token] = normalizeTokenValue(value);
24806
+ }
24807
+ contexts[name] = { ...defaultContexts[name], ...normalized };
24808
+ }
24809
+ const rawFonts = { ...rawConfig.fonts || {} };
24810
+ const appearance = normalizeAppearance(rawConfig.appearance);
24811
+ const { flat: mergedFoundationVars, colorVars } = mergeFoundationVars(
24812
+ foundationVars,
24813
+ rawConfig.vars || rawConfig.foundationVars || {}
24814
+ );
24815
+ const foundationValidation = validateFoundationVars(mergedFoundationVars);
24816
+ if (!foundationValidation.valid) {
24817
+ warnings.push(...foundationValidation.errors);
24818
+ }
24819
+ const fontRoles = {};
24820
+ for (const [name, applyTo] of Object.entries(DEFAULT_FONT_ROLES)) {
24821
+ fontRoles[name] = {
24822
+ value: DEFAULT_FONTS[name],
24823
+ applyTo: [...applyTo],
24824
+ foundationOwned: false,
24825
+ userSet: false
24826
+ };
24827
+ }
24828
+ const nonFontVars = {};
24829
+ for (const [rawName, cfg] of Object.entries(mergedFoundationVars)) {
24830
+ if (!isFontVar(rawName, cfg)) {
24831
+ nonFontVars[rawName] = cfg;
24832
+ continue;
24833
+ }
24834
+ const name = normalizeFontRoleName(rawName);
24835
+ const cfgObj = typeof cfg === "object" ? cfg : { default: cfg };
24836
+ const existing = fontRoles[name];
24837
+ fontRoles[name] = {
24838
+ value: cfgObj.default ?? existing?.value,
24839
+ applyTo: cfgObj.applyTo !== void 0 ? normalizeApplyTo(cfgObj.applyTo) : existing?.applyTo ?? null,
24840
+ foundationOwned: true,
24841
+ userSet: false
24842
+ };
24843
+ }
24844
+ const FONT_LOADING_KEYS = /* @__PURE__ */ new Set(["import", "faces"]);
24845
+ for (const [rawName, value] of Object.entries(rawFonts)) {
24846
+ if (FONT_LOADING_KEYS.has(rawName)) continue;
24847
+ const name = normalizeFontRoleName(rawName);
24848
+ const existing = fontRoles[name];
24849
+ fontRoles[name] = {
24850
+ value,
24851
+ applyTo: existing?.applyTo ?? null,
24852
+ foundationOwned: existing?.foundationOwned ?? false,
24853
+ userSet: true
24854
+ };
24855
+ }
24856
+ for (const role of Object.values(fontRoles)) {
24857
+ const intended = role.foundationOwned || role.userSet;
24858
+ role.apply = intended && Array.isArray(role.applyTo) && role.applyTo.length > 0;
24859
+ role.load = intended;
24860
+ }
24861
+ if (rawFonts.mono !== void 0 && !fontRoles.mono?.foundationOwned) {
24862
+ warnings.push("theme.yml `fonts.mono` is not a built-in font role \u2014 the code/monospace role is `code`. Rename `fonts.mono` \u2192 `fonts.code`.");
24863
+ }
24864
+ const fonts = {};
24865
+ if (rawFonts.import !== void 0) fonts.import = rawFonts.import;
24866
+ if (rawFonts.faces !== void 0) fonts.faces = rawFonts.faces;
24867
+ for (const [name, role] of Object.entries(fontRoles)) {
24868
+ fonts[name] = role.value;
24869
+ }
24870
+ const code = rawConfig.code ?? null;
24871
+ const background = rawConfig.background || null;
24872
+ const inline = mergeInlineStyles(DEFAULT_INLINE, rawConfig.inline);
24873
+ const config = {
24874
+ colors,
24875
+ // Raw colors for CSS generator
24876
+ palettes,
24877
+ // Generated palettes for Theme class
24878
+ contexts,
24879
+ fonts,
24880
+ // name→value (+ import/faces) for the Theme API and loading
24881
+ fontRoles,
24882
+ // resolved font-role map (value/applyTo/apply/load) for CSS gen
24883
+ appearance,
24884
+ foundationVars: nonFontVars,
24885
+ // NON-font vars only (font vars live in fontRoles)
24886
+ colorVars,
24887
+ // Context-aware vars: { light: {...}, dark: {...} }
24888
+ code,
24889
+ // Code block theme for runtime injection
24890
+ background,
24891
+ // Site-level background CSS value
24892
+ inline
24893
+ // Inline text style definitions
24894
+ };
24895
+ return { config, errors, warnings };
24896
+ }
24897
+
23975
24898
  // ../theming/src/section-overrides.js
23976
24899
  function hasOverrides(standardOptions) {
23977
24900
  if (!standardOptions) return false;
@@ -24074,7 +24997,53 @@ function buildSectionOverrides(blocks, appearance = {}) {
24074
24997
  return css;
24075
24998
  }
24076
24999
 
25000
+ // ../theming/src/index.js
25001
+ function buildTheme(themeYml = {}, options = {}) {
25002
+ const { config, errors, warnings } = processTheme(themeYml, options);
25003
+ const { css, links } = generateThemeCSS(config, { base: options.base });
25004
+ return {
25005
+ css,
25006
+ links,
25007
+ config,
25008
+ errors,
25009
+ warnings
25010
+ };
25011
+ }
25012
+
24077
25013
  // ../core/src/block.js
25014
+ function liftContainers(content) {
25015
+ if (!content || !Array.isArray(content.content)) return { content, refs: [] };
25016
+ const refs = [];
25017
+ const visit3 = (nodes) => {
25018
+ let changed = false;
25019
+ const out = nodes.map((node) => {
25020
+ if (!node) return node;
25021
+ if (node.type === "inset_block") {
25022
+ const { component, ...params } = node.attrs || {};
25023
+ const refId = `container_${refs.length}`;
25024
+ refs.push({
25025
+ refId,
25026
+ type: component,
25027
+ params,
25028
+ content: { type: "doc", content: node.content || [] }
25029
+ });
25030
+ changed = true;
25031
+ return { type: "inset_placeholder", attrs: { refId, embedKind: "block" } };
25032
+ }
25033
+ if (Array.isArray(node.content)) {
25034
+ const inner = visit3(node.content);
25035
+ if (inner !== node.content) {
25036
+ changed = true;
25037
+ return { ...node, content: inner };
25038
+ }
25039
+ }
25040
+ return node;
25041
+ });
25042
+ return changed ? out : nodes;
25043
+ };
25044
+ const next = visit3(content.content);
25045
+ return next === content.content ? { content, refs } : { content: { ...content, content: next }, refs };
25046
+ }
24078
25047
  var Block = class _Block {
24079
25048
  constructor(blockData, id, page) {
24080
25049
  this.id = id;
@@ -24083,8 +25052,9 @@ var Block = class _Block {
24083
25052
  this.website = page.website;
24084
25053
  this.type = blockData.type || this.website.getDefaultBlockType();
24085
25054
  this.Component = null;
24086
- this.rawContent = blockData.content || {};
24087
- this.parsedContent = this.parseContent(blockData.content);
25055
+ const lifted = liftContainers(blockData.content);
25056
+ this.rawContent = lifted.content || {};
25057
+ this.parsedContent = this.parseContent(lifted.content);
24088
25058
  if (blockData.parsedContent?.data) {
24089
25059
  this.parsedContent.data = {
24090
25060
  ...this.parsedContent.data || {},
@@ -24143,6 +25113,22 @@ var Block = class _Block {
24143
25113
  this.insets.push(child);
24144
25114
  }
24145
25115
  }
25116
+ for (let i = 0; i < lifted.refs.length; i++) {
25117
+ const ref = lifted.refs[i];
25118
+ this.insets.push(
25119
+ new _Block(
25120
+ {
25121
+ type: ref.type,
25122
+ params: ref.params || {},
25123
+ content: ref.content,
25124
+ stableId: ref.refId,
25125
+ refId: ref.refId
25126
+ },
25127
+ `${id}_container_${i}`,
25128
+ this.page
25129
+ )
25130
+ );
25131
+ }
24146
25132
  this.fetch = blockData.fetch || null;
24147
25133
  this.dataLoading = false;
24148
25134
  this.hasBackground = false;
@@ -24389,6 +25375,10 @@ var Block = class _Block {
24389
25375
  * @returns {Object|null} Next block's info or null
24390
25376
  */
24391
25377
  getNextBlockInfo() {
25378
+ const active = this.website?.activePage;
25379
+ if (active && active !== this.page) {
25380
+ return active.getFirstBodyBlockInfo();
25381
+ }
24392
25382
  const index = this.getIndex();
24393
25383
  if (index < 0 || !this.page) return null;
24394
25384
  return this.page.getBlockInfo(index + 1);
@@ -24399,6 +25389,10 @@ var Block = class _Block {
24399
25389
  * @returns {Object|null} Previous block's info or null
24400
25390
  */
24401
25391
  getPrevBlockInfo() {
25392
+ const active = this.website?.activePage;
25393
+ if (active && active !== this.page) {
25394
+ return active.getLastBodyBlockInfo();
25395
+ }
24402
25396
  const index = this.getIndex();
24403
25397
  if (index <= 0 || !this.page) return null;
24404
25398
  return this.page.getBlockInfo(index - 1);
@@ -24621,6 +25615,20 @@ var ObservableState = class {
24621
25615
  }
24622
25616
  };
24623
25617
 
25618
+ // ../core/src/seo.js
25619
+ function normalizeSeo(raw) {
25620
+ const seo = raw || {};
25621
+ return {
25622
+ noindex: seo.noindex || false,
25623
+ image: seo.image || null,
25624
+ ogTitle: seo.ogTitle || null,
25625
+ ogDescription: seo.ogDescription || null,
25626
+ canonical: seo.canonical || null,
25627
+ changefreq: seo.changefreq || null,
25628
+ priority: seo.priority || null
25629
+ };
25630
+ }
25631
+
24624
25632
  // ../core/src/page.js
24625
25633
  function normalizeHideIn(pageData) {
24626
25634
  const out = [];
@@ -24662,15 +25670,7 @@ var Page = class {
24662
25670
  hide: pageData.layout?.hide || [],
24663
25671
  params: pageData.layout?.params || {}
24664
25672
  };
24665
- this.seo = {
24666
- noindex: pageData.seo?.noindex || false,
24667
- image: pageData.seo?.image || null,
24668
- ogTitle: pageData.seo?.ogTitle || null,
24669
- ogDescription: pageData.seo?.ogDescription || null,
24670
- canonical: pageData.seo?.canonical || null,
24671
- changefreq: pageData.seo?.changefreq || null,
24672
- priority: pageData.seo?.priority || null
24673
- };
25673
+ this.seo = normalizeSeo(pageData.seo);
24674
25674
  this.parent = null;
24675
25675
  this.children = [];
24676
25676
  this.website = website;
@@ -24716,16 +25716,20 @@ var Page = class {
24716
25716
  */
24717
25717
  getHeadMeta() {
24718
25718
  const resolvedTitle = this.getTitle();
25719
+ const site = this.website?.seo || {};
25720
+ const siteKeywords = this.website?.keywords || null;
24719
25721
  return {
24720
25722
  title: resolvedTitle,
24721
25723
  description: this.description,
24722
- keywords: this.keywords,
25724
+ keywords: this.keywords || siteKeywords,
24723
25725
  canonical: this.seo.canonical,
24724
- robots: this.seo.noindex ? "noindex, nofollow" : null,
25726
+ robots: this.seo.noindex || site.noindex ? "noindex, nofollow" : null,
24725
25727
  og: {
24726
- title: this.seo.ogTitle || resolvedTitle,
24727
- description: this.seo.ogDescription || this.description,
24728
- image: this.seo.image,
25728
+ // Page content wins; site-level seo only fills gaps. Image is the
25729
+ // exception authors most want cascaded (the shared social card).
25730
+ title: this.seo.ogTitle || resolvedTitle || site.ogTitle,
25731
+ description: this.seo.ogDescription || this.description || site.ogDescription,
25732
+ image: this.seo.image || site.image,
24729
25733
  url: this.route
24730
25734
  }
24731
25735
  };
@@ -24812,6 +25816,17 @@ var Page = class {
24812
25816
  getFirstBodyBlockInfo() {
24813
25817
  return this.bodyBlocks?.[0]?.getBlockInfo() || null;
24814
25818
  }
25819
+ /**
25820
+ * Get the last body block's info.
25821
+ * Symmetric to getFirstBodyBlockInfo — e.g. a footer adapting to the
25822
+ * content section directly above it.
25823
+ *
25824
+ * @returns {Object|null} Last body block's info or null
25825
+ */
25826
+ getLastBodyBlockInfo() {
25827
+ const blocks = this.bodyBlocks;
25828
+ return blocks?.[blocks.length - 1]?.getBlockInfo() || null;
25829
+ }
24815
25830
  /**
24816
25831
  * Get all blocks (header, body, footer) as flat array
24817
25832
  * Respects page layout preferences (hide list)
@@ -24927,11 +25942,13 @@ var Page = class {
24927
25942
  /**
24928
25943
  * Check if page should appear in a named nav area ('header', 'footer', or any
24929
25944
  * foundation-declared area). The general form behind showInHeader/showInFooter.
25945
+ * False when the page is unpublished (`hidden`), suppressed from every area
25946
+ * (`hideIn` contains '*'), or suppressed from this specific area.
24930
25947
  * @param {string} area
24931
25948
  * @returns {boolean}
24932
25949
  */
24933
25950
  showInNav(area) {
24934
- return !this.hidden && !this.hideIn.includes(area);
25951
+ return !this.hidden && !this.hideIn.includes("*") && !this.hideIn.includes(area);
24935
25952
  }
24936
25953
  /**
24937
25954
  * Check if page should appear in header navigation
@@ -25307,10 +26324,52 @@ function substitutePlaceholders(value, context, options = {}) {
25307
26324
  return value;
25308
26325
  }
25309
26326
 
25310
- // ../core/src/entity-store.js
25311
- function isRefinement(bf) {
25312
- return bf?.refine === true || bf?.inherit === true;
26327
+ // ../core/src/fetch-config.js
26328
+ function isFetchRefinement(cfg) {
26329
+ return cfg?.refine === true || cfg?.inherit === true;
26330
+ }
26331
+ function localizeConfig(cfg, locale, defaultLocale) {
26332
+ if (!cfg.path) return cfg;
26333
+ if (!locale || locale === defaultLocale) return cfg;
26334
+ if (!cfg.path.startsWith("/data/")) return cfg;
26335
+ return { ...cfg, path: `/${locale}${cfg.path}` };
26336
+ }
26337
+ function applyDeferredDetail(cfg, collections) {
26338
+ if (cfg.detail !== void 0) return cfg;
26339
+ const schema4 = cfg.schema;
26340
+ if (!schema4 || !collections) return cfg;
26341
+ const collConfig = collections[schema4];
26342
+ if (!collConfig || typeof collConfig !== "object") return cfg;
26343
+ const deferred = Array.isArray(collConfig.deferred) ? collConfig.deferred : null;
26344
+ if (!deferred || deferred.length === 0) return cfg;
26345
+ const pattern = typeof collConfig.detailUrl === "string" ? collConfig.detailUrl : `/data/${schema4}/{slug}.json`;
26346
+ return { ...cfg, detail: pattern };
26347
+ }
26348
+ function resolveFetchConfigs(sources, options = {}) {
26349
+ const {
26350
+ schemas: schemas2 = [],
26351
+ locale = null,
26352
+ defaultLocale = null,
26353
+ collections = null
26354
+ } = options;
26355
+ const configs = /* @__PURE__ */ new Map();
26356
+ const collectAll = schemas2.length === 0;
26357
+ for (const source of sources) {
26358
+ if (!source) continue;
26359
+ const configList = Array.isArray(source) ? source : [source];
26360
+ for (const cfg of configList) {
26361
+ if (!cfg?.schema) continue;
26362
+ if (configs.has(cfg.schema)) continue;
26363
+ if (!collectAll && !schemas2.includes(cfg.schema)) continue;
26364
+ const localized = localizeConfig(cfg, locale, defaultLocale);
26365
+ configs.set(cfg.schema, applyDeferredDetail(localized, collections));
26366
+ }
26367
+ }
26368
+ return configs;
25313
26369
  }
26370
+
26371
+ // ../core/src/entity-store.js
26372
+ var isRefinement = isFetchRefinement;
25314
26373
  var inheritDeprecationWarned = false;
25315
26374
  function warnInheritDeprecation(block) {
25316
26375
  if (inheritDeprecationWarned) return;
@@ -25367,93 +26426,58 @@ var EntityStore = class {
25367
26426
  if (meta.inheritData === false) return null;
25368
26427
  return [];
25369
26428
  }
25370
- /**
25371
- * Return a localized copy of a fetch config for collection data.
25372
- * Non-default locales get /{locale} prefixed onto /data/ paths so the
25373
- * client fetches the translated JSON (/fr/data/articles.json).
25374
- */
25375
- _localizeConfig(cfg, website) {
25376
- if (!cfg.path || !website) return cfg;
25377
- const locale = website.getActiveLocale?.();
25378
- const defaultLocale = website.getDefaultLocale?.();
25379
- if (!locale || locale === defaultLocale) return cfg;
25380
- if (!cfg.path.startsWith("/data/")) return cfg;
25381
- return { ...cfg, path: `/${locale}${cfg.path}` };
25382
- }
25383
26429
  /**
25384
26430
  * Walk the four-level hierarchy and collect fetch configs for the
25385
26431
  * requested schemas. First match per schema wins.
26432
+ *
26433
+ * This method's job is to read the four source slots off the object graph;
26434
+ * the rule applied to them (precedence, first-match-per-schema, locale
26435
+ * normalization, deferred-detail injection) lives in `./fetch-config.js`,
26436
+ * shared with every other host that has to answer the same question. Do not
26437
+ * re-inline it here — divergence between copies is what the extraction
26438
+ * exists to prevent.
25386
26439
  */
25387
26440
  _findFetchConfigs(block, requested) {
25388
- const configs = /* @__PURE__ */ new Map();
25389
- const collectAll = requested.length === 0;
25390
- const sources = [];
25391
26441
  if (block.fetch?.inherit === true && block.fetch?.refine !== true) {
25392
26442
  warnInheritDeprecation(block);
25393
26443
  }
25394
- if (block.fetch && !isRefinement(block.fetch)) sources.push(block.fetch);
25395
26444
  const page = block.page;
25396
- if (page?.fetch) sources.push(page.fetch);
25397
- if (page?.parent?.fetch) sources.push(page.parent.fetch);
25398
- const siteFetch = block.website?.config?.fetch;
25399
- if (siteFetch) sources.push(siteFetch);
25400
26445
  const website = block.website;
25401
- for (const source of sources) {
25402
- const configList = Array.isArray(source) ? source : [source];
25403
- for (const cfg of configList) {
25404
- if (!cfg.schema) continue;
25405
- if (configs.has(cfg.schema)) continue;
25406
- if (collectAll || requested.includes(cfg.schema)) {
25407
- const localized = this._localizeConfig(cfg, website);
25408
- const withDetail = this._applyDeferredDetail(localized, website);
25409
- configs.set(cfg.schema, withDetail);
25410
- }
26446
+ return resolveFetchConfigs(
26447
+ [
26448
+ block.fetch && !isRefinement(block.fetch) ? block.fetch : null,
26449
+ page?.fetch,
26450
+ page?.parent?.fetch,
26451
+ website?.config?.fetch
26452
+ ],
26453
+ {
26454
+ schemas: requested,
26455
+ locale: website?.getActiveLocale?.() ?? null,
26456
+ defaultLocale: website?.getDefaultLocale?.() ?? null,
26457
+ collections: website?.config?.collections ?? null
25411
26458
  }
25412
- }
25413
- return configs;
26459
+ );
25414
26460
  }
25415
26461
  /**
25416
- * Auto-inject `detail:` on collection refs whose collection has
25417
- * `deferred:` declared. The detail pattern points at the per-record
25418
- * source so the existing dynamic-route singular flow fetches a record
25419
- * with all fields (including the deferred ones) instead of the
25420
- * matched-item-from-the-cascade-collection (without).
25421
- *
25422
- * Two patterns:
25423
- *
25424
- * - Markdown-backed collections (the build emits per-record files
25425
- * at `/data/<name>/<slug>.json`): the auto-injected pattern is
25426
- * that path. `isLocalPath` resolution downstream gives the
25427
- * fetch a `path:` shape.
25428
- *
25429
- * - API-backed collections (the source is a remote URL; the build
25430
- * emits no per-record files): the author declares a `detailUrl:`
25431
- * on the collection — e.g., `/api/articles/{slug}` — and the
25432
- * auto-injected pattern uses it. `isLocalPath` resolution
25433
- * downstream gives the fetch a `url:` shape (because the
25434
- * collection itself has `url:`, not `path:`).
25435
- *
25436
- * Conventions:
25437
- * - Per-record sources are keyed by `item.slug`. The injected
25438
- * pattern uses the `{slug}` placeholder; substitution works when
25439
- * the dynamic route's paramName is 'slug' (the documented
25440
- * convention). Routes with other param names need an explicit
25441
- * author-written `detail:` value.
25442
- * - Author-supplied `cfg.detail` always wins. This helper only fills
25443
- * in the default for collections that have declared deferred fields.
25444
- * - Per-record files are not currently localized; sites needing
25445
- * localized deferred collections write their own `detail:` URL.
26462
+ * Post-process assembled collection data: for each fetch config that declares a
26463
+ * `detailPage` page-ref, resolve it to a locale route template (O(1), via the
26464
+ * Website's `_pageIdMap`) and inject a `route` on each record — so a dynamic-list
26465
+ * card links to the collection's canonical detail page regardless of which page
26466
+ * the list sits on. Runs after `data` is fully assembled, in BOTH the sync (peek)
26467
+ * and async (fetch) paths. Replaces the old runtime `getCollectionDetailRoute`
26468
+ * page-tree scan. A dangling `detailPage` (unresolvable ref) is a no-op — the
26469
+ * component degrades gracefully; records with a baked `route` (file lane) are kept.
25446
26470
  */
25447
- _applyDeferredDetail(cfg, website) {
25448
- if (cfg.detail !== void 0) return cfg;
25449
- const schema4 = cfg.schema;
25450
- if (!schema4) return cfg;
25451
- const collConfig = website?.config?.collections?.[schema4];
25452
- if (!collConfig || typeof collConfig !== "object") return cfg;
25453
- const deferred = Array.isArray(collConfig.deferred) ? collConfig.deferred : null;
25454
- if (!deferred || deferred.length === 0) return cfg;
25455
- const pattern = typeof collConfig.detailUrl === "string" ? collConfig.detailUrl : `/data/${schema4}/{slug}.json`;
25456
- return { ...cfg, detail: pattern };
26471
+ _applyDetailRoutes(data, configs, website) {
26472
+ if (!data || !website?.resolveDetailPageTemplate) return;
26473
+ for (const [schema4, cfg] of configs) {
26474
+ if (!cfg.detailPage) continue;
26475
+ const items = data[schema4];
26476
+ if (!Array.isArray(items) || items.length === 0) continue;
26477
+ const template = website.resolveDetailPageTemplate(cfg.detailPage);
26478
+ if (!template) continue;
26479
+ data[schema4] = items.map((item) => addDetailRoute(item, template));
26480
+ }
25457
26481
  }
25458
26482
  /**
25459
26483
  * Build a detail-URL fetch config from a collection config + dynamic context.
@@ -25593,6 +26617,7 @@ var EntityStore = class {
25593
26617
  }
25594
26618
  }
25595
26619
  if (allCached) {
26620
+ this._applyDetailRoutes(data, configs, block.website);
25596
26621
  return { status: "ready", data };
25597
26622
  }
25598
26623
  return { status: "pending", data: null };
@@ -25677,6 +26702,7 @@ var EntityStore = class {
25677
26702
  }
25678
26703
  }
25679
26704
  if (parallelFetches.length > 0) await Promise.all(parallelFetches);
26705
+ this._applyDetailRoutes(data, configs, block.website);
25680
26706
  return { data };
25681
26707
  }
25682
26708
  };
@@ -25685,6 +26711,19 @@ function peekArray(dispatcher, cfg, ctx) {
25685
26711
  if (!cached) return null;
25686
26712
  return Array.isArray(cached.data) ? cached.data : null;
25687
26713
  }
26714
+ function addDetailRoute(item, template) {
26715
+ if (!item || typeof item !== "object" || item.route !== void 0) return item;
26716
+ let missing = false;
26717
+ const route = template.replace(/:(\w+)/g, (_, name) => {
26718
+ const value = item[name];
26719
+ if (value == null) {
26720
+ missing = true;
26721
+ return "";
26722
+ }
26723
+ return encodeURIComponent(String(value));
26724
+ });
26725
+ return missing ? item : { ...item, route };
26726
+ }
25688
26727
 
25689
26728
  // ../core/src/fetcher-dispatcher.js
25690
26729
  function getFoundationDecl(mod) {
@@ -25951,6 +26990,113 @@ var FetcherDispatcher = class {
25951
26990
  }
25952
26991
  };
25953
26992
 
26993
+ // ../core/src/locale-config.js
26994
+ function codeOf(entry) {
26995
+ if (typeof entry === "string" && entry.trim() && entry.trim() !== "*") return entry.trim();
26996
+ if (entry && typeof entry === "object" && typeof entry.code === "string" && entry.code.trim()) {
26997
+ return entry.code.trim();
26998
+ }
26999
+ return null;
27000
+ }
27001
+ function isWildcardLanguages(value) {
27002
+ return value === "*" || Array.isArray(value) && value.includes("*");
27003
+ }
27004
+ function normalizeLanguageList(value) {
27005
+ if (!Array.isArray(value)) return [];
27006
+ const seen = /* @__PURE__ */ new Set();
27007
+ const codes = [];
27008
+ for (const entry of value) {
27009
+ const code = codeOf(entry);
27010
+ if (!code || seen.has(code)) continue;
27011
+ seen.add(code);
27012
+ codes.push(code);
27013
+ }
27014
+ return codes;
27015
+ }
27016
+ function resolveDefaultLocale(config = {}) {
27017
+ if (typeof config?.defaultLanguage === "string" && config.defaultLanguage.trim()) {
27018
+ return config.defaultLanguage.trim();
27019
+ }
27020
+ return normalizeLanguageList(config?.languages)[0] || "en";
27021
+ }
27022
+ function resolvePublishableLocales(config = {}) {
27023
+ const declared = normalizeLanguageList(config?.languages);
27024
+ const raw = config?.publishLanguages;
27025
+ if (raw == null) return { publishable: declared, dangling: [], explicit: false };
27026
+ const listed = normalizeLanguageList(raw);
27027
+ if (isWildcardLanguages(config?.languages)) {
27028
+ return { publishable: listed, dangling: [], explicit: true };
27029
+ }
27030
+ const declaredSet = new Set(declared);
27031
+ const listedSet = new Set(listed);
27032
+ return {
27033
+ publishable: declared.filter((code) => listedSet.has(code)),
27034
+ dangling: listed.filter((code) => !declaredSet.has(code)),
27035
+ explicit: true
27036
+ };
27037
+ }
27038
+ function validateLanguageConfig(config = {}) {
27039
+ const errors = [];
27040
+ const warnings = [];
27041
+ const inspectList = (value, field, entryCode) => {
27042
+ if (value == null) return;
27043
+ if (value === "*") return;
27044
+ if (!Array.isArray(value)) {
27045
+ warnings.push({
27046
+ code: entryCode,
27047
+ message: `${field} must be a list of locale codes (got ${typeof value}) \u2014 ignored`
27048
+ });
27049
+ return;
27050
+ }
27051
+ const seen = /* @__PURE__ */ new Set();
27052
+ for (const entry of value) {
27053
+ if (entry === "*") continue;
27054
+ const code = codeOf(entry);
27055
+ if (!code) {
27056
+ warnings.push({
27057
+ code: entryCode,
27058
+ message: `${field} entry ${JSON.stringify(entry)} is not a locale code string \u2014 dropped`
27059
+ });
27060
+ continue;
27061
+ }
27062
+ if (typeof entry !== "string") {
27063
+ warnings.push({
27064
+ code: entryCode,
27065
+ message: `${field} entry for '${code}' uses the legacy object form \u2014 use the plain string '${code}'`
27066
+ });
27067
+ }
27068
+ if (seen.has(code)) {
27069
+ warnings.push({ code: "duplicate-language", message: `${field} lists '${code}' more than once \u2014 deduped` });
27070
+ }
27071
+ seen.add(code);
27072
+ }
27073
+ };
27074
+ inspectList(config?.languages, "languages", "invalid-language-entry");
27075
+ inspectList(config?.publishLanguages, "publishLanguages", "invalid-publish-language-entry");
27076
+ const { publishable, dangling, explicit } = resolvePublishableLocales(config);
27077
+ for (const code of dangling) {
27078
+ warnings.push({
27079
+ code: "dangling-publish-language",
27080
+ message: `publishLanguages lists '${code}' but languages does not declare it \u2014 ignored at publish (kept in the file so a re-declared language keeps its publish intent)`
27081
+ });
27082
+ }
27083
+ if (explicit && publishable.length === 0) {
27084
+ errors.push({
27085
+ code: "nothing-publishable",
27086
+ message: "publishLanguages leaves no publishable language (empty list, or nothing it lists is declared) \u2014 a publishable default language is required"
27087
+ });
27088
+ } else if (explicit) {
27089
+ const defaultLocale = resolveDefaultLocale(config);
27090
+ if (!publishable.includes(defaultLocale)) {
27091
+ errors.push({
27092
+ code: "default-not-publishable",
27093
+ message: `the default language '${defaultLocale}' is not in publishLanguages \u2014 the effective default must be publishable`
27094
+ });
27095
+ }
27096
+ }
27097
+ return { errors, warnings };
27098
+ }
27099
+
25954
27100
  // ../core/src/website.js
25955
27101
  var Website = class {
25956
27102
  constructor({
@@ -25989,6 +27135,8 @@ var Website = class {
25989
27135
  this.pageRoutes = [];
25990
27136
  this.themeData = {};
25991
27137
  this.config = {};
27138
+ this.seo = {};
27139
+ this.keywords = null;
25992
27140
  this.siteDefaultLocale = "en";
25993
27141
  this.defaultLocale = "en";
25994
27142
  this.activeLocale = "en";
@@ -26050,7 +27198,9 @@ var Website = class {
26050
27198
  this.pageRoutes = this.pages.map((page) => page.route);
26051
27199
  this.themeData = theme;
26052
27200
  this.config = config;
26053
- this.siteDefaultLocale = config.defaultLanguage || "en";
27201
+ this.seo = normalizeSeo(config.seo);
27202
+ this.keywords = config.keywords || null;
27203
+ this.siteDefaultLocale = resolveDefaultLocale(config);
26054
27204
  this.defaultLocale = config.domainLocale || this.siteDefaultLocale;
26055
27205
  this.activeLocale = config.activeLocale || this.defaultLocale;
26056
27206
  this.locales = this.buildLocalesList(config);
@@ -26110,7 +27260,7 @@ var Website = class {
26110
27260
  * @private
26111
27261
  */
26112
27262
  buildLocalesList(config) {
26113
- const defaultLocale = config.defaultLanguage || "en";
27263
+ const defaultLocale = resolveDefaultLocale(config);
26114
27264
  const languages = config.languages || [];
26115
27265
  const normalizeLocale = (locale) => {
26116
27266
  if (typeof locale === "string") {
@@ -26373,8 +27523,6 @@ var Website = class {
26373
27523
  pageData.title = "Not found";
26374
27524
  pageData.notFound = true;
26375
27525
  }
26376
- pageData.dynamicContext.currentItem = currentItem || null;
26377
- pageData.dynamicContext.allItems = items;
26378
27526
  pageData._collectionLoaded = items.length > 0;
26379
27527
  }
26380
27528
  const dynamicPage = new Page(pageData, `dynamic-${concreteRoute}`, this);
@@ -26531,6 +27679,34 @@ var Website = class {
26531
27679
  }
26532
27680
  return resolvedHref;
26533
27681
  }
27682
+ /**
27683
+ * Resolve a `page:<stable_id>` detail-page reference (from a fetch config's
27684
+ * `detailPage`) to a locale-specific route TEMPLATE, e.g. '/blog/:slug'. The
27685
+ * entity store interpolates each record's field into the `:param` slot to build
27686
+ * a card's href — so a dynamic-list preview links to the collection's canonical
27687
+ * detail page regardless of which page it sits on.
27688
+ *
27689
+ * O(1): a `_pageIdMap` lookup (keyed on stable_id, same map makeHref uses), NOT
27690
+ * a page-tree scan. Returns null when the ref is unresolvable — the target page
27691
+ * was deleted or de-dynamicized (a dangling ref); the caller degrades gracefully
27692
+ * (leaves the record without a `route`). Rename-safe: a stable_id survives page
27693
+ * reorganization.
27694
+ *
27695
+ * @param {string} pageRef - `page:<stable_id>` (bare `<stable_id>` also accepted)
27696
+ * @returns {string|null} locale-specific route template, or null if unresolvable
27697
+ */
27698
+ resolveDetailPageTemplate(pageRef) {
27699
+ if (!pageRef || typeof pageRef !== "string") return null;
27700
+ const id = pageRef.startsWith("page:") ? pageRef.slice(5) : pageRef;
27701
+ const page = this._pageIdMap?.get(id);
27702
+ if (!page || !page.route) {
27703
+ if (typeof console !== "undefined" && typeof process !== "undefined" && true) {
27704
+ console.warn(`[resolveDetailPageTemplate] Detail page not found: ${pageRef}`);
27705
+ }
27706
+ return null;
27707
+ }
27708
+ return this.translateRoute(page.route);
27709
+ }
26534
27710
  /**
26535
27711
  * Get available languages
26536
27712
  * @deprecated Use getLocales() instead
@@ -26677,6 +27853,21 @@ var Website = class {
26677
27853
  const config = this.config?.search || {};
26678
27854
  return {
26679
27855
  enabled: this.isSearchEnabled(),
27856
+ // Which provider serves results. `index` (the default) downloads a
27857
+ // prebuilt index and queries it in the browser — free, and works on any
27858
+ // host. `endpoint` queries a server-side search API, which is what makes
27859
+ // dynamic/API-backed content searchable. Any other value names a
27860
+ // foundation-supplied search transport.
27861
+ //
27862
+ // Kit resolves and loads the provider; core only passes the declaration
27863
+ // through, so a site that never searches pays nothing for the vocabulary
27864
+ // (see kit's search module for the resolution rules).
27865
+ provider: config.provider || "index",
27866
+ // Base-RELATIVE path for the `endpoint` provider. Left raw here: kit
27867
+ // resolves it against `basePath`, so one spelling works whether the site
27868
+ // is served from the root, from a subdirectory, or from a backend
27869
+ // subpath. Undefined unless declared.
27870
+ endpoint: config.endpoint,
26680
27871
  indexUrl: this.getSearchIndexUrl(),
26681
27872
  locale: this.getActiveLocale(),
26682
27873
  include: {
@@ -26694,13 +27885,21 @@ var Website = class {
26694
27885
  };
26695
27886
  }
26696
27887
  /**
26697
- * Get the URL for the search index file
27888
+ * Get the URL for the search index file.
27889
+ *
27890
+ * Includes `basePath`, so the URL is correct on a site deployed under a
27891
+ * subdirectory (`base: /docs/`) and on a backend-hosted site served from a
27892
+ * subpath. Omitting it was a real bug: the returned path was fetched
27893
+ * verbatim, so search 404'd on every non-root deployment while data fetching
27894
+ * — which resolves the same base — worked.
27895
+ *
26698
27896
  * @returns {string} URL to fetch the search index
26699
27897
  */
26700
27898
  getSearchIndexUrl() {
26701
27899
  const locale = this.getActiveLocale();
26702
27900
  const isDefault = locale === this.getDefaultLocale();
26703
- return isDefault ? "/search-index.json" : `/${locale}/search-index.json`;
27901
+ const path = isDefault ? "/search-index.json" : `/${locale}/search-index.json`;
27902
+ return `${this.basePath || ""}${path}`;
26704
27903
  }
26705
27904
  /**
26706
27905
  * Get search data for all pages
@@ -26758,6 +27957,7 @@ var Website = class {
26758
27957
  if (page.isIndex && page.route.endsWith("/index")) return false;
26759
27958
  if (!includeHidden) {
26760
27959
  if (page.hidden) return false;
27960
+ if (page.hideIn?.includes("*")) return false;
26761
27961
  if (navType && page.hideIn?.includes(navType)) return false;
26762
27962
  }
26763
27963
  if (!page.hasContent()) {
@@ -26795,6 +27995,41 @@ var Website = class {
26795
27995
  };
26796
27996
  return filteredPages.map(buildPageInfo);
26797
27997
  }
27998
+ /**
27999
+ * Get the page tree for the branch a route sits in.
28000
+ *
28001
+ * A sidebar shows one branch of a site, not the whole thing: under /docs it
28002
+ * lists the documentation, and under a different top-level section it would
28003
+ * list that instead. Every documentation shell built on this framework has
28004
+ * hand-written the same narrowing, so it lives here — it is a question about
28005
+ * the page graph, with no React and no DOM in it.
28006
+ *
28007
+ * Answers the branch's children when it has any, the branch itself when it
28008
+ * is a leaf, and the whole hierarchy when the route matches no branch (the
28009
+ * site root, most often). The pages come back in the order the build settled
28010
+ * on; `pages:` lists are resolved at build time, so there is nothing to sort.
28011
+ *
28012
+ * @param {Object} [options]
28013
+ * @param {string} options.route - The active route, e.g. '/docs/reference/cli'
28014
+ * @param {string} [options.for] - Layout area being filled ('left', 'header', …).
28015
+ * Checked against each page's `hideIn`, so a page can sit out of this rail
28016
+ * while staying in the menu. Name the area the tree is actually for.
28017
+ * @param {boolean} [options.includeHidden=false] - Include unpublished pages
28018
+ * @returns {Array<Object>} Page info objects, nested
28019
+ *
28020
+ * @example
28021
+ * // In a sidebar component rendered into the `left` layout area
28022
+ * const pages = website.getBranchHierarchy({ route: location.pathname, for: 'left' })
28023
+ */
28024
+ getBranchHierarchy({ route = "", for: navType, includeHidden = false } = {}) {
28025
+ const normalize = (value) => (value || "").replace(/^\/+/, "").replace(/\/+$/, "");
28026
+ const all = this.getPageHierarchy({ for: navType, includeHidden });
28027
+ const branchName = normalize(route).split("/")[0];
28028
+ if (!branchName) return all;
28029
+ const branch = all.find((page) => normalize(page.route) === branchName);
28030
+ if (!branch) return all;
28031
+ return branch.children?.length ? branch.children : [branch];
28032
+ }
26798
28033
  /**
26799
28034
  * Get pages for header navigation
26800
28035
  * Convenience method equivalent to getPageHierarchy({ for: 'header' })
@@ -27361,9 +28596,9 @@ var Uniweb = class {
27361
28596
  };
27362
28597
 
27363
28598
  // ../core/src/theme.js
27364
- var SHADE_LEVELS3 = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
28599
+ var SHADE_LEVELS4 = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
27365
28600
  var VALID_CONTEXTS = ["light", "medium", "dark"];
27366
- var DEFAULT_CONTEXT_TOKENS = {
28601
+ var DEFAULT_CONTEXT_TOKENS2 = {
27367
28602
  light: {
27368
28603
  bg: "var(--neutral-50)",
27369
28604
  text: "var(--neutral-950)",
@@ -27502,7 +28737,7 @@ var Theme = class {
27502
28737
  if (customContext && customContext[token]) {
27503
28738
  return customContext[token];
27504
28739
  }
27505
- const defaults = DEFAULT_CONTEXT_TOKENS[context];
28740
+ const defaults = DEFAULT_CONTEXT_TOKENS2[context];
27506
28741
  return defaults?.[token] || null;
27507
28742
  }
27508
28743
  /**
@@ -27512,7 +28747,7 @@ var Theme = class {
27512
28747
  * @returns {Object} Token name → value mapping
27513
28748
  */
27514
28749
  getContextTokens(context) {
27515
- const defaults = DEFAULT_CONTEXT_TOKENS[context] || {};
28750
+ const defaults = DEFAULT_CONTEXT_TOKENS2[context] || {};
27516
28751
  const custom = this._contexts[context] || {};
27517
28752
  return { ...defaults, ...custom };
27518
28753
  }
@@ -27621,7 +28856,8 @@ var Theme = class {
27621
28856
  /**
27622
28857
  * Get a specific font family
27623
28858
  *
27624
- * @param {string} type - Font type ('body', 'heading', 'mono')
28859
+ * @param {string} type - Font role name ('body', 'heading', 'code', or a
28860
+ * foundation-defined role)
27625
28861
  * @returns {string|null} Font family string or null
27626
28862
  */
27627
28863
  getFont(type) {
@@ -27630,7 +28866,7 @@ var Theme = class {
27630
28866
  /**
27631
28867
  * Get CSS variable reference for a font
27632
28868
  *
27633
- * @param {string} type - Font type
28869
+ * @param {string} type - Font role name
27634
28870
  * @returns {string} CSS var() reference
27635
28871
  */
27636
28872
  getFontVar(type) {
@@ -27680,7 +28916,7 @@ var Theme = class {
27680
28916
  * @returns {number[]}
27681
28917
  */
27682
28918
  getShadeLevels() {
27683
- return [...SHADE_LEVELS3];
28919
+ return [...SHADE_LEVELS4];
27684
28920
  }
27685
28921
  /**
27686
28922
  * Check if theme has any custom configuration
@@ -27706,6 +28942,11 @@ var Theme = class {
27706
28942
  };
27707
28943
  }
27708
28944
  };
28945
+ function hasDarkScheme(appearance = {}) {
28946
+ return Boolean(
28947
+ appearance.allowToggle || appearance.default === "dark" || appearance.default === "system" || appearance.schemes?.includes("dark")
28948
+ );
28949
+ }
27709
28950
 
27710
28951
  // ../core/src/where.js
27711
28952
  var OPERATORS = /* @__PURE__ */ new Set([
@@ -28184,6 +29425,16 @@ function createUniweb(content, foundation = null, extensions = [], { defaultFetc
28184
29425
  // dist/ssr.js
28185
29426
  var import_react = __toESM(require_react(), 1);
28186
29427
  var import_server = __toESM(require_server_browser(), 1);
29428
+
29429
+ // ../core/src/section-id.js
29430
+ var PREFIX = "section-";
29431
+ function sectionDomId(section) {
29432
+ if (!section) return `${PREFIX}unknown`;
29433
+ const id = section.stableId || section.id;
29434
+ return `${PREFIX}${id === void 0 || id === null || id === "" ? "unknown" : id}`;
29435
+ }
29436
+
29437
+ // dist/ssr.js
28187
29438
  function guaranteeItemStructure(item) {
28188
29439
  return {
28189
29440
  title: item.title || "",
@@ -28442,7 +29693,7 @@ function wireFoundationCapabilities(uniweb, foundation) {
28442
29693
  }
28443
29694
  }
28444
29695
  function sliceContentForLocale(content, locale) {
28445
- const defaultLang = content?.config?.defaultLanguage || "en";
29696
+ const defaultLang = resolveDefaultLocale(content?.config);
28446
29697
  const locData = content?.locales?.[locale];
28447
29698
  if (!locale || locale === defaultLang || !locData) return content;
28448
29699
  return {
@@ -28461,6 +29712,21 @@ function hydrateDataStore(website, fetchedData) {
28461
29712
  website.dataStore.set(deriveCacheKey(entry.config), { data: entry.data });
28462
29713
  }
28463
29714
  }
29715
+ function ensureThemeCss(uniweb, foundation) {
29716
+ const website = uniweb?.activeWebsite;
29717
+ const themeData = website?.themeData;
29718
+ if (!themeData || themeData.css) return;
29719
+ const caps = foundation?.default?.capabilities || {};
29720
+ try {
29721
+ const { config, css, links } = buildTheme(themeData, {
29722
+ foundationVars: caps.vars || {},
29723
+ base: website.basePath || "/"
29724
+ });
29725
+ Object.assign(themeData, config, { css, links });
29726
+ } catch (err) {
29727
+ console.warn("[uniweb] theme CSS generation failed:", err?.message || err);
29728
+ }
29729
+ }
28464
29730
  var NS = "uw-";
28465
29731
  var toIdent = (name) => NS + String(name).replace(/[^a-zA-Z0-9_-]/g, "-");
28466
29732
  function resolveLayoutTransitions(areaNames, explicit) {
@@ -28469,6 +29735,46 @@ function resolveLayoutTransitions(areaNames, explicit) {
28469
29735
  for (const name of areaNames) transitions[name] = toIdent(name);
28470
29736
  return explicit ? { ...transitions, ...explicit } : transitions;
28471
29737
  }
29738
+ function applyBootScheme(respectSystem, fallback) {
29739
+ var stored = null;
29740
+ try {
29741
+ stored = localStorage.getItem("uniweb-appearance");
29742
+ } catch (e) {
29743
+ }
29744
+ var hasStored = stored === "light" || stored === "dark";
29745
+ var scheme = hasStored ? stored : fallback;
29746
+ if (!hasStored && respectSystem) {
29747
+ try {
29748
+ if (window.matchMedia("(prefers-color-scheme: dark)").matches) scheme = "dark";
29749
+ } catch (e) {
29750
+ }
29751
+ }
29752
+ try {
29753
+ var root = document.documentElement;
29754
+ if (scheme === "dark") {
29755
+ root.classList.add("scheme-dark");
29756
+ root.classList.remove("scheme-light");
29757
+ } else {
29758
+ root.classList.add("scheme-light");
29759
+ root.classList.remove("scheme-dark");
29760
+ }
29761
+ } catch (e) {
29762
+ }
29763
+ return scheme;
29764
+ }
29765
+ function resolveAppearanceBoot(appearance) {
29766
+ if (!appearance || !hasDarkScheme(appearance)) return null;
29767
+ return {
29768
+ respectSystem: appearance.respectSystemPreference !== false,
29769
+ fallback: appearance.default === "dark" ? "dark" : "light"
29770
+ };
29771
+ }
29772
+ function renderAppearanceBootScript(appearance) {
29773
+ const opts = resolveAppearanceBoot(appearance);
29774
+ if (!opts) return "";
29775
+ const call = `(${applyBootScheme.toString()})(${opts.respectSystem}, ${JSON.stringify(opts.fallback)})`;
29776
+ return `<script id="uniweb-appearance">${call}<\/script>`;
29777
+ }
28472
29778
  var VALID_CONTEXTS2 = ["light", "medium", "dark"];
28473
29779
  function getWrapperProps(block) {
28474
29780
  const theme = block.themeName;
@@ -28492,8 +29798,7 @@ function getWrapperProps(block) {
28492
29798
  style[`--${key}`] = value;
28493
29799
  }
28494
29800
  }
28495
- const sectionId = block.stableId || block.id;
28496
- return { id: `section-${sectionId}`, style, className, background };
29801
+ return { id: sectionDomId(block), style, className, background };
28497
29802
  }
28498
29803
  function withOpacity(color, opacity) {
28499
29804
  if (color.startsWith("#")) {
@@ -28706,15 +30011,15 @@ function renderLayout(page, website) {
28706
30011
  return import_react.default.createElement(
28707
30012
  import_react.default.Fragment,
28708
30013
  null,
28709
- areaElements.header && import_react.default.createElement("header", null, areaElements.header),
30014
+ areaElements.header && import_react.default.createElement("header", { style: { position: "relative", zIndex: 40 } }, areaElements.header),
28710
30015
  bodyElement && import_react.default.createElement("main", null, bodyElement),
28711
- areaElements.footer && import_react.default.createElement("footer", null, areaElements.footer)
30016
+ areaElements.footer && import_react.default.createElement("footer", { style: { position: "relative", zIndex: 30 } }, areaElements.footer)
28712
30017
  );
28713
30018
  }
28714
30019
  function initPrerenderForLocale(content, foundation, locale, extensionsOrOptions, maybeOptions) {
28715
30020
  const localeContent = sliceContentForLocale(content, locale);
28716
30021
  const uniweb = initPrerender(localeContent, foundation, extensionsOrOptions, maybeOptions);
28717
- const defaultLang = content?.config?.defaultLanguage || "en";
30022
+ const defaultLang = resolveDefaultLocale(content?.config);
28718
30023
  if (locale && locale !== defaultLang && uniweb.activeWebsite?.setActiveLocale) {
28719
30024
  uniweb.activeWebsite.setActiveLocale(locale);
28720
30025
  }
@@ -28747,6 +30052,7 @@ function initPrerender(content, foundation, extensionsOrOptions, maybeOptions) {
28747
30052
  );
28748
30053
  };
28749
30054
  wireFoundationCapabilities(uniweb, foundation);
30055
+ ensureThemeCss(uniweb, foundation);
28750
30056
  const website = uniweb.activeWebsite;
28751
30057
  uniweb.routingComponents = {
28752
30058
  useLocation: () => {
@@ -28824,6 +30130,23 @@ function escapeHtml(str) {
28824
30130
  }
28825
30131
  function injectPageContent(html, renderedContent, page, options = {}) {
28826
30132
  let result = html;
30133
+ if (!result.includes('id="uniweb-appearance"')) {
30134
+ const bootScript = renderAppearanceBootScript(page?.website?.themeData?.appearance);
30135
+ if (bootScript) {
30136
+ result = result.replace("</head>", ` ${bootScript}
30137
+ </head>`);
30138
+ }
30139
+ }
30140
+ const themeCss = page?.website?.themeData?.css;
30141
+ if (themeCss && !result.includes('id="uniweb-theme"')) {
30142
+ result = result.replace(
30143
+ "</head>",
30144
+ ` <style id="uniweb-theme">
30145
+ ${themeCss}
30146
+ </style>
30147
+ </head>`
30148
+ );
30149
+ }
28827
30150
  if (options.sectionOverrideCSS) {
28828
30151
  const overrideStyle = `<style id="uniweb-page-overrides">
28829
30152
  ${options.sectionOverrideCSS}
@@ -28851,6 +30174,26 @@ ${options.sectionOverrideCSS}
28851
30174
  </head>`);
28852
30175
  }
28853
30176
  }
30177
+ const headMeta = page.getHeadMeta?.();
30178
+ if (headMeta) {
30179
+ const og = headMeta.og || {};
30180
+ const keywords = Array.isArray(headMeta.keywords) ? headMeta.keywords.join(", ") : headMeta.keywords;
30181
+ const tags = [];
30182
+ if (keywords) tags.push(`<meta name="keywords" content="${escapeHtml(keywords)}">`);
30183
+ if (headMeta.robots) tags.push(`<meta name="robots" content="${escapeHtml(headMeta.robots)}">`);
30184
+ if (og.title) tags.push(`<meta property="og:title" content="${escapeHtml(og.title)}">`);
30185
+ if (og.description) tags.push(`<meta property="og:description" content="${escapeHtml(og.description)}">`);
30186
+ if (og.image) tags.push(`<meta property="og:image" content="${escapeHtml(og.image)}">`);
30187
+ if (og.url) tags.push(`<meta property="og:url" content="${escapeHtml(og.url)}">`);
30188
+ tags.push('<meta property="og:type" content="website">');
30189
+ tags.push(`<meta name="twitter:card" content="${og.image ? "summary_large_image" : "summary"}">`);
30190
+ if (og.title) tags.push(`<meta name="twitter:title" content="${escapeHtml(og.title)}">`);
30191
+ if (og.description) tags.push(`<meta name="twitter:description" content="${escapeHtml(og.description)}">`);
30192
+ if (og.image) tags.push(`<meta name="twitter:image" content="${escapeHtml(og.image)}">`);
30193
+ if (headMeta.canonical) tags.push(`<link rel="canonical" href="${escapeHtml(headMeta.canonical)}">`);
30194
+ if (tags.length) result = result.replace("</head>", `${tags.join("\n")}
30195
+ </head>`);
30196
+ }
28854
30197
  return result;
28855
30198
  }
28856
30199
  function generate404Html({ baseHtml, website, siteContent }) {
@@ -28885,8 +30228,9 @@ function generate404Html({ baseHtml, website, siteContent }) {
28885
30228
  }
28886
30229
 
28887
30230
  // dist/worker-runtime-entry.js
28888
- globalThis.__PLATFORM_REACT = __PlatformReact;
28889
- globalThis.__PLATFORM_JSX_RUNTIME = __PlatformJsxRuntime;
30231
+ globalThis.__PLATFORM_REACT = __P0;
30232
+ globalThis.__PLATFORM_REACT_DOM = __P1;
30233
+ globalThis.__PLATFORM_JSX_RUNTIME = __P2;
28890
30234
  globalThis.__PLATFORM_UNIWEB_CORE = src_exports;
28891
30235
  export {
28892
30236
  applyDefaults,
@@ -28904,6 +30248,7 @@ export {
28904
30248
  injectPageContent,
28905
30249
  prefetchIcons,
28906
30250
  prepareProps,
30251
+ renderAppearanceBootScript,
28907
30252
  renderBackground,
28908
30253
  renderBlock,
28909
30254
  renderBlocks,
@@ -28924,10 +30269,10 @@ react/cjs/react.development.js:
28924
30269
  * LICENSE file in the root directory of this source tree.
28925
30270
  *)
28926
30271
 
28927
- react/cjs/react-jsx-runtime.development.js:
30272
+ react-dom/cjs/react-dom.development.js:
28928
30273
  (**
28929
30274
  * @license React
28930
- * react-jsx-runtime.development.js
30275
+ * react-dom.development.js
28931
30276
  *
28932
30277
  * Copyright (c) Meta Platforms, Inc. and affiliates.
28933
30278
  *
@@ -28935,10 +30280,10 @@ react/cjs/react-jsx-runtime.development.js:
28935
30280
  * LICENSE file in the root directory of this source tree.
28936
30281
  *)
28937
30282
 
28938
- react-dom/cjs/react-dom.development.js:
30283
+ react/cjs/react-jsx-runtime.development.js:
28939
30284
  (**
28940
30285
  * @license React
28941
- * react-dom.development.js
30286
+ * react-jsx-runtime.development.js
28942
30287
  *
28943
30288
  * Copyright (c) Meta Platforms, Inc. and affiliates.
28944
30289
  *