@acms-subir/core 0.3.6 → 0.3.8

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.
Files changed (116) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/integration.mjs +38 -2
  3. package/package.json +1 -1
  4. package/src/actions/index.ts +146 -2
  5. package/src/components/EmailSettings.tsx +6 -0
  6. package/src/components/EventPage.astro +25 -5
  7. package/src/components/booking/DurationEditor.astro +156 -0
  8. package/src/components/calendar/BookingsHead.astro +4 -3
  9. package/src/components/calendar/RoomHolds.tsx +13 -8
  10. package/src/components/editor/EventPanel.tsx +9 -383
  11. package/src/components/editor/LivePane.tsx +16 -3
  12. package/src/components/editor/PostEditor.tsx +59 -46
  13. package/src/components/editor/PreviewOverlay.tsx +7 -1
  14. package/src/components/editor/event/EventSheet.tsx +136 -0
  15. package/src/components/editor/event/LocationField.tsx +266 -0
  16. package/src/components/editor/event/OrganizeCard.tsx +87 -0
  17. package/src/components/editor/event/RegistrationCard.tsx +114 -0
  18. package/src/components/editor/event/RegistrationFormEditor.tsx +142 -0
  19. package/src/components/editor/event/Section.tsx +27 -0
  20. package/src/components/editor/event/WhenCard.tsx +217 -0
  21. package/src/components/editor/event/dates.ts +28 -0
  22. package/src/components/editor/event/registration.ts +39 -0
  23. package/src/components/editor/extensions/form.tsx +60 -0
  24. package/src/components/editor/extensions/slash.tsx +5 -0
  25. package/src/components/editor/frameNav.ts +20 -0
  26. package/src/components/forms/Canvas.tsx +149 -0
  27. package/src/components/forms/FormBuildPage.tsx +155 -0
  28. package/src/components/forms/FormBuilder.tsx +283 -0
  29. package/src/components/forms/FormHeader.astro +31 -0
  30. package/src/components/forms/InsertMenu.tsx +77 -0
  31. package/src/components/forms/Inspector.tsx +232 -0
  32. package/src/components/forms/Outline.tsx +93 -0
  33. package/src/components/forms/ResponsesTable.tsx +123 -0
  34. package/src/components/forms/TypeIcon.tsx +24 -0
  35. package/src/components/forms/dnd.ts +3 -0
  36. package/src/components/forms/meta.ts +84 -0
  37. package/src/components/forms/useFormHistory.ts +41 -0
  38. package/src/layouts/Admin.astro +3 -2
  39. package/src/lib/backup/content.ts +10 -5
  40. package/src/lib/booking/forms.ts +67 -0
  41. package/src/lib/booking/service.ts +6 -2
  42. package/src/lib/calendar/agent-schema.ts +7 -1
  43. package/src/lib/calendar/agent.ts +28 -3
  44. package/src/lib/calendar/api.ts +2 -0
  45. package/src/lib/calendar/ics-write.ts +2 -0
  46. package/src/lib/calendar/ics.ts +4 -0
  47. package/src/lib/calendar/import.ts +3 -3
  48. package/src/lib/calendar/schedule.ts +6 -2
  49. package/src/lib/calendar/seo.ts +4 -1
  50. package/src/lib/content-service.ts +30 -4
  51. package/src/lib/drafts.ts +9 -1
  52. package/src/lib/dynamicBlocks.ts +14 -3
  53. package/src/lib/editor/documents.ts +12 -3
  54. package/src/lib/editor/schemas.ts +4 -3
  55. package/src/lib/email/readiness.ts +14 -0
  56. package/src/lib/email/service.ts +8 -3
  57. package/src/lib/email/templates.ts +8 -2
  58. package/src/lib/email/types.ts +1 -0
  59. package/src/lib/forms/events.ts +40 -0
  60. package/src/lib/forms/export.ts +62 -0
  61. package/src/lib/forms/fields.ts +50 -0
  62. package/src/lib/forms/http.ts +29 -0
  63. package/src/lib/forms/render.ts +11 -0
  64. package/src/lib/forms/schema.ts +56 -0
  65. package/src/lib/forms/service.ts +38 -0
  66. package/src/lib/forms/store.ts +78 -0
  67. package/src/lib/forms/validate.ts +71 -0
  68. package/src/lib/maps/config.ts +64 -0
  69. package/src/lib/maps/migration.ts +12 -0
  70. package/src/lib/maps/parse.ts +180 -0
  71. package/src/lib/maps/places.ts +109 -0
  72. package/src/lib/maps/providers/geoapify.ts +36 -0
  73. package/src/lib/maps/providers/google.ts +54 -0
  74. package/src/lib/maps/providers/http.ts +96 -0
  75. package/src/lib/maps/providers/index.ts +37 -0
  76. package/src/lib/maps/providers/locationiq.ts +35 -0
  77. package/src/lib/maps/providers/mapbox.ts +38 -0
  78. package/src/lib/maps/providers/osm.ts +59 -0
  79. package/src/lib/maps/providers/pelias.ts +51 -0
  80. package/src/lib/maps/service.ts +281 -0
  81. package/src/lib/maps/types.ts +35 -0
  82. package/src/lib/mobile/bookings.ts +1 -1
  83. package/src/lib/mobile/schemas.ts +2 -2
  84. package/src/lib/repo/migrations.ts +8 -0
  85. package/src/lib/repo/sql.ts +99 -10
  86. package/src/lib/repo/types.ts +21 -1
  87. package/src/lib/schema.ts +38 -0
  88. package/src/lib/umami.ts +8 -1
  89. package/src/pages/admin/calendar/bookings.astro +23 -12
  90. package/src/pages/admin/calendar/events/[id].astro +5 -2
  91. package/src/pages/admin/calendar/events/index.astro +3 -0
  92. package/src/pages/admin/calendar/resources/[id].astro +11 -0
  93. package/src/pages/admin/calendar/resources/link.astro +95 -49
  94. package/src/pages/admin/calendar/settings.astro +140 -3
  95. package/src/pages/admin/forms/[id]/share.astro +121 -0
  96. package/src/pages/admin/forms/[id]/submissions.astro +143 -0
  97. package/src/pages/admin/forms/[id].astro +27 -0
  98. package/src/pages/admin/forms/index.astro +198 -0
  99. package/src/pages/admin/integrations.astro +57 -0
  100. package/src/pages/admin/settings.astro +1 -1
  101. package/src/pages/api/agent/index.ts +1 -1
  102. package/src/pages/api/calendar/docs.ts +2 -0
  103. package/src/pages/api/calendar/events/[id].ts +1 -1
  104. package/src/pages/api/calendar/events/index.ts +1 -1
  105. package/src/pages/api/email/settings.ts +4 -2
  106. package/src/pages/api/mcp.ts +1 -1
  107. package/src/pages/book/manage/[token].astro +4 -4
  108. package/src/pages/events/[slug].astro +24 -10
  109. package/src/pages/forms/[id].astro +27 -0
  110. package/src/styles/admin.css +2 -2
  111. package/src/styles/editor.css +275 -34
  112. package/src/styles/form-block.css +38 -0
  113. package/src/styles/forms-admin.css +184 -0
  114. package/src/styles/forms.css +281 -0
  115. package/src/styles/site.css +43 -0
  116. package/src/virtual.d.ts +2 -0
