/* The app's own CSS, beside the utilities Tailwind builds from the classes
   in the templates (/_tailwind.css, which the layout links before this
   file). Tokens are in app/theme.css, read here as var(--color-page).

   Three parts:
   - base: what every element starts from;
   - components: the parts' looks (btn, card, input, type-h3, app-btn, …),
     which a utility on the same element overrides (class="btn px-8");
   - no layer: rules that follow an attribute a script or the server sets
     ([data-cat], [data-framed], [data-rows]); they win over a utility.
   /design shows every part. */

@layer base {
  /* The browser's own margins, paddings and borders stay unless listed
     below, as the pages were drawn: a dialog's, a table cell's, a field's.
     Tailwind's base styles clear them all; revert-layer takes each back to
     what it was before this layer. */
  *, ::after, ::before, ::backdrop, ::file-selector-button {
    margin: revert-layer;
    padding: revert-layer;
    border: revert-layer;
  }
  body, h1, h2, h3, h4, h5, h6, hr, figure, p, pre { margin: 0; }
  p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }
  ul, ol { list-style: none; padding: 0; margin: 0; }
  dd { margin: 0; }
  fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
  legend { padding: 0; }
  button, [type='button'], [type='reset'], [type='submit'] {
    appearance: none;
    background-color: transparent;
    background-image: none;
    border: 0;
    padding: 0;
    cursor: pointer;
  }
  /* Also the browser's: a heading's size and weight, a rule, a table's
     borders, a field's background, corners and placeholder. */
  h1, h2, h3, h4, h5, h6 { font-size: revert-layer; font-weight: revert-layer; }
  hr { height: revert-layer; color: revert-layer; }
  table { border-collapse: revert-layer; border-color: revert-layer; text-indent: revert-layer; }
  input, select, textarea, optgroup { border-radius: revert-layer; background-color: revert-layer; letter-spacing: revert-layer; }
  ::placeholder { color: revert-layer; opacity: revert-layer; }
  textarea { resize: revert-layer; }
  small { font-size: revert-layer; }
  code, kbd, samp, pre { font-family: revert-layer; font-size: revert-layer; }
  /* A date or time field's inner parts keep the browser's spacing. */
  ::-webkit-datetime-edit { display: revert-layer; }
  ::-webkit-datetime-edit, ::-webkit-datetime-edit-fields-wrapper, ::-webkit-datetime-edit-year-field,
  ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field,
  ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field,
  ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {
    padding: revert-layer;
    padding-block: revert-layer;
  }
  ::-webkit-date-and-time-value { min-height: revert-layer; text-align: revert-layer; }
  ::-webkit-calendar-picker-indicator { line-height: revert-layer; }
  /* An image keeps the height its attribute gives. */
  img, video { height: revert-layer; }
  svg, canvas, picture { max-width: 100%; }

  /* Links take the colour of the text around them; pages underline them
     where needed. */
  a { color: inherit; text-decoration: none; }

  /* Nothing moves for a visitor who asked for less motion. */
  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.01ms !important;
      scroll-behavior: auto !important;
    }
  }
}