@@ -1,4 +1,10 @@
1
1
  ---
2
+ import { ApiError } from '../../lib/api';
3
+ import { starter } from '../../lib/forms/schema';
4
+ import { formVersion } from '../../lib/forms/service';
5
+ import { renderFields, hiddenFields } from '../../lib/forms/render';
6
+ import { readForm, readAnswers, submissionGuard } from '../../lib/forms/http';
7
+ import { submitEventForm, prepareLegacyEventForm } from '../../lib/forms/events';
2
8
  import { requestLocale } from '../../lib/i18n';
3
9
  import { localizeDoc, isExtraLocale } from '../../lib/translations';
4
10
  import Site from '../../layouts/Site.astro';
@@ -14,7 +20,7 @@ import { CALENDAR, eventUrl } from '../../lib/calendar/config';
14
20
  import { eventIsPublic, featuredOccurrence } from '../../lib/calendar/events';
15
21
  import { eventJsonLd } from '../../lib/calendar/seo';
16
22
  import { upcomingEvents } from '../../lib/calendar/cards';
17
- import { createRsvp, seatsTaken, BookingError } from '../../lib/booking/service';
23
+ import { seatsTaken, BookingError } from '../../lib/booking/service';
18
24
  import { manageUrl } from '../../lib/calendar/config';
19
25
  import { waitUntilFrom } from '../../lib/webhooks';
20
26
 
@@ -40,21 +46,29 @@ if (!occurrence) return new Response(null, { status: 404, statusText: 'Not found
40
46
  const origin = siteOrigin(settings, Astro.url);
41
47
  // RSVP: "Save my seat" posts back here and lands on the manage page
42
48
  let rsvpError = '';
43
- if (Astro.request.method === 'POST' && event.rsvp.enabled && event.status === 'published') {
44
- const form = await Astro.request.formData();
49
+ let formValues: Record<string,string> = {};
50
+ let coreValues = { name: '', email: '', seats: '1' };
51
+ let requestId: string = crypto.randomUUID();
52
+ const definition = event.rsvp.form ?? starter('simple');
53
+ if (event.rsvp.enabled) Astro.response.headers.set('Cache-Control', 'private, no-store');
54
+ if (Astro.request.method === 'POST' && event.rsvp.enabled) {
45
55
  try {
46
- const b = await createRsvp(repo, {
47
- event, start: occurrence.start, end: occurrence.end, seats: Number(form.get('seats')) || 1,
48
- booker: { name: String(form.get('name') ?? ''), email: String(form.get('email') ?? '') },
49
- }, { origin, locals: Astro.locals, waitUntil: waitUntilFrom(Astro.locals) });
50
- return Astro.redirect(`${manageUrl(b.manageToken)}?new=1`);
56
+ if (!eventIsPublic(event, calMap)) throw new ApiError(404, 'Event not found.');
57
+ const form = await readForm(Astro.request);
58
+ await prepareLegacyEventForm(event, occurrence.start, form);
59
+ requestId = await submissionGuard(repo, form, Astro.clientAddress, `event:${event.id}`);
60
+ formValues = readAnswers(form, definition);
61
+ coreValues = { name: String(form.get('name') || '').slice(0,120), email: String(form.get('email') || '').slice(0,200), seats: String(form.get('seats') || '1') };
62
+ const booking = await submitEventForm(repo, event, occurrence, form, requestId, { origin, locals: Astro.locals, waitUntil: waitUntilFrom(Astro.locals) });
63
+ return Astro.redirect(`${manageUrl(booking.manageToken)}?new=1`, 303);
51
64
  } catch (err) {
52
- rsvpError = err instanceof BookingError ? err.message : 'Couldn’t save your RSVP. Please try again.';
65
+ rsvpError = err instanceof BookingError || err instanceof ApiError ? err.message : 'Couldn’t save your RSVP. Please try again.';
53
66
  }
54
67
  }
68
+ const formHtml = hiddenFields(await formVersion(definition), requestId) + `<input type="hidden" name="occurrence" value="${occurrence.start}">`;
55
69
  const taken = event.rsvp.enabled ? await seatsTaken(repo, event.id, occurrence.start) : 0;
56
70
  const rsvp = event.rsvp.enabled
57
- ? { going: taken, left: event.rsvp.capacity ? Math.max(0, event.rsvp.capacity - taken) : null, maxSeats: event.rsvp.maxSeats, error: rsvpError, open: occurrence.end > now && !event.cancelled }
71
+ ? { going: taken, left: event.rsvp.capacity ? Math.max(0, event.rsvp.capacity - taken) : null, maxSeats: event.rsvp.maxSeats, error: rsvpError, formHtml, fieldsHtml: renderFields(definition, formValues, 'event-registration'), values: coreValues, open: occurrence.end > now && !event.cancelled }
58
72
  : null;
59
73
  const calendars = event.calendarIds.map((id) => calMap.get(id)).filter((c): c is NonNullable<typeof c> => Boolean(c) && c!.visibility !== 'private');
60
74
  const html = highlightCodeHtml(await expandDynamicBlocks(event.bodyHtml, repo));
@@ -0,0 +1,27 @@
1
+ ---
2
+ import Site from '../../layouts/Site.astro';
3
+ import { getRepo } from '../../lib/repo';
4
+ import { renderForm } from '../../lib/forms/render';
5
+ import { collectResponse } from '../../lib/forms/service';
6
+ import { readForm, readAnswers, submissionGuard } from '../../lib/forms/http';
7
+ import { ApiError } from '../../lib/api';
8
+ const repo = await getRepo(Astro.locals);
9
+ const form = await repo.forms.get(Astro.params.id || '');
10
+ if (!form || form.status !== 'published' || form.kind !== 'form' || form.purpose !== 'general') return new Response(null, { status: 404 });
11
+ Astro.response.headers.set('Cache-Control', 'private, no-store');
12
+ const embed = Astro.url.searchParams.has('embed');
13
+ let error = '', success = false, values: Record<string,string> = {};
14
+ let requestId: string = crypto.randomUUID();
15
+ if (Astro.request.method === 'POST') {
16
+ try {
17
+ const data = await readForm(Astro.request);
18
+ requestId = await submissionGuard(repo, data, Astro.clientAddress, `form:${form.id}`);
19
+ values = readAnswers(data, form.definition);
20
+ const response = await collectResponse(form.definition, values, String(data.get('formVersion') || ''));
21
+ await repo.forms.submit(form.id, response, requestId);
22
+ success = true;
23
+ } catch (e) { error = e instanceof ApiError ? e.message : 'Could not save your response. Please try again.'; Astro.response.status = e instanceof ApiError ? e.status : 500; }
24
+ }
25
+ const html = success ? '' : await renderForm(form.id, form.definition, values, error, requestId, embed);
26
+ ---
27
+ <Site title={form.definition.title || form.name} noindex bare={embed}>{success ? <section class="pc-simple-form"><h1>{form.definition.title || form.name}</h1><p role="status">{form.definition.confirmation || 'Thank you. Your response has been received.'}</p><a href={Astro.url.pathname + (embed ? '?embed=1' : '')}>Send another response</a></section> : <div set:html={html}/>}</Site>
@@ -307,7 +307,7 @@ kbd {
307
307
  .tabbar .active svg { color: var(--accent); }
308
308
  /* comfortable touch targets */
309
309
  .btn { min-height: 36px; }
310
- input[type='text'], input[type='password'], input[type='email'], input[type='url'], input[type='number'], input[type='search'], input[type='datetime-local'], textarea, select { font-size: 16px; }
310
+ input:where(:not([type])), input[type='text'], input[type='password'], input[type='email'], input[type='url'], input[type='number'], input[type='search'], input[type='datetime-local'], textarea, select { font-size: 16px; }
311
311
  }
312
312
 
313
313
  /* cards & stats */
@@ -367,7 +367,7 @@ table.list { width: 100%; border-collapse: collapse; }
367
367
  .btn.sm { padding: 3px 9px; font-size: 12px; }
368
368
  .btn.ghost { background: transparent; border-color: transparent; color: var(--muted); box-shadow: none; }
369
369
  .btn.ghost:hover { color: var(--text); background: var(--hover); }
370
- input[type='text'], input[type='password'], input[type='email'], input[type='url'], input[type='number'], input[type='search'], input[type='datetime-local'], textarea, select {
370
+ input:where(:not([type])), input[type='text'], input[type='password'], input[type='email'], input[type='url'], input[type='number'], input[type='search'], input[type='datetime-local'], textarea, select {
371
371
  width: 100%; background: var(--panel); color: var(--text);
372
372
  border: 1px solid var(--line-strong); border-radius: var(--r-md);
373
373
  padding: 7px 11px; font-size: 13.5px; font-family: inherit;
@@ -12,6 +12,8 @@
12
12
  }
13
13
  .pe-topbar-left, .pe-topbar-right { display: flex; align-items: center; gap: 8px; min-width: 0; }
14
14
  .pe-topbar-right { justify-content: flex-end; }
15
+ /* a language switcher adds a fourth item: keep it next to the view switch */
16
+ .pe-topbar:has(> .pe-langs) { grid-template-columns: 1fr auto auto 1fr; }
15
17
  .pe-savestate { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
16
18
  .pe-save-dot { flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%; background: var(--green); transition: background-color 0.2s; }
17
19
  .pe-savestate.dirty .pe-save-dot, .pe-savestate.saving .pe-save-dot { background: var(--amber); }
@@ -824,6 +826,8 @@
824
826
  background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 2px 8px;
825
827
  }
826
828
  .pe-live-ago { flex: 1; font-size: 12px; color: var(--faint); white-space: nowrap; }
829
+ .pe-live-back { flex: none; }
830
+ .pe-live-away { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
827
831
  /* the site sits on its own card with a margin, so a light site never reads
828
832
  as a hole in a dark admin */
829
833
  .pe-split-stage { flex: 1; min-height: 0; display: flex; justify-content: center; background: var(--panel-2); padding: 10px; }
@@ -902,6 +906,7 @@
902
906
  .pe-prose { font-size: 16.5px; }
903
907
  .pe-shell.has-sidebar .pe-body { margin-right: 0; }
904
908
  .pe-topbar { grid-template-columns: auto 1fr auto; height: auto; }
909
+ .pe-topbar:has(> .pe-langs) { grid-template-columns: auto 1fr auto auto; gap: 6px; }
905
910
  .pe-modes { justify-self: center; background: none; }
906
911
  .pe-dock { display: none; }
907
912
  .pe-modes button { padding: 4px 8px; font-size: 0; gap: 0; }
@@ -996,23 +1001,6 @@
996
1001
  .pe-ev-skips { margin-bottom: 8px; }
997
1002
  .pe-ev-note { font-size: 12.5px; color: var(--muted); margin: 0; line-height: 1.5; }
998
1003
  .pe-ev-note a { color: var(--accent-deep); }
999
- .pe-ev-cals { display: flex; flex-direction: column; gap: 2px; }
1000
- .pe-ev-cals label { display: flex; align-items: center; gap: 9px; padding: 6px 8px; border-radius: var(--r-sm); cursor: pointer; font-size: 13px; color: var(--text-2); }
1001
- .pe-ev-cals label:hover { background: var(--hover); }
1002
- .pe-ev-cals label.is-on { background: var(--sel); color: var(--text); font-weight: 600; }
1003
- .pe-ev-cals input { accent-color: var(--accent); margin: 0; }
1004
- .pe-ev-cals i { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }
1005
- .pe-ev-byline { flex-wrap: wrap; }
1006
- .pe-ev-when {
1007
- display: inline-flex; align-items: center; gap: 6px; border: 0; background: var(--panel-2); color: var(--text);
1008
- border-radius: var(--r-full); padding: 3px 11px 3px 9px; font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer;
1009
- }
1010
- .pe-ev-when:hover { background: var(--sel); }
1011
- .pe-ev-when svg { width: 14px; height: 14px; color: var(--muted); }
1012
- .pe-ev-when.is-cancelled { text-decoration: line-through; color: var(--muted); }
1013
- .pe-ev-when.is-cancelled b { text-decoration: none; color: var(--red); }
1014
- .pe-ev-cal { display: inline-flex; align-items: center; gap: 6px; }
1015
- .pe-ev-cal i { width: 8px; height: 8px; border-radius: 50%; }
1016
1004
  .pe-field input.mono, .pe-ev input.mono { font-family: ui-monospace, 'SF Mono', monospace; font-size: 12px; }
1017
1005
 
1018
1006
  /* calendar card: site calendars; event card */
@@ -1046,23 +1034,7 @@
1046
1034
  .pe-seg button[aria-checked='true'] { background: var(--bg); color: var(--text); box-shadow: var(--shadow-sm); }
1047
1035
  :root[data-theme='dark'] .pe-seg button[aria-checked='true'] { background: #3a3632; }
1048
1036
 
1049
- /* Event settings → Rooms (components/calendar/RoomHolds.tsx) */
1050
- .rh-list { display: flex; flex-direction: column; gap: 6px; margin: 8px 0 10px; }
1051
- .rh-room { display: grid; grid-template-columns: 16px 1fr auto; gap: 9px; align-items: center; padding: 8px 10px; border: 1px solid var(--line); border-radius: 9px; background: var(--bg); cursor: pointer; }
1052
- .rh-room:hover { border-color: var(--line-strong); }
1053
- .rh-room.on { border-color: var(--accent-ring); background: var(--accent-soft); }
1054
- .rh-room input { accent-color: var(--accent); margin: 0; }
1055
- .rh-name { display: flex; flex-direction: column; min-width: 0; }
1056
- .rh-name b { font-size: 13px; font-weight: 550; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1057
- .rh-name small { font-size: 11.5px; color: var(--faint); }
1058
- .rh-st { font-size: 11.5px; white-space: nowrap; }
1059
- .rh-st.free { color: var(--green); }
1060
- .rh-st.busy { color: var(--amber); }
1061
- .rh-span { display: flex; gap: 1px; padding: 2px; border-radius: 9px; background: var(--sel); margin: 4px 0 8px; }
1062
- .rh-span button { flex: 1; border: 0; background: none; font: inherit; font-size: 12px; font-weight: 600; color: var(--muted); padding: 5px 8px; border-radius: 7px; cursor: pointer; }
1063
- .rh-span button[aria-pressed='true'] { background: var(--bg); color: var(--text); box-shadow: var(--shadow-sm); }
1064
- .rh-buffers { display: flex; flex-direction: column; gap: 6px; font-size: 12.5px; color: var(--text-2); margin-bottom: 6px; }
1065
- .rh-buffers input { width: 64px; margin: 0 4px; padding: 3px 6px; border: 1px solid var(--line-strong); border-radius: 7px; background: var(--bg); color: var(--text); font: inherit; }
1037
+ /* Event settings → Rooms: conflicts + publish dialog (components/calendar/RoomHolds.tsx; the table is with the settings column) */
1066
1038
  .rh-conflict { margin: 10px 0 4px; padding: 10px 12px; border-radius: 10px; background: var(--amber-soft); font-size: 12.5px; color: var(--text); }
1067
1039
  .rh-conflict > b { display: block; margin-bottom: 4px; }
1068
1040
  .rh-bk { display: flex; flex-direction: column; padding: 5px 0; border-top: 1px solid color-mix(in srgb, var(--amber) 25%, transparent); }
@@ -1081,3 +1053,272 @@
1081
1053
  .rh-row small { color: var(--muted); font-size: 11.5px; }
1082
1054
  .rh-row select { padding: 4px 8px; border: 1px solid var(--line-strong); border-radius: 7px; background: var(--panel); color: var(--text); font: inherit; font-size: 12.5px; }
1083
1055
  @media (max-width: 640px) { .rh-layer { place-items: end stretch; padding: 0; } .rh-dialog { border-radius: 16px 16px 0 0; } .rh-row { grid-template-columns: 1fr; } }
1056
+
1057
+ /* event settings column — every event setting on the page, above the event's
1058
+ own content. Index · summary · section rows (title + help | controls).
1059
+ Sized by the editor pane (container query), not the window: under 1080px
1060
+ the index becomes a jump bar, under 760px labels stack over controls. */
1061
+ .pe-editor-pane { container: pane / inline-size; }
1062
+ .pe-evs-wrap { --evs-pad: 24px; max-width: 1180px; margin: 0 auto; padding: 28px var(--evs-pad) 0; }
1063
+ .pe-shell.has-split .pe-evs-wrap { --evs-pad: 28px; }
1064
+ .pe-evs { display: grid; grid-template-columns: 164px minmax(0, 1fr); gap: 0 40px; align-items: start; }
1065
+ .pe-evs-col { min-width: 0; }
1066
+ .pe-evs-divider { display: flex; align-items: center; gap: 12px; margin: 0 0 28px; font-size: 11px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: var(--faint); scroll-margin-top: 16px; }
1067
+ .pe-evs-divider::after { content: ''; flex: 1; height: 1px; background: var(--line); }
1068
+ .pe-column.pe-ev-column { padding-top: 36px; }
1069
+
1070
+ .pe-evs-index { position: sticky; top: 20px; z-index: 6; display: flex; flex-direction: column; gap: 2px; padding-top: 2px; }
1071
+ .pe-evs-index button {
1072
+ display: flex; flex-direction: column; gap: 1px; min-width: 0; padding: 7px 10px; border: 0; border-radius: var(--r-sm);
1073
+ background: none; font: inherit; text-align: left; cursor: pointer;
1074
+ }
1075
+ .pe-evs-index button:hover { background: var(--hover); }
1076
+ .pe-evs-index button.is-current { background: var(--sel); }
1077
+ .pe-evs-index button:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-ring); }
1078
+ .pe-evs-index b { font-size: 13px; font-weight: 600; color: var(--text-2); }
1079
+ .pe-evs-index .is-current b { color: var(--text); }
1080
+ .pe-evs-index small { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1081
+ .pe-evs-index small.is-cancelled { color: var(--red); }
1082
+ .pe-evs-index .pe-evs-index-page { margin-top: 10px; font-size: 12.5px; font-weight: 600; color: var(--accent-deep); }
1083
+
1084
+ .pe-evs-sum { display: flex; flex-direction: column; gap: 3px; margin: 0; padding: 2px 0 22px; border-bottom: 1px solid var(--line); }
1085
+ .pe-evs-sum b { font-size: 17px; font-weight: 650; letter-spacing: -0.01em; color: var(--text); }
1086
+ .pe-evs-sum span { font-size: 13.5px; color: var(--text-2); line-height: 1.45; }
1087
+ .pe-evs-sum.is-cancelled span { color: var(--muted); }
1088
+ .pe-evs-sum em { font-style: normal; font-weight: 600; color: var(--red); }
1089
+
1090
+ .pe-evsec { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 0 32px; padding: 26px 0; border-bottom: 1px solid var(--line); scroll-margin-top: 16px; border-radius: 2px; }
1091
+ .pe-evsec.is-flash { animation: pe-evsec-flash 1.4s ease-out; }
1092
+ @keyframes pe-evsec-flash { from { background: var(--accent-soft); } to { background: transparent; } }
1093
+ .pe-evsec-h h3 { margin: 0; font-size: 14.5px; font-weight: 600; color: var(--text); }
1094
+ .pe-evsec-h p { margin: 4px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--muted); }
1095
+ .pe-evsec-h a, .pe-evs-hint a, .pe-evs-link { color: var(--accent-deep); font-weight: 600; text-decoration: none; }
1096
+ .pe-evsec-h a:hover, .pe-evs-hint a:hover, .pe-evs-link:hover { text-decoration: underline; }
1097
+ .pe-evsec-b { min-width: 0; max-width: 640px; container: evsec / inline-size; }
1098
+ #ev-when .pe-evsec-b { max-width: 940px; }
1099
+
1100
+ /* primitives: 36px controls, 18px between fields, labels above inputs */
1101
+ .pe-evs-fields { display: flex; flex-direction: column; gap: 18px; }
1102
+ .pe-evs-fields .pe-field { margin: 0; }
1103
+ .pe-evs-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
1104
+ .pe-evs-hint { display: block; margin: 5px 0 0; font-size: 12px; line-height: 1.45; color: var(--muted); }
1105
+ .pe-evs-hint.is-error { color: var(--red); }
1106
+ .pe-field.is-invalid input { border-color: var(--red); }
1107
+ .pe-field.is-invalid input:focus { box-shadow: 0 0 0 3px var(--red-soft); }
1108
+ .pe-evs-box { border: 1px solid var(--line); border-radius: var(--r-md); background: var(--panel); padding: 0 14px; }
1109
+ .pe-evs-box .pe-switch-row { align-items: center; padding: 11px 0; }
1110
+ .pe-evs-box .pe-switch-row + .pe-switch-row { border-top: 1px solid var(--line); }
1111
+ .pe-evsec input:where(:not([type='checkbox'], [type='radio'])), .pe-evsec select {
1112
+ height: 36px; min-width: 0; background: var(--panel); color: var(--text); border: 1px solid var(--line-strong);
1113
+ border-radius: var(--r-md); padding: 0 10px; font: inherit; font-size: 13.5px;
1114
+ }
1115
+ .pe-evsec textarea { background: var(--panel); border-color: var(--line-strong); font-size: 13.5px; }
1116
+ .pe-evsec input:focus, .pe-evsec select:focus, .pe-evsec textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring); }
1117
+ .pe-evsec input[type='date'] { min-width: 150px; }
1118
+ .pe-evsec input[type='time'] { min-width: 112px; }
1119
+ .pe-evsec input.mono { font-size: 12.5px; }
1120
+ .pe-evsec .pe-tags { min-height: 36px; padding: 4px 8px; background: var(--panel); border-color: var(--line-strong); }
1121
+ .pe-evsec .pe-tags input { height: 26px; }
1122
+ :root[data-theme='dark'] .pe-evsec input { color-scheme: dark; }
1123
+ .pe-evc-note { margin: 0 0 12px; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
1124
+
1125
+ /* When: key column + date + time, mini month at the side when there's room */
1126
+ .pe-evw { display: grid; grid-template-columns: minmax(0, 1fr); gap: 22px 36px; align-items: start; }
1127
+ @container evsec (min-width: 680px) { .pe-evw.has-lands { grid-template-columns: minmax(0, 1fr) 272px; } }
1128
+ .pe-evw-main { --evw-key: 56px; display: flex; flex-direction: column; gap: 18px; min-width: 0; max-width: 560px; }
1129
+ .pe-evw-times { display: grid; grid-template-columns: var(--evw-key) minmax(150px, 1fr) minmax(112px, 132px); gap: 10px; align-items: center; }
1130
+ .pe-evw-times.is-allday { grid-template-columns: var(--evw-key) minmax(150px, 240px); }
1131
+ .pe-evw-key { font-size: 13px; font-weight: 500; color: var(--text-2); }
1132
+ .pe-evw-opts { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 26px; margin-top: -4px; padding-left: calc(var(--evw-key) + 10px); min-height: 32px; }
1133
+ .pe-evw-allday { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 500; color: var(--text); cursor: pointer; }
1134
+ .pe-evw-allday .pe-switch { margin: 0; }
1135
+ .pe-evw-tz { display: inline-flex; align-items: center; gap: 6px; min-width: 0; font-size: 13px; color: var(--text-2); }
1136
+ .pe-evw-tz svg { width: 14px; height: 14px; flex: none; color: var(--muted); }
1137
+ .pe-evw-tz em { font-style: normal; color: var(--muted); }
1138
+ .pe-evsec .pe-evw-tz input { width: 220px; height: 32px; }
1139
+ .pe-evw-link { border: 0; background: none; padding: 2px 0; font: inherit; font-size: 12.5px; font-weight: 600; color: var(--accent-deep); cursor: pointer; }
1140
+ .pe-evw-link:hover { text-decoration: underline; }
1141
+ .pe-evw-sub { display: block; font-size: 12px; font-weight: 500; color: var(--muted); margin-bottom: 6px; }
1142
+ .pe-evw-sentence { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
1143
+ .pe-evw-word { font-size: 13px; color: var(--text-2); }
1144
+ .pe-evw-sentence select, .pe-evw-sentence input { width: auto; flex: none; }
1145
+ .pe-evsec .pe-evw-num { width: 64px; }
1146
+ .pe-evs-group { min-width: 0; }
1147
+ .pe-evw-sum { margin: 7px 0 0; font-size: 12.5px; color: var(--muted); }
1148
+ .pe-evw-repeat .pe-ev-days, .pe-evw-repeat .pe-ev-choices, .pe-evw-repeat .pe-field { margin: 12px 0 0; }
1149
+ .pe-evw-skips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin-top: 14px; }
1150
+ .pe-evw-skip { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 4px 0 9px; border: 1px solid var(--line-strong); border-radius: var(--r-sm); background: var(--panel); font-size: 12.5px; color: var(--text); }
1151
+ .pe-evw-skip button { width: 20px; height: 20px; border: 0; border-radius: 6px; background: none; color: var(--muted); font-size: 10px; cursor: pointer; }
1152
+ .pe-evw-skip button:hover { background: var(--hover); color: var(--text); }
1153
+ .pe-evw-skipadd { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; }
1154
+ .pe-evsec .pe-evw-skipadd input { width: 170px; height: 32px; }
1155
+ .pe-evw .lands { margin: 0; max-width: 360px; }
1156
+
1157
+ /* Registration: three large choices, then the mode's fields */
1158
+ .pe-evr-modes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
1159
+ .pe-evr-modes button {
1160
+ display: flex; flex-direction: column; align-items: flex-start; gap: 3px; min-width: 0; padding: 12px 14px;
1161
+ border: 1px solid var(--line-strong); border-radius: var(--r-md); background: var(--panel); font: inherit; text-align: left; cursor: pointer;
1162
+ }
1163
+ .pe-evr-modes button:hover { border-color: var(--faint); }
1164
+ .pe-evr-modes button[aria-checked='true'] { background: var(--sel); border-color: var(--muted); }
1165
+ .pe-evr-modes button:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-ring); }
1166
+ .pe-evr-modes b { font-size: 13.5px; font-weight: 600; color: var(--text); }
1167
+ .pe-evr-modes small { font-size: 12px; color: var(--muted); }
1168
+ .pe-evr-modes + .pe-evs-fields { margin-top: 22px; }
1169
+ .pe-evr-link { grid-template-columns: minmax(0, 1fr) 150px; }
1170
+ .pe-evr-seats { grid-template-columns: repeat(2, minmax(0, 200px)); }
1171
+ .pe-evr-form { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--panel); }
1172
+ .pe-evr-form-t { flex: 1 1 240px; min-width: 0; }
1173
+ .pe-evr-form-t b { display: block; font-size: 13.5px; font-weight: 600; color: var(--text); }
1174
+ .pe-evr-form-t small { display: block; margin-top: 2px; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
1175
+ .pe-evr-form-a { display: flex; align-items: center; gap: 16px; }
1176
+ .pe-evs-link { font-size: 12.5px; white-space: nowrap; }
1177
+ /* registration form: the full forms builder over the event editor */
1178
+ html.pe-evr-lock { overflow: hidden; }
1179
+ .pe-evr-overlay { position: fixed; inset: 0; width: 100vw; height: 100dvh; max-width: none; max-height: none; margin: 0; padding: 0; border: 0; background: var(--bg); color: var(--text); display: flex; flex-direction: column; }
1180
+ .pe-evr-overlay::backdrop { background: var(--dim); }
1181
+ .pe-evr-bar { display: flex; align-items: center; gap: 12px 16px; padding: 10px 20px; border-bottom: 1px solid var(--line); flex-wrap: wrap; }
1182
+ .pe-evr-crumb { font-size: 13px; color: var(--muted); min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
1183
+ .pe-evr-crumb b { color: var(--text); font-weight: 600; }
1184
+ .pe-evr-hint { font-size: 12.5px; color: var(--faint); margin-left: auto; }
1185
+ .pe-evr-acts { display: flex; align-items: center; gap: 8px; }
1186
+ .pe-evr-pop { position: relative; }
1187
+ .pe-evr-menu { position: absolute; top: calc(100% + 6px); right: 0; z-index: 20; width: 300px; padding: 6px; background: var(--panel); border: 1px solid var(--line-strong); border-radius: var(--r-lg); box-shadow: var(--shadow-pop); display: grid; gap: 1px; }
1188
+ .pe-evr-menu > button, .pe-evr-menu > a { display: grid; gap: 1px; text-align: left; padding: 8px 10px; border: 0; border-radius: var(--r-sm); background: none; color: var(--text); font: inherit; cursor: pointer; text-decoration: none; }
1189
+ .pe-evr-menu > button:hover, .pe-evr-menu > a:hover, .pe-evr-menu > button:focus-visible { background: var(--sel); outline: none; }
1190
+ .pe-evr-menu b { font-size: 13px; font-weight: 600; }
1191
+ .pe-evr-menu small { font-size: 12px; color: var(--muted); }
1192
+ .pe-evr-menu-h { font-size: 10.5px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: var(--faint); padding: 8px 10px 3px; }
1193
+ .pe-evr-menu-empty { margin: 0; padding: 4px 10px 8px; font-size: 12.5px; color: var(--muted); }
1194
+ .pe-evr-confirm { padding: 10px; display: grid; gap: 6px; }
1195
+ .pe-evr-confirm b { font-size: 13.5px; }
1196
+ .pe-evr-confirm p { margin: 0; font-size: 12.5px; color: var(--text-2); line-height: 1.5; }
1197
+ .pe-evr-confirm div { display: flex; justify-content: flex-end; gap: 8px; margin-top: 4px; }
1198
+ .pe-evr-save { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px; padding: 12px 20px; border-bottom: 1px solid var(--line); background: var(--panel-2); }
1199
+ .pe-evr-save .pe-field { flex: 0 1 320px; margin: 0; }
1200
+ .pe-evr-save .pe-btn { height: 36px; }
1201
+ .pe-evr-save p { flex-basis: 100%; margin: 0; font-size: 12.5px; color: var(--muted); }
1202
+ .pe-evr-save p:empty { display: none; }
1203
+ .pe-evr-undo { display: flex; align-items: center; gap: 10px; padding: 8px 20px; border-bottom: 1px solid var(--line); background: var(--panel-2); font-size: 13px; color: var(--text-2); }
1204
+ .pe-evr-undo span { margin-right: auto; }
1205
+ .pe-evr-body { flex: 1; min-height: 0; overflow: auto; padding: 20px; }
1206
+ @media (max-width: 760px) {
1207
+ .pe-evr-bar { padding: 10px 14px; }
1208
+ .pe-evr-hint { display: none; }
1209
+ .pe-evr-acts { margin-left: auto; }
1210
+ .pe-evr-menu { width: min(300px, calc(100vw - 28px)); }
1211
+ .pe-evr-body { padding: 12px; }
1212
+ }
1213
+
1214
+ /* Organize: calendars as a grid of checkable rows */
1215
+ .pe-ev-cals { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 4px 6px; }
1216
+ .pe-ev-cals label { display: flex; align-items: center; gap: 9px; min-width: 0; height: 36px; padding: 0 10px; border-radius: var(--r-sm); cursor: pointer; font-size: 13px; color: var(--text-2); }
1217
+ .pe-ev-cals label:hover { background: var(--hover); }
1218
+ .pe-ev-cals label.is-on { background: var(--sel); color: var(--text); font-weight: 600; }
1219
+ .pe-ev-cals input { accent-color: var(--accent); margin: 0; flex: none; }
1220
+ .pe-ev-cals i { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }
1221
+ .pe-ev-cals span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1222
+
1223
+ /* Status: the switch row tints when cancelled */
1224
+ .pe-evsec.is-cancelled .pe-evs-cancel { background: var(--red-soft); border-color: transparent; }
1225
+ .pe-evsec.is-cancelled .pe-evs-cancel b { color: var(--red); }
1226
+
1227
+ /* Where: room / people holds as a checklist table */
1228
+ .rh { container: rh / inline-size; margin-top: 26px; }
1229
+ .rh-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; margin-bottom: 8px; }
1230
+ .rh-head b { font-size: 13px; font-weight: 600; color: var(--text); }
1231
+ .rh-head small { font-size: 12px; color: var(--muted); }
1232
+ .rh-table { border: 1px solid var(--line); border-radius: var(--r-md); background: var(--panel); overflow: hidden; }
1233
+ .rh-tr { display: grid; grid-template-columns: 16px minmax(0, 1fr) 76px minmax(96px, auto); gap: 12px; align-items: center; min-height: 40px; padding: 4px 14px; }
1234
+ .rh-th { min-height: 32px; font-size: 11.5px; font-weight: 500; color: var(--muted); background: var(--panel-2); border-bottom: 1px solid var(--line); }
1235
+ .rh-room { cursor: pointer; }
1236
+ .rh-room + .rh-room { border-top: 1px solid var(--line); }
1237
+ .rh-room:hover { background: var(--hover); }
1238
+ .rh-room.on { background: var(--sel); }
1239
+ .rh-room input { accent-color: var(--accent); margin: 0; }
1240
+ .rh-name { display: flex; align-items: baseline; gap: 6px; min-width: 0; }
1241
+ .rh-name b { font-size: 13px; font-weight: 550; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1242
+ .rh-room.on .rh-name b { font-weight: 600; }
1243
+ .rh-name small { flex: none; font-size: 12px; color: var(--muted); }
1244
+ .rh-cap { font-size: 12.5px; color: var(--text-2); font-variant-numeric: tabular-nums; }
1245
+ .rh-st { font-size: 12.5px; white-space: nowrap; }
1246
+ .rh-st.free { color: var(--green); }
1247
+ .rh-st.busy { color: var(--amber); }
1248
+ @container rh (max-width: 400px) {
1249
+ .rh-tr { grid-template-columns: 16px minmax(0, 1fr) auto; }
1250
+ .rh-tr > :nth-child(3) { display: none; }
1251
+ }
1252
+ .rh-span { display: flex; gap: 1px; max-width: 360px; padding: 2px; border-radius: 9px; background: var(--sel); margin: 12px 0 10px; }
1253
+ .rh-span button { flex: 1; border: 0; background: none; font: inherit; font-size: 12.5px; font-weight: 600; color: var(--muted); padding: 6px 8px; border-radius: 7px; cursor: pointer; }
1254
+ .rh-span button[aria-pressed='true'] { background: var(--panel); color: var(--text); box-shadow: var(--shadow-sm); }
1255
+ .rh-buffers { display: flex; flex-wrap: wrap; gap: 8px 22px; font-size: 13px; color: var(--text-2); margin-bottom: 8px; }
1256
+ .rh-buffers label { display: inline-flex; align-items: center; gap: 6px; }
1257
+ .pe-evsec .rh-buffers input { width: 72px; }
1258
+
1259
+ /* location search: saved places + provider suggestions + pasted links */
1260
+ .pe-loc-search { position: relative; }
1261
+ .pe-loc-search > svg { position: absolute; left: 10px; top: 11px; width: 14px; height: 14px; color: var(--faint); pointer-events: none; }
1262
+ .pe-loc-search input { width: 100%; padding-left: 30px; padding-right: 30px; }
1263
+ .pe-loc-spin { position: absolute; right: 10px; top: 11px; width: 14px; height: 14px; border: 2px solid var(--line-strong); border-top-color: var(--accent); border-radius: 50%; animation: pe-loc-spin 0.7s linear infinite; }
1264
+ @keyframes pe-loc-spin { to { transform: rotate(360deg); } }
1265
+ .pe-loc-list {
1266
+ position: absolute; z-index: 30; left: 0; right: 0; top: calc(100% + 4px); margin: 0; padding: 4px; list-style: none;
1267
+ background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-md); box-shadow: var(--shadow-pop); max-height: 320px; overflow-y: auto;
1268
+ }
1269
+ .pe-loc-group { display: block; padding: 8px 8px 4px; font-size: 10.5px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: var(--faint); }
1270
+ .pe-loc-opt { display: grid; grid-template-columns: 24px minmax(0, 1fr) auto; gap: 9px; align-items: center; padding: 7px 8px; border-radius: 8px; cursor: pointer; font-size: 13px; }
1271
+ .pe-loc-opt.is-active { background: var(--accent-soft); }
1272
+ .pe-loc-opt b { display: block; font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1273
+ .pe-loc-opt small { display: block; font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1274
+ .pe-loc-opt em { font-style: normal; font-size: 11px; font-weight: 600; color: var(--faint); }
1275
+ .pe-loc-mk { width: 24px; height: 24px; display: grid; place-items: center; border-radius: 7px; background: var(--panel-2); color: var(--accent-deep); font-size: 12px; }
1276
+ .pe-loc-empty, .pe-loc-foot { padding: 9px 8px; font-size: 12.5px; color: var(--muted); }
1277
+ .pe-loc-foot { border-top: 1px solid var(--line); margin-top: 4px; }
1278
+ .pe-loc-foot a { color: var(--accent-deep); font-weight: 600; }
1279
+ .pe-loc-msg { margin: -8px 0 0; font-size: 12.5px; color: var(--muted); }
1280
+
1281
+ .pe-loc-map { margin: 0; }
1282
+ .pe-loc-img { display: block; width: 100%; aspect-ratio: 12 / 5; object-fit: cover; border-radius: 9px; border: 1px solid var(--line); background: var(--panel-2); }
1283
+ .pe-loc-img.is-dark { display: none; }
1284
+ :root[data-theme='dark'] .pe-loc-img.is-light { display: none; }
1285
+ :root[data-theme='dark'] .pe-loc-img.is-dark { display: block; }
1286
+ .pe-loc-noimg { display: flex; align-items: center; gap: 10px; padding: 12px; border-radius: 9px; background: var(--panel-2); font-size: 12px; line-height: 1.4; color: var(--muted); }
1287
+ .pe-loc-noimg a { color: var(--accent-deep); font-weight: 600; }
1288
+ .pe-loc-pin { flex: none; width: 14px; height: 14px; background: var(--accent); border: 2px solid var(--panel); border-radius: 50% 50% 50% 0; transform: rotate(-45deg); box-shadow: 0 1px 3px rgb(0 0 0 / 25%); }
1289
+ .pe-loc-check { margin-top: 8px; display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--text-2); cursor: pointer; }
1290
+ .pe-loc-check input { accent-color: var(--accent); margin: 0; }
1291
+ .pe-loc-actions { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
1292
+ .pe-loc-gap { flex: 1; }
1293
+ @container pane (max-width: 1079px) {
1294
+ .pe-evs { grid-template-columns: minmax(0, 1fr); }
1295
+ .pe-evs-index {
1296
+ top: 0; flex-direction: row; gap: 2px; margin: 0 calc(-1 * var(--evs-pad)) 18px; padding: 6px var(--evs-pad);
1297
+ overflow-x: auto; scrollbar-width: none; background: var(--bg); border-bottom: 1px solid var(--line);
1298
+ }
1299
+ .pe-evs-index button { flex: none; flex-direction: row; align-items: baseline; gap: 6px; padding: 6px 10px; }
1300
+ .pe-evs-index small { max-width: 140px; }
1301
+ .pe-evs-index .pe-evs-index-page { margin: 0 0 0 auto; }
1302
+ .pe-evsec { grid-template-columns: 170px minmax(0, 1fr); gap: 0 26px; scroll-margin-top: 60px; }
1303
+ }
1304
+ @container pane (max-width: 759px) {
1305
+ .pe-evs-index small { display: none; }
1306
+ .pe-evsec { grid-template-columns: minmax(0, 1fr); padding: 22px 0; }
1307
+ .pe-evsec-h { margin-bottom: 16px; }
1308
+ }
1309
+ @container evsec (max-width: 440px) {
1310
+ .pe-evs-pair:not(.pe-evr-seats) { grid-template-columns: minmax(0, 1fr); }
1311
+ .pe-evr-modes { grid-template-columns: minmax(0, 1fr); gap: 6px; }
1312
+ .pe-evr-modes button { flex-direction: row; align-items: baseline; justify-content: space-between; padding: 10px 12px; }
1313
+ .pe-evw-opts { padding-left: 0; }
1314
+ }
1315
+ @container evsec (max-width: 520px) { .pe-ev-cals { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
1316
+ @container evsec (max-width: 360px) {
1317
+ .pe-evw-main { --evw-key: 44px; }
1318
+ .pe-evw-times { grid-template-columns: var(--evw-key) minmax(0, 1fr) minmax(104px, 112px); gap: 8px; }
1319
+ .pe-evsec .pe-evw-times input[type='date'] { min-width: 0; }
1320
+ }
1321
+ @media (max-width: 900px) {
1322
+ .pe-evs-wrap { --evs-pad: 14px; padding-top: 18px; }
1323
+ .pe-evsec input:where(:not([type='checkbox'], [type='radio'])), .pe-evsec select, .pe-evsec textarea, .pe-loc-search input, .pe-evsec input.mono { font-size: 16px; }
1324
+ }
@@ -0,0 +1,38 @@
1
+ /* Post editor → Form block: a config bar plus a static, disabled render of
2
+ the chosen form (public field markup from renderFields, admin tokens). */
3
+ .pfb-card { background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-md); padding: 10px 12px 14px; }
4
+ .pfb-card.is-selected { box-shadow: 0 0 0 2px var(--accent); }
5
+ .pfb-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; padding-right: 40px; margin-bottom: 12px; font-size: 12.5px; }
6
+ .pfb-kind { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.07em; color: var(--muted); }
7
+ .pfb-bar select { width: auto; min-width: 180px; max-width: 100%; padding: 5px 9px; font-size: 13px; border: 1px solid var(--line-strong); border-radius: var(--r-sm); background: var(--bg); color: var(--text); font-family: inherit; }
8
+ .pfb-st { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; font-size: 12px; }
9
+ .pfb-st i { width: 7px; height: 7px; border-radius: 2px; background: currentColor; flex: 0 0 auto; }
10
+ .pfb-st.is-live { color: var(--green); }
11
+ .pfb-st.is-hidden { color: var(--amber); }
12
+ .pfb-link { margin-left: auto; font-size: 12.5px; color: var(--accent-deep); white-space: nowrap; }
13
+ .pfb-stage { background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 18px 20px; }
14
+ .pfb-note { margin: 0; color: var(--muted); font-size: 13px; }
15
+ .pfb-preview { border: 0; margin: 0 auto; padding: 0; min-width: 0; max-width: 560px; display: grid; gap: 12px; pointer-events: none; user-select: none; font-size: 14px; color: var(--text); }
16
+ .pfb-preview h3 { margin: 0; font-size: 18px; letter-spacing: -0.01em; }
17
+ .pfb-intro { margin: -4px 0 0; color: var(--text-2); }
18
+ .pfb-fields { display: grid; gap: 12px; grid-template-columns: 1fr 1fr; }
19
+ .pfb-fields > * { grid-column: 1 / -1; min-width: 0; margin: 0; }
20
+ .pfb-fields > [data-width='half'], .pfb-fields > .is-half { grid-column: auto; }
21
+ .pfb-fields .pc-bk-field, .pfb-fields fieldset { display: grid; gap: 5px; border: 0; padding: 0; margin: 0; }
22
+ .pfb-fields .pc-bk-field > span, .pfb-fields legend { font-size: 13px; font-weight: 600; padding: 0; }
23
+ .pfb-fields input:not([type='checkbox']):not([type='radio']), .pfb-fields select, .pfb-fields textarea {
24
+ width: 100%; padding: 8px 10px; border: 1px solid var(--line-strong); border-radius: var(--r-sm);
25
+ background: var(--panel); color: var(--text); font: inherit; font-size: 13.5px; opacity: 1;
26
+ }
27
+ .pfb-fields textarea { resize: none; }
28
+ .pfb-fields small { display: block; color: var(--muted); font-size: 12px; }
29
+ .pfb-fields .pc-bk-check, .pfb-fields label:has(> input[type='radio']), .pfb-fields label:has(> input[type='checkbox']) { display: flex; gap: 8px; align-items: flex-start; font-size: 13.5px; }
30
+ .pfb-fields input[type='checkbox'], .pfb-fields input[type='radio'] { margin: 3px 0 0; accent-color: var(--accent); opacity: 1; }
31
+ .pfb-fields .pc-form-trap { display: none; }
32
+ .pfb-submit { justify-self: start; padding: 9px 18px; border-radius: var(--r-md); background: var(--text); color: var(--bg); font-weight: 600; font-size: 13.5px; }
33
+ @media (max-width: 600px) {
34
+ .pfb-fields { grid-template-columns: 1fr; }
35
+ .pfb-fields > [data-width='half'], .pfb-fields > .is-half { grid-column: 1 / -1; }
36
+ .pfb-link { margin-left: 0; }
37
+ .pfb-stage { padding: 14px; }
38
+ }