@layer components {
  /* Type styles. h1–h5, label, overline and caption are the editorial site's
     (serif headings, mono labels); title, subtitle and figure are the work
     area's (organizer, admin, editor): page title, section title, and a
     number in a summary card, in the same serif as the public pages. With
     type-title, type-subtitle, type-figure, type-h1, type-h2, type-h3,
     type-h4, type-h5, type-label, type-overline, type-caption. */
  .type {
    margin: 0;
  }
  .type-title {
    font-family: var(--font-serif);
    font-size: var(--text-h3);
    font-weight: 500;
  }
  .type-subtitle {
    font-family: var(--font-serif);
    font-size: var(--text-h5);
    font-weight: 500;
  }
  .type-figure {
    font-family: var(--font-serif);
    font-size: var(--text-h4);
    font-weight: 400;
  }
  .type-h1 {
    font-family: var(--font-serif);
    font-size: var(--text-h1);
    font-weight: 500;
  }
  .type-h2 {
    font-family: var(--font-serif);
    font-size: var(--text-h2);
    font-weight: 500;
  }
  .type-h3 {
    font-family: var(--font-serif);
    font-size: var(--text-h3);
    font-weight: 500;
  }
  .type-h4 {
    font-family: var(--font-serif);
    font-size: var(--text-h4);
    font-weight: 400;
  }
  .type-h5 {
    font-family: var(--font-serif);
    font-size: var(--text-h5);
    font-weight: 500;
  }
  .type-label {
    font-family: var(--font-mono);
    font-size: var(--text-label);
    font-weight: 500;
  }
  .type-overline {
    font-family: var(--font-mono);
    font-size: var(--text-label);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.7px;
  }
  .type-caption {
    font-family: var(--font-mono);
    font-size: var(--text-caption);
    font-weight: 500;
  }
  @media (min-width: 768px) {
      .type-figure {
        font-size: var(--text-h3);
      }
  }

  /* The client app's text styles (the public site and members' pages):
     Crimson Pro for headings and the lead, Geist for text, Geist Mono for
     small details. intro the description under a sheet's title (Geist
     16/24). h1 an event's title, h2 a section's heading, lead the text that
     opens an event, value a fact's figure ("10 km"), item a name in a list
     (a space, an organizer, a location), body a paragraph, label a field
     name or a short line, caption a photo credit or a date on a photo. The
     admin keeps type above; the two systems share no text style. Line
     heights are set here , since a text token's second value is not applied.
     With app-type-h1, app-type-h2, app-type-lead, app-type-value,
     app-type-item, app-type-body, app-type-intro, app-type-label,
     app-type-caption. */
  .app-type {
    margin: 0;
  }
  .app-type-h1 {
    font-family: var(--font-display);
    font-size: var(--text-app-h1);
    line-height: 48px;
    font-weight: 400;
  }
  .app-type-h2 {
    font-family: var(--font-display);
    font-size: var(--text-app-h2);
    line-height: 40px;
    font-weight: 500;
  }
  .app-type-lead {
    font-family: var(--font-display);
    font-size: var(--text-app-lead);
    line-height: 32px;
    font-weight: 400;
  }
  .app-type-value {
    font-family: var(--font-body);
    font-size: var(--text-app-value);
    line-height: 24px;
    font-weight: 600;
  }
  .app-type-item {
    font-family: var(--font-body);
    font-size: var(--text-app-item);
    line-height: 24px;
    font-weight: 500;
  }
  .app-type-body {
    font-family: var(--font-body);
    font-size: var(--text-app-body);
    line-height: 24px;
    font-weight: 400;
  }
  .app-type-intro {
    font-family: var(--font-body);
    font-size: var(--text-md);
    line-height: 24px;
    font-weight: 400;
  }
  .app-type-label {
    font-family: var(--font-body);
    font-size: var(--text-app-label);
    line-height: 20px;
    font-weight: 500;
  }
  .app-type-caption {
    font-family: var(--font-mono);
    font-size: var(--text-app-caption);
    line-height: 16px;
    font-weight: 500;
  }

  /* app-button: primary is dark on the light booking sheet (Figma "Reserve
     Now"); inverse is light on the dark page. With app-btn-primary,
     app-btn-inverse, app-btn-ink, app-btn-wide. */
  .app-btn {
    display: inline-flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    gap: var(--spacing-sm);
    height: 48px;
    padding-left: var(--spacing-xl);
    padding-right: var(--spacing-xl);
    border-radius: var(--radius-pill);
    font-family: var(--font-body);
    font-size: var(--text-app-label);
    line-height: 24px;
    font-weight: 500;
    white-space: nowrap;
    cursor: pointer;
    transition: opacity 150ms ease 0s;
  }
  .app-btn:hover {
    opacity: 0.85;
  }
  .app-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
  }
  .app-btn:where(.app-btn-primary, :not(.app-btn-primary, .app-btn-inverse, .app-btn-ink)) {
    background-color: var(--color-cat);
    color: var(--color-cat-ink);
  }
  .app-btn-primary {
    background-color: var(--color-cat);
    color: var(--color-cat-ink);
  }
  .app-btn-inverse {
    background-color: var(--color-cat-ink);
    color: var(--color-cat);
  }
  .app-btn-ink {
    background-color: var(--color-ink);
    color: var(--color-band);
  }
  .app-btn-wide {
    width: 100%;
  }

  /* app-tab, one tab of an app-tabs group; the selected one is filled. Tabs
     share the track's width and grow to fit a long label. */
  .app-tab {
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    flex-grow: 1;
    flex-shrink: 0;
    height: 32px;
    padding-left: var(--spacing-xl);
    padding-right: var(--spacing-xl);
    border-radius: var(--radius-pill);
    font-family: var(--font-body);
    font-size: var(--text-app-label);
    line-height: 20px;
    font-weight: 500;
    color: var(--color-cat-ink);
    white-space: nowrap;
    cursor: pointer;
    transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke;
    transition-duration: 150ms;
    transition-timing-function: ease;
    transition-delay: 0s;
  }
  .app-tab:hover {
    background-color: color-mix(in srgb, var(--color-cat-ink) 10%, transparent);
  }

  /* app-tabs, the track the tabs sit in; it scrolls sideways when the labels
     do not fit. */
  .app-tabs {
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    align-items: stretch;
    gap: var(--spacing-sm);
    padding: 0.125rem;
    border-radius: var(--radius-md);
    background-color: var(--color-shade);
    overflow-x: auto;
  }

  /* app-badge: an icon and a short label (the event's activity, location,
     organizer). Takes the colour of the text around it. */
  .app-badge {
    display: inline-flex;
    flex-direction: row;
    justify-content: flex-start;
    align-items: center;
    gap: var(--spacing-xs);
    padding-left: var(--spacing-xs);
    padding-right: var(--spacing-sm);
    border-radius: var(--radius-sm);
    background-color: var(--color-shade);
    font-family: var(--font-body);
    font-size: var(--text-app-label);
    line-height: 24px;
    font-weight: 500;
    white-space: nowrap;
  }

  /* app-detail-list of app-detail-row: a label and its value on one line,
     between rules in the text's colour at 10%. */
  .app-detail-list {
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    align-items: stretch;
    border-bottom: 1px solid color-mix(in srgb, currentColor 10%, transparent);
  }

  .app-detail-row {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    gap: var(--spacing-lg);
    padding-top: var(--spacing-sm);
    padding-bottom: var(--spacing-sm);
    border-top: 1px solid color-mix(in srgb, currentColor 10%, transparent);
    font-family: var(--font-body);
    font-size: var(--text-app-label);
    line-height: 24px;
    font-weight: 500;
  }

  /* app-field: a one-line text field on the neutral page (the newsletter's
     email); its placeholder is muted (public/site.css). */
  .app-field {
    flex: 1;
    min-width: 0;
    height: 48px;
    padding-left: var(--spacing-lg);
    padding-right: var(--spacing-lg);
    border-radius: var(--radius-pill);
    border: 1px solid var(--color-muted);
    background: none;
    color: var(--color-ink);
    font-family: var(--font-body);
    font-size: var(--text-app-label);
    line-height: 20px;
    font-weight: 500;
  }
  .app-field:focus {
    outline: none;
    border: 1px solid var(--color-ink);
  }

  /* app-icon-link: a round link with only an icon (the footer's email,
     Instagram, Facebook); label it for screen readers. */
  .app-icon-link {
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    width: 48px;
    height: 48px;
    border-radius: var(--radius-pill);
    background-color: var(--color-band);
    color: var(--color-ink);
    flex-shrink: 0;
    transition: opacity 150ms ease 0s;
  }
  .app-icon-link:hover {
    opacity: 0.85;
  }

  /* app-info-row: a label over its value, with an optional action at the end
     (the booking sheet's rows: date, meeting point, price). */
  .app-info-row {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    gap: var(--spacing-lg);
    padding-top: var(--spacing-lg);
    padding-bottom: var(--spacing-lg);
    border-bottom: 1px solid color-mix(in srgb, currentColor 10%, transparent);
    font-family: var(--font-body);
    font-size: var(--text-app-label);
    line-height: 20px;
    font-weight: 500;
  }

  /* app-sheet: a sheet that slides up over the page (the space's and the
     location's details), on the page's neutral colours; public/app.js opens
     it from a [data-open-sheet] button. */
  .app-sheet {
    position: fixed;
    margin: 0;
    margin-top: auto;
    margin-left: auto;
    margin-right: auto;
    bottom: 0;
    width: 100%;
    max-width: var(--container-read);
    max-height: 92vh;
    padding: 0;
    border: none;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    overflow-y: auto;
    background-color: var(--color-page);
    color: var(--color-ink);
  }
  .app-sheet::backdrop {
    background-color: color-mix(in srgb, var(--color-ink) 60%, transparent);
  }

  /* app-link-chip: an icon and a word, a link out (call, website,
     Instagram). */
  .app-link-chip {
    display: inline-flex;
    flex-direction: row;
    justify-content: flex-start;
    align-items: center;
    gap: var(--spacing-xs);
    padding-left: var(--spacing-sm);
    padding-right: var(--spacing-lg);
    padding-top: 14px;
    padding-bottom: 14px;
    border-radius: var(--radius-pill);
    background-color: var(--color-band);
    color: var(--color-ink);
    font-family: var(--font-body);
    font-size: var(--text-app-label);
    line-height: 16px;
    font-weight: 500;
    white-space: nowrap;
    flex-shrink: 0;
  }

  /* app-event-card: a tall photo with its date, the place and the title (the
     "more ideas" row). */
  .app-event-card {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    align-items: stretch;
    gap: var(--spacing-sm);
    width: 160px;
    flex-shrink: 0;
    color: var(--color-ink);
  }

  /* Buttons are effortless-ui's btn in this app's shape: a pill as tall as
     its text and padding, with no border unless its kind draws one. A kind
     sets --btn-bg, --btn-fg and --btn-hover, which the library's rules
     read. The library's compact sizes (btn-xs, btn-icon), which its own
     components put inside a control, keep its shape. A btn with no kind is
     the main action. With btn-secondary (the library's own parts write
     btn-outline, which looks the same here), btn-danger, btn-category,
     btn-on-category, btn-category-outline, and btn-sm for the compact size;
     w-full stretches one. */
  .btn:where(:not(.btn-xs, .btn-icon)) {
    flex-shrink: 1;
    gap: var(--spacing-sm);
    height: auto;
    padding: var(--spacing-md) var(--spacing-xl);
    border: 0;
    border-radius: var(--radius-pill);
    font-size: var(--text-label);
    line-height: 1.5;
    white-space: normal;
    user-select: auto;
    transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke;
    transition-duration: 150ms;
    transition-timing-function: ease;
    transition-delay: 0s;
  }
  /* The browser's own focus outline, and no nudge when pressed. */
  .btn:where(:not(.btn-xs, .btn-icon)):focus-visible {
    outline: revert-layer;
  }
  .btn:where(:not(.btn-xs, .btn-icon)):active:not([aria-haspopup]) {
    translate: none;
  }
  .btn:where(:not(.btn-xs, .btn-icon)):disabled {
    cursor: not-allowed;
    pointer-events: auto;
  }
  .btn:where(:not(.btn-xs, .btn-icon)):disabled:hover {
    background-color: var(--btn-bg);
  }
  .btn:where(:not(.btn-xs, .btn-icon)) svg {
    flex-shrink: revert-layer;
    width: revert-layer;
    height: revert-layer;
    pointer-events: revert-layer;
  }
  .btn:where(:not(.btn-outline, .btn-secondary, .btn-ghost, .btn-danger, .btn-link, .btn-category, .btn-on-category, .btn-category-outline)) {
    --btn-hover: var(--color-brand-strong);
  }
  .btn-secondary,
  .btn-outline {
    --btn-bg: var(--color-surface);
    --btn-fg: var(--color-ink);
    --btn-hover: var(--color-band);
    border: 1px solid var(--color-rule);
  }
  .btn-danger {
    --btn-bg: var(--color-danger);
    --btn-fg: var(--color-on-brand);
    --btn-hover: var(--color-danger);
  }
  .btn-category {
    --btn-bg: var(--color-cat);
    --btn-fg: var(--color-cat-ink);
    --btn-hover: var(--color-cat);
  }
  .btn-on-category {
    --btn-bg: var(--color-cat-ink);
    --btn-fg: var(--color-cat);
    --btn-hover: var(--color-cat-ink);
  }
  .btn-category-outline {
    --btn-bg: var(--color-cat);
    --btn-fg: var(--color-cat-ink);
    --btn-hover: var(--color-cat);
    border: 1px solid var(--color-cat-ink);
  }
  .btn-sm:where(:not(.btn-icon)) {
    padding: var(--spacing-sm) var(--spacing-lg);
  }
  /* A small button with only an icon (a dialog's close): this app's 32px
     square. */
  .btn-icon.btn-sm {
    height: 32px;
    border-radius: var(--radius-sm);
  }

  /* A dialog over the page (ui-dialog, ui-confirm) is effortless-ui's in
     this app's look: as wide as a form, the work area's serif title, the
     page's text size, a shadow under it, and its buttons at the end with no
     band behind them. */
  .dialog {
    max-width: min(var(--container-form), calc(100% - 2rem));
    padding: var(--spacing-xl);
    border: 0;
    font-size: revert-layer;
    line-height: revert-layer;
    box-shadow: var(--shadow-edge), var(--shadow-popover);
  }
  .dialog-alert {
    max-width: min(var(--container-form), calc(100% - 2rem));
  }
  .dialog::backdrop {
    backdrop-filter: none;
  }
  :is(.dialog, .dialog > form) > header > :is(h1, h2, h3) {
    font-family: var(--font-serif);
    font-size: var(--text-h5);
    line-height: 1.5;
  }
  :is(.dialog, .dialog > form) > header > p {
    font-size: var(--text-sm);
    line-height: 1.5;
  }
  :is(.dialog, .dialog > form) > footer {
    gap: var(--spacing-sm);
    margin: 0;
    padding: 0;
    border-top: 0;
    background-color: transparent;
  }
  /* A button there keeps its text on one line; side by side, the ones that
     do not fit go to a second row. A dialog with four is wider, so that
     they fit. */
  .dialog:has(> footer > .btn:nth-child(4)) {
    max-width: min(calc(var(--container-form) + 6rem), calc(100% - 2rem));
  }
  :is(.dialog, .dialog > form) > footer > .btn {
    flex-shrink: 0;
    white-space: nowrap;
  }
  @media (min-width: 40rem) {
    :is(.dialog, .dialog > form) > footer {
      flex-wrap: wrap;
    }
  }

  /* Tables in the work areas: th for a column heading, td for a cell. A row
     that opens something adds hover:bg-page. */
  .th {
    padding-left: var(--spacing-lg);
    padding-right: var(--spacing-lg);
    padding-top: var(--spacing-sm);
    padding-bottom: var(--spacing-sm);
    text-align: left;
    font-family: var(--font-mono);
    font-size: var(--text-caption);
    font-weight: 500;
    color: var(--color-muted);
    text-transform: uppercase;
    border-bottom: 1px solid var(--color-rule);
    white-space: nowrap;
  }

  .td {
    padding-left: var(--spacing-lg);
    padding-right: var(--spacing-lg);
    padding-top: var(--spacing-md);
    padding-bottom: var(--spacing-md);
    font-size: var(--text-sm);
    border-bottom: 1px solid var(--color-rule);
    vertical-align: top;
  }

  /* A link in a work area's sidebar, which sits on the band colour; current
     is the page shown. With nav-item-current. */
  .nav-item {
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    align-items: center;
    gap: var(--spacing-md);
    padding-left: var(--spacing-md);
    padding-right: var(--spacing-md);
    padding-top: var(--spacing-sm);
    padding-bottom: var(--spacing-sm);
    border-radius: var(--radius-md);
    font-size: var(--text-sm);
    color: var(--color-ink);
  }
  .nav-item:hover {
    background-color: var(--color-surface);
  }
  .nav-item-current {
    background-color: var(--color-surface);
    font-weight: 600;
    box-shadow: var(--shadow-card);
  }

  /* A number beside a link or a heading: unread notifications, items
     waiting. */
  .count {
    display: inline-flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    min-width: 20px;
    height: 20px;
    padding-left: var(--spacing-xs);
    padding-right: var(--spacing-xs);
    border-radius: var(--radius-pill);
    font-size: var(--text-caption);
    font-weight: 600;
    background-color: var(--color-brand);
    color: var(--color-on-brand);
  }

  /* A field's name: effortless-ui's label on a line of its own, at the
     line height of the text around it. Inside ui-field, which spaces its
     parts itself, it has no margin. */
  .label {
    display: block;
    font-size: var(--text-label);
    line-height: revert-layer;
    color: var(--color-ink);
    margin-bottom: var(--spacing-sm);
  }
  label > .label {
    margin-bottom: 0;
  }

  /* A text control (an input, a select, a textarea, the date picker's
     button) is effortless-ui's input in this app's look: 16px text with 12
     and 16px around it, and a textarea as tall as its rows. Its height,
     border, corner and fill are tokens in app/theme.css. It turns red with
     aria-invalid="true", or inside a ui-field that has an error. */
  .input {
    padding: var(--spacing-md) var(--spacing-lg);
    font-size: var(--text-md);
    line-height: 1.5rem;
  }
  select.input {
    font-size: var(--text-md);
    line-height: 1.5rem;
  }
  textarea.input {
    min-height: revert-layer;
    padding-block: var(--spacing-md);
    field-sizing: revert-layer;
  }
  .input:focus {
    outline: none;
    border-color: var(--color-ring);
  }
  /* A field in a row of a list that has column headings: from md up its
     name is for screen readers only. Around a ui-field. */
  @media (min-width: 768px) {
    .field-compact .label {
      position: absolute;
      width: 1px;
      height: 1px;
      margin: -1px;
      padding: 0;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
    }
  }

  /* A panel one of this app's parts opens under itself: the photo table's
     "Add photo" choices, the list of what a record lacks. effortless-ui's
     popup and popover are the library's own and are left as they are. */
  .drop-panel {
    position: absolute;
    z-index: 30;
    margin-top: var(--spacing-xs);
    background-color: var(--color-surface);
    border: 1px solid var(--color-rule);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-popover);
  }

  /* One choice in a list an island opens (the photo table's "Add photo"). */
  .option {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    gap: var(--spacing-md);
    padding-left: var(--spacing-lg);
    padding-right: var(--spacing-lg);
    padding-top: var(--spacing-sm);
    padding-bottom: var(--spacing-sm);
    font-size: var(--text-md);
    color: var(--color-ink);
    cursor: pointer;
  }

  /* A square icon button: a photo row's tools, a dialog's close. */
  .tool {
    display: inline-flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    width: 32px;
    height: 32px;
    border-radius: var(--radius-sm);
    color: var(--color-ink);
    cursor: pointer;
  }
  .tool:hover {
    background-color: var(--color-band);
  }
  .tool:focus {
    outline: none;
  }
  .tool:focus-visible {
    box-shadow: 0 0 0 2px var(--color-ink);
  }

  /* A message on the page is effortless-ui's alert in this app's look: a
     tinted box with its kind's border, its text laid out as a paragraph
     unless an icon comes first. A danger one takes role="alert", the others
     role="status". With alert-danger, alert-success, and this app's
     alert-warning. */
  .alert {
    padding: var(--spacing-lg);
    line-height: revert-layer;
    text-align: revert-layer;
  }
  .alert:where(:not(:has(> svg))) {
    display: block;
  }
  .alert-danger {
    background-color: var(--color-danger-soft);
    border-color: var(--color-danger);
  }
  .alert-success {
    background-color: var(--color-success-soft);
    border-color: var(--color-success);
  }
  .alert-warning {
    background-color: var(--color-warning-soft);
    color: var(--color-warning);
    border-color: var(--color-warning);
  }

  /* effortless-ui's card with this app's edge (a border and a faint
     shadow) and the text of the page around it. */
  .card {
    padding: var(--spacing-lg);
    border-radius: var(--radius-lg);
    background-color: var(--color-surface);
    border: 1px solid var(--color-rule);
    box-shadow: var(--shadow-card);
    color: revert-layer;
    font-size: revert-layer;
    line-height: revert-layer;
  }
  @media (min-width: 768px) {
      .card {
        padding: var(--spacing-xl);
      }
  }

  /* A small rounded label (a category on a card, a booking status) is
     effortless-ui's badge in this app's look: mono type, as tall as its text
     and padding, and the same on a link when the pointer is over it. A kind
     sets --badge-bg and --badge-fg. With badge-secondary (neutral),
     badge-success, badge-danger, and this app's badge-warning and
     badge-category (the palette of the data-cat around it). */
  .badge {
    --badge-hover: var(--badge-bg);
    flex-shrink: revert-layer;
    gap: revert-layer;
    width: revert-layer;
    height: auto;
    padding: var(--spacing-sm) var(--spacing-lg);
    overflow: revert-layer;
    border-radius: var(--radius-pill);
    font-family: var(--font-mono);
    line-height: revert-layer;
    transition: revert-layer;
  }
  .badge:where(:not(.badge-outline)) {
    border-width: 0;
  }
  .badge-success {
    --badge-bg: var(--color-success-soft);
  }
  .badge-warning {
    --badge-bg: var(--color-warning-soft);
    --badge-fg: var(--color-warning);
  }
  .badge-category {
    --badge-bg: var(--color-pill);
    --badge-fg: var(--color-pill-ink);
  }

  /* A row of links that switch a list's view (Upcoming / Past) is
     effortless-ui's tabs in this app's look: a pill on the band colour, the
     current link raised on the surface. The current one has
     aria-current="page". */
  .tabs {
    gap: var(--spacing-xs);
    height: auto;
    padding: var(--spacing-xs);
    border-radius: var(--radius-pill);
  }
  .tabs > :is(a, button, label) {
    height: auto;
    padding: var(--spacing-xs) var(--spacing-lg);
    border: 0;
    border-radius: var(--radius-pill);
    color: var(--color-muted);
    font-weight: 400;
    line-height: 1.5;
    white-space: revert-layer;
    transition: revert-layer;
  }
  .tabs > :is(a, button, label):hover,
  .tabs > :is([aria-current="page"], [aria-selected="true"], :has(:checked)) {
    color: var(--color-ink);
  }
  .tabs > :is([aria-current="page"], [aria-selected="true"], :has(:checked)) {
    background-color: var(--color-surface);
    box-shadow: var(--shadow-card);
    font-weight: 600;
  }

  /* Markdown rendered by the server (event bodies, notes, bios):
     effortless-ui's prose at the line height of where it stands, its
     paragraphs, lists and subheadings spaced as below. */
  .prose { line-height: revert-layer; }
  .prose li + li, .prose li > :is(ul, ol), .prose li > p + p { margin-top: revert-layer; }
  .prose p { margin: 0 0 1em; }
  .prose p:last-child { margin-bottom: 0; }
  .prose h3 { font-family: var(--font-serif); font-size: 1.5rem; line-height: 2rem; font-weight: 500; margin: 1.5em 0 0.5em; }
  .prose ul { list-style: disc; padding-left: 1.25rem; margin: 0 0 1em; }
  .prose ol { list-style: decimal; padding-left: 1.25rem; margin: 0 0 1em; }
  .prose a { text-decoration: underline; text-underline-offset: 2px; }
  .prose strong { font-weight: 600; }
  /* Text that opens with a subheading starts at the top, without the space a
     subheading keeps from the paragraph above it. */
  .prose > :first-child { margin-top: 0; }

  /* An on/off switch is effortless-ui's switch, on a checkbox with
     role="switch", in this app's look: a 44 by 24 track in the text's colour
     at 22%, green while on, with a white knob. */
  .switch {
    --switch-thumb: 18px;
    width: 44px;
    height: 24px;
    margin: 0;
    padding: 0 3px;
    border: 0;
    border-radius: var(--radius-pill);
    background-color: color-mix(in srgb, currentColor 22%, transparent);
  }
  .switch::before {
    background-color: white;
    box-shadow: 0 1px 2px rgb(0 0 0 / 0.2);
  }
  .switch:checked {
    background-color: #004639;
  }
  .switch:checked::before {
    background-color: white;
    translate: 20px;
  }
  .switch:focus-visible {
    outline: 2px solid #004639;
    outline-offset: 2px;
  }

  /* effortless-ui's checkbox, left as the browser draws one, at 18px. Without
     these rules it is the library's: a box in the brand colour with a tick. */
  .checkbox {
    appearance: revert-layer;
    display: revert-layer;
    flex-shrink: revert-layer;
    place-content: revert-layer;
    width: 18px;
    height: 18px;
    padding: revert-layer;
    border: revert-layer;
    border-radius: revert-layer;
    background-color: revert-layer;
    transition: revert-layer;
    cursor: pointer;
  }
  .checkbox:checked {
    border-color: revert-layer;
    background-color: revert-layer;
  }
  .checkbox:checked::after {
    content: none;
  }
  .checkbox:focus-visible {
    outline: revert-layer;
    border-color: revert-layer;
    box-shadow: revert-layer;
  }
  /* A checkbox with its label beside it: a hidden "0" of the same name goes
     first, so an unchecked box still posts the field. */
  .check {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    font-size: var(--text-md);
    cursor: pointer;
  }

  /* Client app components (app/components/app-*): the selected tab is filled
     with the text colour (public/app.js switches it), and a focused
     button or tab gets a ring in its text colour. */
  .app-tab[aria-selected="true"] {
    background: var(--color-cat-ink);
    color: var(--color-cat);
    border-radius: var(--radius-md);
  }
  .app-tabs { scrollbar-width: none; }
  .app-tabs::-webkit-scrollbar { display: none; }
  .app-tab:focus-visible,
  .app-btn:focus-visible,
  .app-icon-link:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 2px;
  }

  /* The event's story on the redesigned page: a subheading (### in the text)
     in app-type h2, paragraphs in app-type lead. */
  .app-prose { display: flex; flex-direction: column; gap: 2rem; }
  .app-prose > * { margin: 0; }
  .app-prose h3 { font-family: var(--font-display); font-size: 2.125rem; line-height: 2.5rem; font-weight: 500; }
  .app-prose p, .app-prose li { font-family: var(--font-display); font-size: 1.3125rem; line-height: 2rem; }
  .app-prose ul { list-style: disc; padding-left: 1.25rem; }
  .app-prose ol { list-style: decimal; padding-left: 1.25rem; }
  .app-prose a { text-decoration: underline; text-underline-offset: 2px; }
  .app-prose strong { font-weight: 600; }

  /* Text written in Markdown inside a booking row (price, notes): a small
     gap between paragraphs. */
  .app-info-row p + p { margin-top: 0.5rem; }

  .app-field::placeholder { color: var(--color-muted); opacity: 1; }

  /* A row that scrolls sideways by touch (photos, cards, chips): no
     scrollbar line under it. */
  .app-scroll-x { scrollbar-width: none; }
  .app-scroll-x::-webkit-scrollbar { display: none; }
}

/* Category palettes. An element with data-cat={event.category} gets its
   category's colours for bg-cat, text-cat-ink, bg-pill and text-pill-ink.
   cat is the page colour of an event in that category, cat-ink its text;
   the pill on a card is the inverse unless a palette says otherwise.
   Pairs from the editorial site (avangrada-old src/lib/events.ts). */

[data-cat] {
  --color-pill: var(--color-cat-ink);
  --color-pill-ink: var(--color-cat);
}

[data-cat="vodeno"] { --color-cat: #addfff; --color-cat-ink: #0152ab; }
[data-cat="smireno"] { --color-cat: #bdd1d8; --color-cat-ink: #7c1823; }
[data-cat="kreativno"] { --color-cat: #bdd8c4; --color-cat-ink: #a2480a; }
[data-cat="drustveno"] { --color-cat: #f0ba60; --color-cat-ink: #7c1823; }
/* No palette of its own yet; kreativno's on purpose. */
[data-cat="porodicno"] { --color-cat: #bdd8c4; --color-cat-ink: #a2480a; }

/* The dark pages: the pill on a card keeps the page's colours. */
[data-cat="aktivno"] {
  --color-cat: #004639;
  --color-cat-ink: #b5f9c1;
  --color-pill: #004639;
  --color-pill-ink: #b5f9c1;
}
/* Placeholder palette; gladno is not offered yet. */
[data-cat="gladno"] {
  --color-cat: #5c1a00;
  --color-cat-ink: #ffcbb3;
  --color-pill: #5c1a00;
  --color-pill-ink: #ffcbb3;
}

/* The client app's accent per category theme: the theme's own colours,
   inverted where the surface is (text colour on the page, page colour on
   the light badge); Aktivno keeps the orange of its Figma. More accents
   can come per theme later. */
[data-cat] {
  --color-accent: var(--color-cat-ink);
  --color-on-accent: var(--color-cat);
  --color-accent-inverse: var(--color-cat);
  --color-accent-off: var(--color-cat-ink);
}
[data-cat="aktivno"] {
  --color-accent: #e95f2a;
  --color-on-accent: #f7f0e6;
  --color-accent-inverse: #e95f2a;
  --color-accent-off: #938b87;
}

/* A list of rows edited in place (effortless-ui's ui-rows, on a data-rows
   element) shows its column headings only above rows. */
[data-rows]:not(:has(> [data-row])) > [data-head] { display: none; }

/* A work-area page inside a side panel (public/pwa.js) shows only the
   record's editable fields: no menu, no way back, no header actions, and
   none of the related records beside the form. */
html[data-framed] [data-area-nav],
html[data-framed] [data-back],
html[data-framed] [data-header-actions],
html[data-framed] [data-related] {
  display: none;
}

/* Records related to the one being edited (a partner's events, a
   location's events and spaces) sit in a sidebar locked to the right edge
   on wide screens, and below the form on narrower ones. The editing area
   takes the width left, up to a readable measure. In a side panel they are
   hidden (above). */
@media (min-width: 1360px) {
  html:not([data-framed]) [data-related] {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 15;
    width: 340px;
    overflow-y: auto;
    padding: 2rem 1.5rem;
    background: var(--color-band);
    border-left: 1px solid var(--color-rule);
  }
  html:not([data-framed]) main:has([data-related]) {
    padding-right: calc(340px + 2.5rem);
  }
}
html:not([data-framed]) main:has([data-related]) > div {
  max-width: 960px;
}

/* ui-combobox (effortless-ui): room for the button at
   the field's end, and a list at the fields' text size with rows as tall as
   a field's line and its padding; the picked row is bold beside its tick.
   Outside a layer, as the component's own rules come after this file. */
.combobox-box { padding-right: var(--spacing-3xl); }
.combobox-list { font-size: var(--text-md); line-height: 1.5rem; }
.combobox-list [role="option"] { padding: var(--spacing-sm) 2rem var(--spacing-sm) var(--spacing-md); }
.combobox-list [aria-selected="true"] { font-weight: 600; }
.combobox-list [aria-selected="true"] > svg { top: calc(50% - 0.5rem); }

/* ui-field and ui-select (effortless-ui). A field's name keeps the line of
   the text around it, where the library sets a tighter one; a select has
   room for its arrow where this app's fields had it. */
label > .label.leading-snug { line-height: inherit; }
.select > select { padding-right: var(--spacing-3xl); cursor: pointer; }
.select > svg { right: var(--spacing-lg); }

/* ui-datepicker (effortless-ui) in this app's look: the field's text at the
   fields' size, and a calendar of round 40px days with small square arrows,
   today ringed and the picked day filled. */
.datepicker-date > .input { padding-right: var(--spacing-lg); font-size: var(--text-md); line-height: 1.5rem; }
/* Room for the clear button, which stands over the field's end. */
.datepicker-date > .input:has(+ .btn) { padding-right: var(--spacing-3xl); }
.datepicker-panel { padding: var(--spacing-md); }
.datepicker-head > .btn { width: 32px; height: 32px; border-radius: var(--radius-sm); }
.datepicker-panel table { margin-top: var(--spacing-sm); }
.datepicker-panel th { width: 40px; height: 40px; font-size: var(--text-caption); font-weight: 500; }
.datepicker-panel td { padding: 0; }
.datepicker-panel td > button { width: 40px; height: 40px; border-radius: var(--radius-pill); }
.datepicker-panel td > button[aria-current] { border-color: var(--color-rule); background-color: transparent; }
.datepicker-panel td > button[aria-current]:hover { background-color: var(--color-band); }
.datepicker-panel td:not([data-mark="between"])[data-mark] > button { border-color: transparent; background-color: var(--color-brand); }

/* ui-timepicker (effortless-ui): hours and minutes as tall as a calendar's
   days are, with the small square corners of its arrows. */
.timepicker-panel { padding: var(--spacing-sm); }
.timepicker-panel > span { max-height: 240px; }
.timepicker-panel button { width: 48px; height: 40px; border-radius: var(--radius-sm); }

/* ui-toaster (effortless-ui), the short message after a save (data-toast on
   a form), in the look of this app's save toast (undo-notice): ink with the
   page's light text, above the phone's tab bar and a form's save bar. */
.toaster:not([data-position^="top"]) { bottom: 6rem; }
.toast { padding: var(--spacing-sm) var(--spacing-sm) var(--spacing-sm) var(--spacing-lg); border: 0; border-radius: var(--radius-lg); background-color: var(--color-ink); color: var(--color-surface); box-shadow: var(--shadow-popover); }

/* ui-upload (effortless-ui) in this app's look: a roomier drop area on the
   surface, and a saved or picked picture shown large over its name. */
.upload-drop { padding: var(--spacing-xl); background-color: var(--color-surface); }
.upload ul { max-width: var(--container-form); }
.upload li { flex-wrap: wrap; padding: var(--spacing-sm); }
.upload li > img { flex-basis: 100%; width: 100%; height: auto; aspect-ratio: 16 / 9; border-radius: var(--radius-sm); }

/* ui-markdown (effortless-ui) in this app's look: the text at the fields'
   size with room around it. This app's texts take one level of subheading
   and no quotes (the public pages style nothing else), so the Heading and
   Quote buttons are left out; they are found by their names. */
.markdown > [role="toolbar"] { gap: var(--spacing-xs); padding: var(--spacing-xs) var(--spacing-sm); }
.markdown-text { min-height: 180px; padding: var(--spacing-lg); font-size: var(--text-md); line-height: 1.6; }
.markdown button[aria-label="Heading"], .markdown button[aria-label="Quote"] { display: none; }
