/* SFAF Calendar — /caladmin portal */

/* ---------------------------------------------------------------------------
   THE BRAND, AND THE ONE RULE THE GUIDE IS EXPLICIT ABOUT.

   The guide (v3.0) approves ten colours and then says not to use them all:
   too many produces a kaleidoscope. It directs a neutral gray or black plus
   ONE OR TWO accents, with lighter and darker variations of those for
   contrast. So this portal is Dark Gray and white, TEAL as the single
   structural accent, and YELLOW reserved for one job.

   YELLOW MEANS "THIS IS THE ACTION" AND NOTHING ELSE. Save and Add. The
   moment it decorates a heading or a border it stops carrying that meaning
   and there is no colour left that does.

   EVERY PAIRING BELOW IS MEASURED, NOT CHOSEN BY EYE. Brand teal #16BECF is
   2.26:1 against white and has been banned as a text colour here since 3.1.0.
   The guide permits darker variations of an approved colour, and p.18's
   #0E818C is the usual one, but it measures 4.27:1 on the 10% teal heading
   band and 4.28:1 on the page background, both of which fail AA. So teal that
   carries text is one step darker again: --uc-accent-text below clears 4.5:1
   on white, on the page background and on both bands.
   ------------------------------------------------------------------------- */
:root {
    /* Approved SFAF brand palette (brand guide v3.0, p.9), verbatim. */
    --sfaf-yellow:    #FFD900;
    --sfaf-orange:    #F7921E;
    --sfaf-red:       #F04937;
    --sfaf-burgundy:  #A30C33;
    --sfaf-pink:      #F1668C;
    --sfaf-purple:    #8D54A2;
    --sfaf-green:     #8CC745;
    --sfaf-teal:      #16BECF;
    --sfaf-lightgray: #D1D3D4;
    --sfaf-darkgray:  #373433;
    --sfaf-black:     #000000;
    --sfaf-gray:      #373433;

    --uc-primary: #FFD900;   /* SFAF yellow, Pantone 109 CP. PRIMARY ACTIONS ONLY. */
    --uc-accent: #16BECF;    /* teal fill/border, Pantone 7710 UP. Decoration only. */
    /* Teal that CARRIES TEXT, or has to be seen as a control boundary.
       5.35:1 on white, 4.95:1 on the page background, 4.94:1 and 4.56:1 on the
       two heading bands. See the note above for why not #0E818C. */
    --uc-accent-text: #0E7680;

    /* The 10% teal heading band, pre-flattened. A translucent fill over an
       unknown backdrop cannot be contrast-checked; a flat colour can, and
       these are the two values the alpha actually resolves to here. */
    --uc-band: #E8F9FA;      /* over a white card */
    --uc-band-alt: #DFF0F3;  /* over the page background */

    /* The dim behind a modal, the value the confirm and scope dialogs'
       ::backdrop has always used, named for the tour (3.108.0). */
    --p-scrim: rgba(15, 23, 42, 0.55);

    /* The editors' inline notices (3.108.1): the palette's success state is
       the Green family, its tint and ink 6.08:1; a failure is the Red
       family's tint and ink, 6.10:1. */
    --p-ok-tint: #F1F8E9;
    --p-ok-ink: #46661F;
    --p-error-tint: #FDE9E7;
    --p-error-ink: #AD1C0D;
    --p-shadow-raised: 0 24px 60px rgba(0, 0, 0, 0.28);

    --p-bg: #F5F6F7;
    --p-panel: #ffffff;
    /* Hairlines between rows: decorative, so brand Light Gray at low contrast
       is right. A control's OWN boundary is --p-border-strong below, which is
       a darker variation of the same brand gray and clears 3:1. */
    --p-border: #E2E5EA;
    --p-border-strong: #8C8D8E;
    /* ---------------------------------------------------------------------
       THE TWO CONTROL FACES. WHITE IS THE STATEMENT, AND IT ONLY WORKS IF
       SOMETHING ELSE IS NOT WHITE.

       DESIGN.md settled this on the public filter bar in 3.61.0: white fill
       with a boundary means you TYPE in this or it OPENS; no fill means you
       PRESS it. Caladmin had the first half and not the second, so a
       secondary button and a text field were the same object twice, white
       with a 1px --p-border-strong edge and an 8px radius, differing only in
       font-weight. That is the whole of the reported complaint, reported
       three times on three screens.

       In caladmin "no fill" is not available: a button sits on a white card
       as often as on the page, so transparent IS white there. So the pair is
       inverted and the BUTTON takes the surface. Brand Light Gray at its own
       value, which spends no accent and cannot compete with the one yellow.

       MEASURED, in .claude/control-standard-audit.php, which fails the build
       if these two ever come to the same value again:

         #D1D3D4 face against a white card         1.50:1
         #D1D3D4 face against the page #F5F6F7     1.39:1
         #373433 ink on the face                   8.22:1
         #BFC2C4 hover face, ink on it             6.89:1

       IT IS NOT THE DISABLED STATE, and the numbers are how that is kept
       true rather than a hope. A disabled control here is LIGHTER than the
       page with MUTED ink: #F3F4F6 with #6B7280 (.uc-field-nobulk) or
       #F9FAFB with #4B5563 (.uc-field-locked). This is darker than both, at
       full ink and 600 weight, and measures 1.37:1 against the nearer of
       them.
       --------------------------------------------------------------------- */
    --p-control-face: #ffffff;   /* you type in this, or it opens */
    --p-btn-face: #D1D3D4;       /* you press this */
    --p-btn-face-hover: #BFC2C4;
    --p-text: #373433;       /* brand Dark Gray, not pure black */
    --p-muted: #6B6764;      /* a warm gray from the same family, 5.60:1 on white */
    /* The bento cards sit on the page background and need to read as raised
       panels without a heavy border. surface-2 is a hair off white so a card
       inside a card is still legible. */
    --surface-2: #FFFFFF;
    --p-sidebar: #373433;
    --p-sidebar-text: #D1D3D4;
    --p-green: #8CC745;      /* Pantone 3561 UP */
    --p-gray: #D1D3D4;
    --p-danger: #F04937;     /* Red, Pantone 179 CP. FILLS AND ICONS ONLY. */
    /* The darkened red that can carry TEXT, exactly as --uc-teal-text is the
       darkened teal that can. Brand red measures 3.68:1 on a card and 3.40:1
       on the page, both under the 4.5:1 floor, which is why DESIGN.md has it
       as large-text only. This is 5.44:1 and 5.03:1 on the same two grounds,
       and is not a new colour: it is what the danger button is filled with. */
    --p-danger-text: #c0392b;

    /* Web brand typefaces (brand guide v3.0, p.10). */
    --uc-font-heading: 'Montserrat', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    --uc-font-body: 'Merriweather', Georgia, 'Times New Roman', serif;
}

* { box-sizing: border-box; }
body.uc-portal {
    margin: 0;
    background: var(--p-bg);
    color: var(--p-text);
    font-family: var(--uc-font-heading);
    font-size: 14px;
    line-height: 1.55;
}
.uc-portal .sfaf-icon { display: inline-block; vertical-align: -0.135em; flex-shrink: 0; }

/* ---------------------------------------------------------------------------
   THE LINK COLOUR IS A FLOOR, NOT A RULING. THIS ONE LINE WAS REPAINTING
   HALF THE PORTAL.

   Written as `.uc-portal a` this is (0,1,1), and an anchor that declares a
   colour of its own through a single class is (0,1,0). One class does not beat
   one class plus one type, so EVERY styled link in caladmin lost its own
   colour to the page's link teal and there was no way to tell by reading the
   rule that declared it, because that rule is correct and simply never won.

   Nine distinct anchors were affected, found by walking each one's class list
   against every colour rule in this file rather than by looking at screens:

     a.uc-nav-item ............ the whole sidebar nav, the visible complaint
     a.uc-btn, a.uc-btn-sm .... every link-shaped button: Cancel, Manage, Rename
     a.uc-btn-primary ......... teal on SFAF yellow, 3.87:1, an actual failure
     a.uc-view-tab ............ the All events / My events tabs
     a.uc-page-num ............ the pager
     a.uc-portal-logout ....... meant to be --p-muted
     a.uc-tlink, a.uc-source-link

   :where() CONTRIBUTES ZERO SPECIFICITY, so the ancestor stops counting and
   this becomes (0,0,1): a bare <a> still gets link teal, and anything that
   names a colour of its own now wins by declaring it once. Same instrument as
   the control fallback further down, applied to the opposite problem: there it
   stops a catch-all from outranking classes, here it stops a base rule from
   doing it.

   THE HOVER UNDERLINE STAYS AT (0,1,1) DELIBERATELY. Dropping it to zero too
   would underline every button and tab that never declares text-decoration.
   Anything that must not underline says so in its own :hover rule, which is
   (0,2,0) and wins; .uc-btn:hover and .uc-nav-item:hover both do.
   ------------------------------------------------------------------------- */
:where(.uc-portal) a { color: var(--uc-accent-text); text-decoration: none; }
.uc-portal a:hover { text-decoration: underline; }
.uc-portal h1 { font-size: 24px; font-weight: 800; margin: 0; letter-spacing: -0.01em; }
/* 17px sat between the section step and the subhead, and this is what every
   h2 in the portal falls back to when it is not a card heading. Subhead. */
.uc-portal h2 { font-size: 16px; font-weight: 600; margin: 0; }

/* ---------------------------------------------------------------------------
   THE TYPE SCALE. FIVE STEPS, AND EVERY ONE OF THEM IS VISIBLY DIFFERENT.

   The coloured card headers fixed the outermost level and stopped there, so
   INSIDE a card everything was still within a point or two of everything else:
   a subhead, a field label and a line of helper text all read as one texture,
   which is the same complaint one level down.

   The ladder, largest to smallest, and nothing may sit between two steps:

     PAGE TITLE   24px  800                        h1
     SECTION      20px  700                        .uc-section-head h2
     CARD HEADING 14px  600  UPPERCASE, tracked, on the tinted band
     SUBHEAD      16px  600  Montserrat, 22px of space above
     FIELD LABEL  13px  600
     BODY         14px  400
     HELPER       12px  400  muted

   THE CARD HEADING IS SMALLER THAN THE SUBHEAD ON PURPOSE. Size is not what
   makes it dominant: uppercase, letter-spacing and a coloured band across the
   full width of the card do that, and all three are things no other level has.
   Making it larger as well would push every field further down the page for a
   distinction that is already unmistakable.

   THE SUBHEAD IS THE STEP THAT WAS MISSING. It has to beat body text at a
   glance, so it is larger, heavier, in the display face, and carries real
   space above it. Space is half the signal: a heading with a line of air over
   it reads as starting something, and one without reads as continuing.
   ------------------------------------------------------------------------- */
.uc-portal { font-size: 14px; }
.uc-portal .uc-subhead,
.uc-portal .uc-notify-subhead,
.uc-portal .uc-schedule-head,
.uc-portal .uc-picker-heading,
.uc-portal h3 {
    font-family: var(--uc-font-heading);
    font-size: 16px;
    font-weight: 600;
    line-height: 1.3;
    letter-spacing: 0;
    text-transform: none;
    color: var(--sfaf-darkgray);
    margin: 22px 0 8px;
}
/* A subhead at the very top of its container has nothing to be spaced away
   from, and the gap would read as a mistake. */
.uc-portal .uc-subhead:first-child,
.uc-portal .uc-notify-subhead:first-child,
.uc-portal .uc-schedule-head:first-child,
.uc-portal .uc-picker-heading:first-child,
.uc-portal h3:first-child { margin-top: 0; }

/* Helper text is the quietest thing on the screen and must never be mistaken
   for a label. Two steps below the subhead and one below the label. */
.uc-portal .uc-hint { font-size: 12px; line-height: 1.55; font-weight: 400; color: var(--p-muted); }
.uc-portal .uc-field-label { font-size: 13px; font-weight: 600; line-height: 1.3; color: var(--sfaf-darkgray); }
.uc-portal .uc-muted { font-size: inherit; color: var(--p-muted); }

/* ---------------------------------------------------------------------------
   HEADINGS HAVE TO READ AS HEADINGS.

   The core complaint about this portal was that everything looked the same
   weight, so a card heading was indistinguishable from the label of a field
   inside it. A heading is now three things at once, which is what makes it
   unmistakable at a glance rather than on inspection: Montserrat (the brand's
   web headline face), UPPERCASE with letter-spacing, and sitting on a tinted
   band that a field label never has.

   14px and semibold, not big and bold. A heading does not have to be large to
   be a heading; it has to be DIFFERENT. Making it large would push the fields
   down the page for nothing.
   ------------------------------------------------------------------------- */
.uc-heading, .uc-card-head h2, .uc-bento-title {
    font-family: var(--uc-font-heading);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
    color: var(--sfaf-darkgray);
}

/* ---------- Login ---------- */
/* ON TOKENS SINCE 3.109.0, and the layout the forgotten-password and reset
   pages share. THE LOGO is the wide one, as wide as the form and never wider
   than 320px: 320px at desktop, the form's whole width on a phone. The logo
   guide sets no clear space, so it is the card's 40px on three sides and 24px
   under it, above the heading. */
.uc-login-wrap { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px; background: linear-gradient(135deg, var(--sfaf-black), var(--sfaf-darkgray)); }
.uc-login-card { background: var(--p-panel); border-radius: 16px; padding: 40px; width: 400px; max-width: 100%; box-sizing: border-box; box-shadow: var(--p-shadow-raised); text-align: center; }
.uc-login-brand { margin: 0 0 24px; }
.uc-login-brand .uc-login-logo { display: block; width: 100%; max-width: 320px; height: auto; margin: 0 auto; }
.uc-login-card h1 { font-size: 22px; margin-bottom: 4px; }
.uc-login-sub { color: var(--p-muted); margin: 0 0 24px; }
.uc-login-form { display: flex; flex-direction: column; gap: 14px; text-align: left; }
.uc-login-form label { font-size: 13px; font-weight: 600; display: flex; flex-direction: column; gap: 6px; }
/* Nothing about the box, only about the screen: a login field is the standard
   field and gets it from the baseline. It kept a 15px face and the decorative
   hairline as its boundary until 3.64.0, which is why the sign-in box read
   fainter than every field behind it. */
.uc-login-form input[type=text], .uc-login-form input[type=password] { width: 100%; }
.uc-login-remember { flex-direction: row !important; align-items: flex-start; gap: 8px; font-weight: 500 !important; }
.uc-login-error { background: var(--p-error-tint); color: var(--p-error-ink); padding: 10px 14px; border-radius: 8px; font-size: 14px; margin-bottom: 16px; }
.uc-login-card .uc-login-notice { margin: 0 0 16px; text-align: left; }
.uc-login-aside { margin: 16px 0 0; font-size: 13px; }
.uc-login-aside a { color: var(--uc-accent-text); font-weight: 600; }

/* ---------------------------------------------------------------------------
   THE SIDEBAR. DARK, AND MEASURED ON THE DARK.

   THIS IS THE OPPOSITE CASE FROM EVERY OTHER SURFACE IN THIS FILE, and getting
   it wrong in the obvious way would have been easy. --uc-accent-text (#0E7680)
   exists because brand teal #16BECF is 2.26:1 on white and cannot carry text
   there. On #373433 the arithmetic runs the other way: #0E7680 measures 2.30:1
   and is unreadable, and BRAND TEAL AT FULL VALUE IS THE CORRECT CHOICE. So
   the darkened teal is banned here exactly as brand teal is banned on white.

   NONE OF WHICH WAS ON SCREEN. Every value in the table below was correct and
   none of it applied: `.uc-portal a` at (0,1,1) outranked `.uc-nav-item` at
   (0,1,0), so the nav rendered in exactly the #0E7680 this note calls
   unreadable, at 2.30:1, and the icons with it because they are currentColor.
   The rule that says #D1D3D4 has been here since 3.16.0 and never won once.
   See the :where() note at the top of this file for the fix and for the eight
   other anchors it was doing the same thing to.

   EVERY PAIRING ON THIS BACKGROUND, MEASURED. Floors: 4.5:1 where there is
   text, 3:1 for anything that is only a shape.

     Dark Gray  #373433   the background, relative luminance 0.0351
     Light Gray #D1D3D4   inactive label + icon .................. 8.22:1  AAA
     White      #FFFFFF   hover label + icon, on #43403F ......... 10.28:1  AAA
     White      #FFFFFF   ACTIVE label 14/600, on the tint ....... 10.47:1  AAA
     Brand teal #16BECF   ACTIVE icon, on the tint (icon, 3:1) .... 4.64:1  ok
     Brand teal #16BECF   ACTIVE bar vs the tint (shape, 3:1) ..... 4.64:1  ok
     Brand teal #16BECF   ACTIVE bar vs the bare bg (shape, 3:1) .. 5.47:1  ok
     Dark Gray  #373433   on the yellow Pending badge ............. 8.92:1  AAA
     Yellow     #FFD900   the badge itself, as a shape on the bg .. 8.92:1
     White      #FFFFFF   brand text, footer name ................ 12.34:1  AAA
     #9EA1A3              the footer role label ................... 4.75:1  AA
     Light Gray #D1D3D4   the footer Sign out link ................ 8.22:1  AAA

   THE ACTIVE TINT IS 10 PERCENT, NOT 15, AND IT NO LONGER CARRIES ANYTHING.
   Teal at 15% over #373433 flattens to #32494A, and brand teal on that is
   4.253:1, under the 4.5:1 AA floor for a 14px semibold nav label. At 10% it
   flattens to #344243 and the same teal measures 4.638:1. That constraint is
   what made "more tint" a dead end, and it is why the active state is now
   carried by a bar and a white label instead: with the label white at 10.47:1
   the tint has no contrast job left, so the ceiling stopped mattering rather
   than being raised. The value stays pre-flattened, for the same reason as
   --uc-band: a translucent fill over an unknown backdrop cannot be
   contrast-checked and a flat colour can.

   NO COLLAPSE-TO-ICONS. A 64px rail of glyphs is a memory test. The sidebar is
   240px or it is the off-canvas drawer below 720px, and nothing in between.
   ------------------------------------------------------------------------- */
.uc-portal-layout { display: flex; min-height: 100vh; }
.uc-portal-sidebar { width: 240px; background: var(--p-sidebar); color: var(--p-sidebar-text);
    display: flex; flex-direction: column; flex-shrink: 0; position: sticky; top: 0; height: 100vh; }
/* THE STACKED LOGO, STRAIGHT ON THE SIDEBAR (3.110.0). The file is
   transparent, so it sits on --p-sidebar with 12px of padding all round, as
   wide as the sidebar's 200px of content, and "Calendar Admin" 10px under it.
   3.109.0 put it on a white tile, which Mark took away. */
.uc-portal-brand { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; padding: 20px;
    border-bottom: 1px solid rgba(255,255,255,0.10); }
.uc-portal-logo-wrap { display: block; box-sizing: border-box; width: 100%; padding: 12px; }
.uc-portal-logo-wrap .uc-portal-logo { display: block; width: 100%; height: auto; }
.uc-portal-brandtext { font-weight: 700; color: #fff; font-size: 15px; letter-spacing: -0.01em; }

.uc-portal-nav { padding: 12px 10px; flex: 1; min-height: 0; overflow-y: auto; }
.uc-nav-item { position: relative; display: flex; align-items: center; gap: 12px;
    padding: 10px 12px; margin-bottom: 2px; border-radius: 9px;
    color: var(--p-sidebar-text); font-weight: 500; font-size: 14px;
    transition: background-color .15s ease, color .15s ease; }
.uc-portal .uc-nav-item:hover { background: rgba(255,255,255,0.06); color: #fff; text-decoration: none; }
.uc-nav-item:focus-visible { outline: 2px solid var(--sfaf-teal); outline-offset: -2px; }

/* ---------------------------------------------------------------------------
   THE ACTIVE ROW: A BAR, A WHITE LABEL AND A TEAL ICON. NO MORE TINT.

   The previous treatment made the whole signal out of colour: teal label on a
   10% teal tint. That is the version that could not be pushed any further,
   because 10% is the ceiling documented above: at 15% the tint flattens to
   #32494A and teal on it is 4.253:1, under the AA floor for a 14px semibold
   label. The way out is not more tint. It is to stop asking colour to do the
   whole job.

   So the signal is now three things that do not compete for the same contrast
   budget:

     POSITION  a 4px solid brand teal bar down the row's left edge, full
               height. 5.47:1 against the bare sidebar and 4.64:1 against the
               row's own tint, so it reads as a shape either way (3:1 applies).
     WEIGHT    the label goes WHITE at 600. 10.47:1 on the tint, against the
               8.22:1 an inactive label gets, so active is the brighter of the
               two rather than merely a different hue from it.
     HUE       the icon keeps brand teal, 4.64:1 on the tint. It is an icon,
               so 3:1 applies and it clears it comfortably.

   THE TINT IS KEPT, at the same 10%. It has no contrast job left now that the
   label is white, but it is what makes the row read as one block behind the
   bar rather than a bar with some text next to it. The value stays
   pre-flattened for the reason given above.

   THE LEFT CORNERS GO SQUARE WHEN ACTIVE. A full-height bar against a 9px
   rounded corner is either a lozenge or a sliver; squaring that one edge is
   what lets the bar be a clean rectangle flush against the row.

   THE ICON DECLARES ITS OWN COLOUR IN THIS ONE STATE ONLY. Everywhere else it
   is still color: inherit, so inactive and hover cannot drift from the label
   beside them; active is the state where they are deliberately different, and
   the rule says so rather than leaving it to be discovered.
   ------------------------------------------------------------------------- */
.uc-portal .uc-nav-item.active {
    background: #344243; color: #fff; font-weight: 600;
    border-radius: 0 9px 9px 0;
}
.uc-portal .uc-nav-item.active::before {
    content: ""; position: absolute; left: 0; top: 0; bottom: 0;
    width: 4px; background: var(--sfaf-teal);
}
.uc-portal .uc-nav-item.active:hover { background: #344243; color: #fff; }
.uc-portal .uc-nav-item.active .uc-nav-icon { color: var(--sfaf-teal); }

/* The icon takes the row's colour rather than declaring its own, so the
   inactive and hover states cannot drift apart from the label beside them.
   Active is the one exception, and it is stated above. */
.uc-nav-icon { display: inline-flex; align-items: center; justify-content: center;
    width: 20px; height: 20px; flex: 0 0 auto; color: inherit; }
.uc-nav-label { flex: 1 1 auto; min-width: 0; }

/* THE ONE YELLOW THING IN THE SIDEBAR. Same discipline as the primary button:
   yellow means "act on this", so it appears once, on the queue. */
.uc-nav-badge { flex: 0 0 auto; min-width: 22px; padding: 1px 7px; border-radius: 99px;
    background: var(--uc-primary); color: var(--sfaf-darkgray);
    font-size: 12px; font-weight: 700; line-height: 1.5; text-align: center; }

/* ---------- Sidebar footer: who is signed in ---------- */
.uc-portal-foot { padding: 14px 14px 16px; border-top: 1px solid rgba(255,255,255,0.10);
    display: flex; flex-direction: column; gap: 14px; }
.uc-portal-me { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.uc-portal-me-name { font-size: 13.5px; font-weight: 600; color: #fff;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uc-portal-me-role { font-size: 11px; font-weight: 600; letter-spacing: 0.06em;
    text-transform: uppercase; color: #9EA1A3; }
.uc-portal-signout { margin-top: 4px; font-size: 12px; font-weight: 600; align-self: flex-start; }
/* .uc-portal a is (0,1,1) and would paint this the page's link teal, which is
   the colour that fails on this background. Two classes beat it. */
.uc-portal .uc-portal-signout { color: var(--p-sidebar-text); }
.uc-portal .uc-portal-signout:hover { color: #fff; }
.uc-portal-signout:focus-visible { outline: 2px solid var(--sfaf-teal); outline-offset: 2px; border-radius: 4px; }

/* ---------------------------------------------------------------------------
   WEGLOT'S LANGUAGE DROPDOWN, HIDDEN ON THESE SCREENS AND ONLY ON THESE.

   HIDING, NOT DISABLING. Weglot 5.4 is a separate plugin and its switcher is
   appended after </html>, which every browser then reparents into <body>, so
   it lands inside body.uc-portal and floats over the sidebar. It is not ours
   to remove and nothing here touches how Weglot runs: this is display: none on
   our own screens, and every public page keeps its switcher exactly as it is.

   THIS IS ALSO WHAT 3.16.0 SHOULD HAVE DONE. That release read "tidy the
   English/Espanol control" as a reason to build a language toggle the plugin
   had never had. The control was always Weglot's.

   The attribute and class list is Weglot's own switcher markup. The
   [class*="weglot"] catch is deliberate and safe: no class in this plugin
   contains that string, so it can only ever match theirs, and it survives them
   renaming a wrapper.
   ------------------------------------------------------------------------- */
body.uc-portal aside.country-selector,
body.uc-portal .country-selector,
body.uc-portal .weglot-container,
body.uc-portal .wg-drop,
body.uc-portal .wgcurrent,
body.uc-portal #weglot_here,
body.uc-portal [class*="weglot"],
body.uc-portal [id*="weglot"],
body.uc-portal [data-wg-hidden] { display: none !important; }

.uc-portal-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.uc-portal-topbar { display: flex; align-items: center; justify-content: space-between; padding: 14px 28px; background: var(--p-panel); border-bottom: 1px solid var(--p-border); position: sticky; top: 0; z-index: 20; }
.uc-portal-menu-btn { display: none; background: none; border: none; font-size: 22px; cursor: pointer; }
/* ONE SIGN-OUT (3.107.0). Log out left this bar, which then held only the menu
   button, and that shows only below 720px; so the bar does too. */
@media (min-width: 721px) {
    .uc-portal-topbar { display: none; }
}
.uc-portal-content { padding: 28px; max-width: 1100px; width: 100%; }

.uc-page-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 22px; gap: 16px; flex-wrap: wrap; }

/* ---------------------------------------------------------------------------
   ALL EVENTS / MY EVENTS, and every other PICK ONE OF THESE.

   THE SEGMENTED CONTROL IS DECLARED HERE ONCE (3.64.0) and worn by both of the
   places that need it. It was written out twice, 1500 lines apart and value for
   value identical: this, built from two real links, and the recurrence
   control's Repeats switch, built from radios. Two copies of one control is
   how the two come to disagree, and it is the same fault as the fourteen
   separate declarations of a text field.

   The elements stay different on purpose. All events / My events are LINKS,
   because each is a URL that can be bookmarked and shared and that survives
   paging and sorting. Repeats is a group of RADIOS, because it is a value on a
   form. Nothing about the two shapes differs, so nothing about the two
   declarations does either: each selector keeps its own specificity in the
   list, (0,2,0) for the anchor so it beats `.uc-portal a`, and (0,1,1) for the
   span the radio paints.

   AND IT IS NOT A ROW OF BUTTONS, which is the distinction the whole standard
   turns on. Pressing a segment picks a value; it does not do a thing. So it
   wears one continuous boundary with seams inside it rather than four separate
   edges, and the chosen one FILLS: the darkened teal with white on it, 5.35:1.
   Brand teal would have been 2.26:1 and is never used behind text.
   ------------------------------------------------------------------------- */
.uc-scope-switch,
.uc-seg { display: inline-flex; flex-wrap: wrap; border: 1px solid var(--p-border-strong);
    border-radius: 9px; overflow: hidden; }
.uc-scope-switch { align-self: center; }
.uc-seg { align-self: flex-start; }

.uc-portal .uc-scope-opt,
.uc-seg-opt span { display: block; padding: 8px 16px; font-size: 13px; font-weight: 600;
    color: var(--p-text); background: var(--p-control-face);
    border-left: 1px solid var(--p-border);
    text-decoration: none; white-space: nowrap; cursor: pointer; user-select: none; }
.uc-portal .uc-scope-opt:first-child,
.uc-seg-opt:first-child span { border-left: 0; }
.uc-portal .uc-scope-opt:hover,
.uc-seg-opt input:hover + span { background: var(--uc-band); color: var(--p-text); text-decoration: none; }
.uc-portal .uc-scope-opt.is-on,
.uc-seg-opt input:checked + span { background: var(--uc-accent-text); color: #fff; }
.uc-portal .uc-scope-opt:focus-visible,
.uc-seg-opt input:focus-visible + span { outline: 2px solid var(--uc-accent-text); outline-offset: -2px; }
.uc-scope-switch + .uc-view-hint { margin-top: 14px; }

/* The read-only table other people's events are drawn in. No actions column,
   no registration column, nothing clickable: see public_events_table(). */
.uc-table-public td { vertical-align: top; }

/* ---------- Flash ---------- */
.uc-flash { background: #d1fae5; color: #065f46; padding: 12px 16px; border-radius: 10px; margin-bottom: 18px; font-weight: 600; }
.uc-flash-info { background: #dbeafe; color: #1e40af; }

/* ---------------------------------------------------------------------------
   EVERY CONTROL, INCLUDING THE ONES NOBODY HAS THOUGHT OF YET.

   THE FAULT THIS FIXES IS STRUCTURAL, not a list of misses. Until now a
   control was styled because it happened to sit inside a wrapper that styled
   it: .uc-field, .uc-filters-bar, .uc-login-form, .uc-picker-filter and a
   dozen others. Every one of those is a rule about a CONTAINER, so a control
   rendered outside all of them fell through to the browser's own chrome, and
   nothing said so. That is why the opt-ins search box was a raw Chrome input
   for four releases while the identical search box on Registrations was not:
   one form carried .uc-filters-bar and the other carried .uc-inline-form,
   which styles a `select` and nothing else. Sweeping by eye finds the ones
   somebody happens to open; it cannot find the ones nobody has opened yet.

   SO THE BASELINE IS NOW A PROPERTY OF BEING A CONTROL IN THIS PORTAL, and the
   wrappers only refine it. A new field in a new card is styled before anybody
   writes a rule for it.

   :where() IS LOad-BEARING, NOT TIDINESS. It contributes ZERO specificity, so
   this whole block scores (0,0,0) and loses to literally every class rule in
   this file. Written as `.uc-portal input` it would score (0,1,1) and would
   OUTRANK .uc-btn, .uc-link-danger, .uc-seg-opt input and the rest, which is
   precisely the specificity accident documented at .uc-btn-source below, where
   `.uc-portal a` silently repainted a button. A fallback must never be able to
   win an argument.

   WHAT IS DELIBERATELY NOT HERE: checkbox and radio, which get sizing and an
   accent instead of a box (a box is not a text field, see .uc-field); submit
   and button inputs, which are buttons; and file, which the browser draws its
   own way and is styled separately below.
   ------------------------------------------------------------------------- */
:where(.uc-portal) :where(
    input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="file"]):not([type="hidden"]):not([type="range"]):not([type="color"]),
    select,
    textarea
) {
    padding: 9px 12px;
    border: 1px solid var(--p-border-strong);
    border-radius: 8px;
    /* background-color, never the shorthand: `background` resets
       background-image, which is what draws the chevron on a select.
       WHITE IS SAID OUT LOUD because it is the statement, not the default:
       in this portal white fill plus a boundary means you type in this or it
       opens, and the button face beside it is Light Gray. See --p-btn-face. */
    background-color: var(--p-control-face);
    color: var(--p-text);
    font-family: inherit;
    font-size: 14px;
    font-weight: 400;
    line-height: 1.4;
    max-width: 100%;
}
:where(.uc-portal) :where(input, select, textarea):focus-visible {
    outline: none;
    border-color: var(--uc-accent-text);
    box-shadow: 0 0 0 3px rgba(22,190,207,0.18);
}
:where(.uc-portal) :where(textarea) { min-height: 72px; resize: vertical; }

/* ---------------------------------------------------------------------------
   THE SAME CHEVRON caladmin AND wp-admin, drawn by us in both.

   The portal was not showing the fault the embed generator was, because
   nothing here sets appearance: none, so the platform still drew its own
   arrow. That is a working control by luck rather than by decision: the box,
   the border and the radius are ours and the one part that says "this opens"
   was the operating system's, which is why the two surfaces looked like
   different controls side by side. Both draw the same mark now, and the
   `background` shorthand in the baseline above cannot delete it, because it is
   set after it on background-image.
   ------------------------------------------------------------------------- */
/* THE END CAP CAME WITH IT IN 3.64.0, and it is the public filter bar's
   answer rather than a second one. The chevron alone was not enough: a select
   and a text field were the same white box with the same boundary, and the
   only difference was a 16px glyph at the far right that reads as an icon
   inside the field rather than as part of the control. calendar.css draws a
   1px hairline just inside the right-hand end, which turns that end into a
   PART of the control, and that is the thing a text box does not have.

   HERE IT IS A SECOND BACKGROUND LAYER, NOT AN ELEMENT, and the difference
   between the two surfaces is why. On the public calendar the affordance has
   to be in the markup, because a host stylesheet saying `background: none`
   would delete it and the failure would be invisible. Nothing hosts
   /caladmin: this file is the only stylesheet on the page, and the rule that
   would delete it is the `background` shorthand, which is banned in the
   baseline above and checked by .claude/control-standard-audit.php. Two
   layers means the renderers do not have to wrap 21 bare selects in a span.

   Layer order is cap then chevron, both painted over the fill. */
:where(.uc-portal) :where(select) {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    padding-right: 38px;
    background-image:
        linear-gradient(var(--p-border), var(--p-border)),
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%230E7680' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat, no-repeat;
    background-position: right 33px center, right 10px center;
    background-size: 1px 60%, 16px 16px;
}
/* Open, and pointing the way it opens. `:focus` rather than `:focus-visible`
   deliberately: the native menu is up for exactly as long as the select has
   focus however it was reached, including by mouse, which is the state this
   describes. The same reasoning as `:focus-within` on the public bar. */
:where(.uc-portal) :where(select):focus {
    background-image:
        linear-gradient(var(--p-border), var(--p-border)),
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%230E7680' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m18 15-6-6-6 6'/%3E%3C/svg%3E");
}
/* A list box has no menu to open, so a chevron on it would be a lie, and an
   end cap with nothing behind it is the same lie in a quieter voice. */
:where(.uc-portal) :where(select[multiple], select[size]:not([size="1"])) {
    appearance: auto; -webkit-appearance: auto; background-image: none; padding-right: 12px;
}

/* A BOX IS SIZED AND TINTED, NEVER BOXED. accent-color is the one property
   that recolors a native checkbox or radio without replacing it, so the
   control a keyboard and a screen reader get is still the platform's own. */
:where(.uc-portal) :where(input[type="checkbox"], input[type="radio"]) {
    width: 16px; height: 16px; flex: 0 0 auto;
    accent-color: var(--uc-accent-text); cursor: pointer;
}
:where(.uc-portal) :where(input[type="checkbox"], input[type="radio"]):focus-visible {
    outline: 2px solid var(--uc-accent-text); outline-offset: 2px;
}

/* DATE, TIME AND FILE ARE PARTLY THE BROWSER'S, AND THAT IS NOT A MISS.
   The box, its border, its radius, its font and its focus ring are ours and
   are set above. What is NOT ours, in any browser, is the picker chrome: the
   calendar popover a date field opens, the spinner a time field draws, the
   "Choose file" button and the filename beside it. Those are UA shadow DOM
   with no standard hook. The list of every control in that category is in the
   3.16.0 changelog rather than being chased here. What this rule does add is
   the one thing that IS reachable: the indicator glyph, tinted to the brand.  */
:where(.uc-portal) :where(input[type="date"], input[type="time"], input[type="datetime-local"], input[type="month"], input[type="week"])::-webkit-calendar-picker-indicator {
    cursor: pointer; opacity: 0.65;
}
:where(.uc-portal) :where(input[type="date"], input[type="time"])::-webkit-calendar-picker-indicator:hover { opacity: 1; }
:where(.uc-portal) :where(input[type="file"]) {
    font-family: inherit; font-size: 13px; color: var(--p-text);
    padding: 8px; border: 1px dashed var(--p-border-strong); border-radius: 8px;
    background: var(--p-bg); max-width: 100%;
}
/* The one part of a file input that IS a button gets the button face, so
   "Choose file" reads as pressable next to every other button on the form. */
:where(.uc-portal) :where(input[type="file"])::file-selector-button {
    margin-right: 10px; padding: 6px 12px; border: 1px solid var(--p-border-strong);
    border-radius: 7px; background: var(--p-btn-face); color: var(--p-text);
    font-family: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}

/* The same fallback for buttons. Zero specificity again, so .uc-btn,
   .uc-link-danger, .uc-link-ok, .uc-picker-tab, .uc-help-btn and
   every other button class in this file override it completely. This only ever
   catches a button that carries no class of its own. */
/* NO `display` AND NO `gap` HERE, deliberately. Several button classes in this
   file position themselves (.uc-help-btn is a 16px circle, .uc-chip-remove sits
   inside a pill) and set no display of their own, so a display in the fallback would
   silently change them even though it loses every other property. A fallback
   should supply a surface, not a layout. */
:where(.uc-portal) :where(button, input[type="submit"], input[type="button"], input[type="reset"]) {
    padding: 9px 16px; border-radius: 8px;
    border: 1px solid var(--p-border-strong); background: var(--p-btn-face); color: var(--p-text);
    font-family: inherit; font-size: 14px; font-weight: 600; line-height: 1.4; cursor: pointer;
}
:where(.uc-portal) :where(button, input[type="submit"]):focus-visible {
    outline: 2px solid var(--uc-accent-text); outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
   THE BUTTON VOCABULARY. FOUR WEIGHTS AND A QUIET FIFTH, AND NOTHING ELSE.

   A SECONDARY BUTTON HAS A SURFACE (3.64.0). It was a white box with a 1px
   --p-border-strong outline and an 8px radius, which is byte for byte what a
   text input was, so Choose Image, Add these questions, Add FAQ, Add category,
   Save Draft and Back all read as the same thing as the Title field beside
   them. An outline on white does not say "press me"; it says "there is an edge
   here". The fill is what says it, and the fill is brand Light Gray:

     PRIMARY      yellow #FFD900, ink #373433, 8.92:1. ONE per view.
     SECONDARY    Light Gray #D1D3D4, ink #373433, 8.22:1. The default.
     UTILITY      solid teal #0E7680, white ink, 5.35:1. "Go and get it again".
     DESTRUCTIVE  solid #c0392b, white ink, 5.44:1. Behind a disclosure.
     QUIET        no surface at all: .uc-action-link, .uc-link-danger,
                  .uc-link-ok. A verb in a row of verbs, never a box.

   The border stays. The fill is 1.50:1 against a white card, which is a
   visible surface and not a boundary, so the edge is still the thing clearing
   WCAG 1.4.11's 3:1 at 3.33:1. Two jobs, two declarations.

   HOVER MOVES THE FACE, not just the edge. The old hover changed border and
   text colour only, so on a white card the thing that moved was a hairline.
   ------------------------------------------------------------------------- */
.uc-btn,
.uc-form-links-open { display: inline-flex; align-items: center; gap: 6px; padding: 9px 16px; border-radius: 8px; border: 1px solid var(--p-border-strong); background: var(--p-btn-face); color: var(--p-text); font-size: 14px; font-weight: 600; cursor: pointer; transition: all 0.15s; font-family: inherit; }
.uc-btn:hover,
.uc-form-links-open:hover { background: var(--p-btn-face-hover); border-color: var(--uc-accent-text); color: var(--p-text); text-decoration: none; }
.uc-btn:focus-visible,
.uc-form-links-open:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: 2px; }
.uc-btn-primary,
.uc-form-links-open { background: var(--uc-primary); border-color: #E0BE00; color: var(--sfaf-darkgray); }
/* THE FILL IS NAMED IN THE HOVER TOO, and that is not redundancy. Until the
   secondary button had a face of its own, `.uc-btn:hover` set no background
   and a yellow button simply kept its own through the hover. It sets one now,
   so a rule that only darkens with a filter would hover from yellow to grey.
   Same shape as the 3.39.0 fault: a state rule inheriting a fill from the
   resting rule, which holds right up until the resting rule changes. */
.uc-btn-primary:hover,
.uc-form-links-open:hover { background: var(--uc-primary); filter: brightness(0.94); color: var(--sfaf-darkgray); border-color: #E0BE00; }
/* ---------------------------------------------------------------------------
   THE UTILITY BUTTON: "go and get it again".

   A THIRD WEIGHT, AND IT DOES NOT COMPETE WITH YELLOW. Fetch updates fills the
   pending queue; it is not what the queue is for. Publishing and dismissing
   are, and those are the yellow and the links on the rows. A plain white
   outline button said nothing about which of the two it was, which is why this
   one was indistinguishable from "Export CSV" on a screen where they do very
   different things.

   MEASURED. Solid --uc-accent-text #0E7680 with a white label is 5.35:1, and
   the fill against the page background #F5F6F7 is 4.95:1, well past the 3:1
   WCAG 1.4.11 asks of a control's own boundary, so the button reads as a
   button without a separate border. Yellow stays the single primary.
   ------------------------------------------------------------------------- */
.uc-btn-utility { background: var(--uc-accent-text); border-color: var(--uc-accent-text); color: #fff; }
.uc-btn-utility:hover { background: #0B5F67; border-color: #0B5F67; color: #fff; }
.uc-portal a.uc-btn-utility { color: #fff; }
.uc-portal a.uc-btn-utility:hover { color: #fff; }
/* The mark turns when the fetch is running, so the button says "working"
   without losing its label. portal.js sets [disabled] for the duration. */
.uc-btn-utility .sfaf-icon { transition: transform .25s ease; }
.uc-btn-utility:hover .sfaf-icon { transform: rotate(-45deg); }
.uc-btn-utility[disabled] .sfaf-icon { animation: uc-spin 1.1s linear infinite; }
@media (prefers-reduced-motion: reduce) {
    .uc-btn-utility .sfaf-icon, .uc-btn-utility:hover .sfaf-icon { transition: none; transform: none; }
    .uc-btn-utility[disabled] .sfaf-icon { animation-duration: 2.4s; }
}

.uc-btn-block { width: 100%; justify-content: center; padding: 12px; font-size: 15px; }
.uc-btn-sm { padding: 6px 12px; font-size: 13px; }
.uc-link-danger { background: none; border: none; color: var(--p-danger-text); cursor: pointer; font-size: 13px; padding: 0; font-weight: 600; }
/* NO SURFACE IN ANY STATE. Both of these are worn alongside .uc-btn in a few
   places, and since 3.64.0 `.uc-btn:hover` names a fill. A quiet action that
   inherited "no fill" through the hover would grow a grey box on the way past.
   The pair is declared together, which is the 3.39.0 rule. */
.uc-link-danger:hover { background: none; text-decoration: underline; }
.uc-link-ok { background: none; border: none; color: var(--p-green); cursor: pointer; font-size: 13px; padding: 0; font-weight: 600; }
.uc-link-ok:hover { background: none; text-decoration: underline; }

/* ---------- Stats ---------- */
.uc-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 24px; }
.uc-stat { background: var(--p-panel); border: 1px solid var(--p-border); border-radius: 12px; padding: 20px; text-align: center; }
.uc-stat-num { display: block; font-size: 32px; font-weight: 800; color: var(--uc-accent-text); }
.uc-stat-label { font-size: 13px; color: var(--p-muted); }
.uc-stat-accent .uc-stat-num { color: var(--uc-accent-text); }
/* To review (3.111.0) is a link to the reviewer's Pending screen, drawn as a stat. */
a.uc-stat { display: block; color: inherit; text-decoration: none; }
a.uc-stat:hover, a.uc-stat:focus-visible { border-color: var(--uc-accent-text); }

/* ---------- Cards / tables ---------- */
/* ---------------------------------------------------------------------------
   THE CARD: A TEAL EDGE AND A TINTED HEADER BAND.

   ONE accent, used the same way everywhere, rather than a colour per card.
   Colouring cards individually is exactly the kaleidoscope the guide warns
   against, and it would also collide with the category colours, which are a
   different system with real meaning behind each hue.

   The 3px edge is decoration and is deliberately brand teal #16BECF, which
   measures 2.26:1 against white. That is below the 3:1 that WCAG 1.4.11 asks
   of non-text content, and it is fine here because the edge carries no
   information: the card is identified by its heading and its own border, and
   removing the stripe entirely would lose nothing but the brand. Anything
   that DOES carry information uses --uc-accent-text, which is measured.
   ------------------------------------------------------------------------- */
/* NO ACCENT EDGE. Until 3.38.0 every card carried a 3px teal left border and
   an asymmetric 4/12/12/4 radius. An accent every card has distinguishes
   nothing, and the curved coloured edge is the most recognisable tell of
   generated UI. The card is a white panel with a hairline. Where a coloured
   edge survives in this plugin it is because the colour IS the fact: the
   category band on an event page, and the amber locator on a field that
   still needs filling in. */
.uc-card { background: var(--p-panel); border: 1px solid var(--p-border);
    border-radius: 12px; padding: 20px; margin-bottom: 20px; overflow: hidden; }
/* The band is full bleed, pulled out to the padding edge rather than achieved
   by unpadding the card and re-padding every child. */
.uc-card-head { display: flex; align-items: center; justify-content: space-between;
    gap: 12px; flex-wrap: wrap; margin: -20px -20px 16px; padding: 11px 20px;
    background: var(--uc-band); border-bottom: 1px solid var(--p-border); }
.uc-card-head h2, .uc-card-head h3 { font-size: 14px; }

/* ---------------------------------------------------------------------------
   A HEADING AT THE TOP OF A CARD **IS** THE CARD'S HEADING, whether or not
   somebody wrapped it in a .uc-card-head.

   THE 3.14.0 TREATMENT WAS BEING APPLIED PER SCREEN, WHICH IS WHY IT DRIFTED.
   The band was a thing you had to remember to add, so on the series screen the
   Schedule card had one and the details card immediately above it did not, and
   the "Remove this series" card had a bare <h3> that took the generic subhead
   style instead. Sixteen of thirty-nine cards in caladmin were in that state.
   That is the same structural fault as the 3.16.0 control sweep: a rule about
   a CONTAINER somebody has to opt into, rather than a rule about what a thing
   is.

   So the band now follows from being the first element of a card. A card
   cannot be built without it, and a heading cannot be styled two ways
   depending on which screen it is on. .uc-card-head is still there and still
   preferred, because it is the only one that can also hold a count or a
   status on the right of the band; this is what happens when it is absent.
   ------------------------------------------------------------------------- */
.uc-card > h2:first-child,
.uc-card > h3:first-child {
    font-family: var(--uc-font-heading);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
    font-size: 14px;
    color: var(--sfaf-darkgray);
    margin: -20px -20px 16px;
    padding: 11px 20px;
    background: var(--uc-band);
    border-bottom: 1px solid var(--p-border);
}
/* THE SAME RULE FOR THE OTHER KIND OF CARD.

   .uc-card got this because sixteen of thirty-nine cards had a bare heading and
   no band. .uc-bento-card did not, and has only escaped the same fate because
   every one of its headings happens to carry .uc-bento-title today. A heading at
   the top of a card IS that card's heading, and should not depend on somebody
   remembering a class, which is the argument DESIGN.md already makes. */
.uc-bento-card > h2:first-child,
.uc-bento-card > h3:first-child {
    font-family: var(--uc-font-heading);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
    font-size: 14px;
    color: var(--sfaf-darkgray);
    margin: -18px -18px 16px;
    padding: 10px 18px;
    background: var(--uc-band);
    border-bottom: 1px solid var(--p-border);
}

/* THE TREATMENT IS THE HEADING'S OWN TEXT, AND NOTHING THAT SITS INSIDE IT
   (3.105.0).

   text-transform and letter-spacing INHERIT, so every rule above that sets
   them on a heading also set them on whatever was put inside that heading.
   The series card and the team card carry their help button on the title,
   and the help panel opens inside the title, so a paragraph of help text was
   rendering in tracked capitals. caps-sweep-live.php reads every screen for
   that in Chrome, hidden panels included.

   Fixed here, at the treatment, and not on the panel: anything that is not
   the heading's own words (help, a hint, a label, a control, a sentence) is
   given its case and spacing back wherever a card heading holds it. :where()
   on both sides keeps this at zero specificity, which is all it needs: a
   declared value beats an inherited one at any weight, and this must never
   outrank a component that sets its own. */
:where(.uc-heading, .uc-card-head h2, .uc-card-head h3, .uc-bento-title,
       .uc-card > h2:first-child, .uc-card > h3:first-child,
       .uc-bento-card > h2:first-child, .uc-bento-card > h3:first-child)
    :where(.uc-help-body, .uc-hint, .uc-muted, .uc-field-label, p, label, small, input, select, textarea, button) {
    text-transform: none;
    letter-spacing: normal;
}

.uc-empty { color: var(--p-muted); padding: 24px; text-align: center; }

.uc-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.uc-table th { text-align: left; font-size: 12px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--p-muted); padding: 10px 12px; border-bottom: 2px solid var(--p-border); }
.uc-table td { padding: 12px; border-bottom: 1px solid var(--p-border); vertical-align: middle; }
.uc-table tr:last-child td { border-bottom: none; }
.uc-tlink { font-weight: 600; }
.uc-muted { color: var(--p-muted); }
.uc-col-actions { white-space: nowrap; }
.uc-row-actions { white-space: nowrap; }
.uc-actions { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.uc-actions form { display: inline; margin: 0; line-height: 1; }

/* ---------------------------------------------------------------------------
   THE EVENTS LIST'S ACTIONS ARE ICONS (3.73.0).

   WHAT WAS THERE. Edit, Duplicate and Remove as three text links, one weight,
   two similar colours, across 259 rows. The common action did not stand out and
   the destructive one did not either, and the column was wide enough that some
   rows wrapped and some did not, so the edge of the table looked broken.

   NEVER WRAPS, BY CONSTRUCTION. `flex-wrap: nowrap` and three fixed-width
   targets: the column's width is now the same on every row whatever the row
   holds, which is the half of the complaint that was about the table rather
   than about the controls.

   44px IS THE TOUCH TARGET and it is the reason for the padding rather than the
   glyph size. The icons are 17px; the box around them is what a finger has to
   hit. WCAG 2.5.5 asks for 44 and a phone is a real way to reach caladmin.

   SHAPE IS NEVER THE ONLY CARRIER. Each control has a `title` for a mouse and a
   `.uc-visually-hidden` name for a screen reader, and the destructive one has a
   colour on top of both. See the note in the events table for what a touch
   device gets, which is the clipped name, not the title.
   ------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
   BULK ADD A CATEGORY (3.73.0).

   ABOVE THE TABLE, NOT BELOW IT. The ticks are in the rows and the control
   acts on them, so it reads top to bottom: choose a category, tick the rows,
   press. Below the table it would be found after the scrolling rather than
   before it, on a list that runs to 259 rows.

   IT IS NOT A CARD. A second panel above a table that is already inside one
   would be a box in a box; this is a row of controls on the card it belongs
   to, separated by the same hairline the table uses.
   ------------------------------------------------------------------------- */
.uc-bulk-cat {
    display: flex; align-items: flex-end; flex-wrap: wrap; gap: 12px;
    margin: 0 0 14px; padding: 0 0 14px;
    border-bottom: 1px solid var(--p-border);
}
.uc-bulk-cat-pick { flex: 0 1 320px; margin: 0; }
.uc-bulk-cat-go { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; padding-bottom: 2px; }
.uc-bulk-cat-go .uc-hint { margin: 0; }
.uc-bulk-cat button[disabled] { opacity: 0.55; cursor: not-allowed; }

/* The tick column. Narrow, and the box centred in it so a column of them
   reads as a column rather than as a ragged left edge.

   IT IS WIDER NOW BECAUSE IT CARRIES A SECOND THING (3.79.0). A draft the
   bulk publish may not touch says so under its box, in the column where
   somebody is already deciding what to tick. 34px fitted a checkbox and
   nothing else. */
.uc-col-tick { width: 92px; text-align: center; padding-right: 0; }
.uc-col-tick input[type="checkbox"] { margin: 0; width: auto; }
.uc-tick-all { display: inline-flex; margin: 0; }

/* WHY A TICKED ROW MIGHT STILL NOT PUBLISH.

   THE BOX STAYS AND THE REASON SITS UNDER IT, which is the opposite of the
   schedule screen, where an ineligible row gets no box at all. It has to be:
   this tick is shared with the bulk category control, which reaches every row
   the viewer can edit, past events and imports included. Taking the box away
   to protect the publish button would take the category control's reach with
   it, and that reach is a 3.73.0 guarantee.

   SO IT IS TYPED DOWN, NOT COLOURED. It is a footnote on a row, not a warning
   and not a status: the pills two columns over are what say what the event IS.
   Small, muted, and it wraps rather than widening the column further. */
.uc-tick-block {
    display: block;
    margin-top: 3px;
    font-size: 10px; line-height: 1.25;
    color: var(--p-muted, #6B6764);
    text-align: center;
    cursor: help;
}

/* The publish button sits on its own line under the category row, because the
   two are different acts and one of them is public. */
.uc-bulk-publish { flex: 1 0 100%; }

.uc-actions-icons { gap: 2px; flex-wrap: nowrap; }
.uc-actions-icons form { display: inline-flex; }

.uc-icon-action {
    position: relative;
    display: inline-flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; padding: 0;
    border: 1px solid transparent; border-radius: 8px;
    background: none; color: var(--p-muted, #6B6764);
    cursor: pointer; line-height: 0;
}
/* THE HIT AREA IS LARGER THAN THE BOX THAT IS DRAWN, so three icons can sit two
   pixels apart and still be 44px to a finger. Centred on the control rather
   than anchored to its corner, or it would overhang one side by ten pixels and
   the leftmost icon would steal taps from the table's edge. */
.uc-icon-action::before {
    content: "";
    position: absolute; left: 50%; top: 50%;
    transform: translate(-50%, -50%);
    width: 44px; height: 44px;
}

.uc-icon-action:hover {
    color: var(--p-text);
    background: var(--p-surface-2, #f6f7f8);
    border-color: var(--p-border);
    text-decoration: none;
}
.uc-icon-action:focus-visible {
    outline: 2px solid var(--uc-accent-text); outline-offset: 1px;
}

/* THE DESTRUCTIVE ONE CARRIES ITS COLOUR AT REST, not only on hover, because a
   row of three identical grey glyphs is the thing this replaced. #c0392b on
   white is 5.44:1, which is the DESTRUCTIVE ink in the control standard. */
.uc-icon-action-danger { color: var(--p-danger-text); }
.uc-icon-action-danger:hover { color: #fff; background: var(--p-danger-text); border-color: var(--p-danger-text); }

/* CANCEL IS NOT A VARIANT OF REMOVE and does not take its red. It is
   reversible, it keeps the registrations, and it is the action offered when
   removing is refused. Ordinary action ink, and a different glyph. */
.uc-icon-action-cancel { color: var(--uc-accent-text); }
.uc-icon-action-cancel:hover { color: var(--uc-accent-text); background: var(--p-surface-2, #f6f7f8); border-color: var(--uc-accent-text); }

/* A STATE, NOT A CONTROL. No hover, no pointer, no focus ring: an imported
   event with registrations is removed at its source and there is nothing here
   to press. */
.uc-icon-action-locked { color: var(--p-muted, #6B6764); cursor: default; opacity: 0.75; }
.uc-icon-action-locked:hover { background: none; border-color: transparent; color: var(--p-muted, #6B6764); }
/* 14px, up from 13px. A row of actions is not helper text: Publish, Dismiss,
   Approve and Reject are the only things on this screen that DO anything, and
   they were being drawn one step below body size. Body size is the floor. */
.uc-actions .uc-action-link,
.uc-actions .uc-link-danger,
.uc-actions .uc-link-ok { font-size: 14px; font-weight: 600; line-height: 1; }

/* ---------------------------------------------------------------------------
   .uc-action-link ON A <button>.

   IT HAD NO RULE AT ALL, only the size and weight above, which say nothing
   about background or border. On an <a> that is fine, because .uc-portal a
   already supplies the colour. On a <button> it left the browser's own grey
   chrome, so Dismiss and Restore in the pending queue were native buttons
   sitting in a row of links, next to Publish which is .uc-link-ok and IS
   reset. Same class, two different renderings, decided by the element.

   One rule, both elements, and the button is now indistinguishable from the
   anchor beside it, which is the point of giving them the same class.
   ------------------------------------------------------------------------- */
.uc-portal .uc-action-link,
.uc-portal button.uc-action-link {
    display: inline; padding: 0; border: 0; background: none;
    color: var(--uc-accent-text); font-family: inherit; font-size: 14px;
    font-weight: 600; line-height: 1; text-decoration: none; cursor: pointer;
}
.uc-portal .uc-action-link:hover,
.uc-portal button.uc-action-link:hover { text-decoration: underline; }
.uc-portal .uc-action-link:focus-visible,
.uc-portal button.uc-action-link:focus-visible {
    outline: 2px solid var(--uc-accent-text); outline-offset: 2px; border-radius: 3px; }
/* Duplicate has to be a submit button, because it posts a nonce. This makes it
 * sit in the row exactly like the Edit link beside it. */
.uc-actions button.uc-action-btn { background: none; border: 0; padding: 0; cursor: pointer;
    font-family: inherit; color: var(--uc-accent-text); text-decoration: none; }
.uc-actions button.uc-action-btn:hover { text-decoration: underline; }

.uc-pill { display: inline-block; padding: 3px 10px; border-radius: 99px; font-size: 12px; font-weight: 600; background: #eef2f7; color: var(--p-muted); text-transform: capitalize; }
.uc-pill-publish { background: #d1fae5; color: #065f46; }
.uc-pill-pending { background: #fef3c7; color: #92400e; }
.uc-pill-draft { background: #e5e7eb; color: #374151; }
.uc-pill-confirmed { background: #d1fae5; color: #065f46; }

/* Amber, and sitting beside the status rather than replacing it: the event IS
 * a draft, and this says who made it one and why. Never capitalized away from
 * the words it was given, unlike the status pills. */
.uc-pill-removed { background: #fffbeb; color: #92400e; border: 1px solid #fcd34d;
    text-transform: none; margin-left: 5px; cursor: help; }

/* Private, beside the status rather than replacing it: a private event is still
 * published, and this says who can find it. Slate rather than a warning colour,
 * because being private is a choice somebody made and not a problem. Same
 * text-transform: none as the removed pill, so the word reads as the word the
 * editor's own control uses. */
.uc-pill-private { background: #eef2ff; color: #3730a3; border: 1px solid #c7d2fe;
    text-transform: none; margin-left: 5px; cursor: help; }

/* The address to send, on the editor's privacy control. Wraps, because a
 * 32-character token plus the site URL does not fit a form column and a
 * horizontally scrolling code element is one somebody copies half of. */
.uc-private-field .uc-private-link code { display: inline-block; max-width: 100%;
    word-break: break-all; font-size: 12px; padding: 2px 6px; border-radius: 4px;
    background: var(--p-bg); }

/* ---------- Views ----------
 * Which events are being looked at, asked before the refinements below it.
 * A row of links rather than a segmented control, because each one is a real
 * URL that can be bookmarked and shared.  */
.uc-view-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 10px;
    border-bottom: 1px solid var(--p-border); }
.uc-view-tab { padding: 8px 14px; font-size: 14px; font-weight: 600; color: var(--p-muted);
    text-decoration: none; border: 1px solid transparent; border-bottom: 0;
    border-radius: 8px 8px 0 0; margin-bottom: -1px; }
.uc-view-tab:hover { color: var(--uc-accent-text); background: var(--p-bg); }
.uc-view-tab-active { color: var(--p-text); background: #fff;
    border-color: var(--p-border); border-bottom: 1px solid #fff; }
.uc-view-tab:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: -2px; }
.uc-view-hint { margin: 0 0 14px; max-width: 70ch; }

/* ---------- Filters ---------- */
.uc-filters-bar { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 18px; }
/* LAYOUT ONLY. The box, the boundary and the face come from the baseline, so
   the search field on Registrations and the one on Opt-ins cannot render as
   two different controls again. */
.uc-filters-bar input[type=search] { flex: 1; min-width: 180px; }

/* ---------- Forms ---------- */
.uc-form-grid { display: grid; grid-template-columns: 1fr 300px; gap: 20px; }
.uc-form-main, .uc-form-side { display: flex; flex-direction: column; gap: 16px; }
.uc-field { display: flex; flex-direction: column; gap: 6px; font-size: 13px; font-weight: 600; color: var(--p-text); }
/* LAYOUT ONLY, SINCE 3.64.0. This rule used to declare the whole appearance of
   a field — padding, boundary, radius, size, face — at (0,1,1), and it was one
   of FOURTEEN rules in this file that did, nine of which handed the control the
   decorative hairline instead of a boundary. The appearance is the baseline's
   now and this says the one thing that is genuinely about being inside a
   labelled field: fill the column.

   ITS :focus RULE IS GONE AND IS NOT COMING BACK. It painted the focused
   border YELLOW, which is the one colour reserved for the single primary
   action on a screen, and it keyed on :focus rather than :focus-visible so a
   mouse click lit it too. Focus is teal, from the baseline, everywhere. */
.uc-field input, .uc-field select, .uc-field textarea { width: 100%; }
/* A BOX IS NOT A TEXT FIELD, and the rule above does not know that.
   `.uc-field input` gives every input inside a .uc-field wrapper width: 100%.
   The padding, border and background this also resets came from the same rule
   until 3.64.0 and now come from nowhere, because the baseline excludes
   checkbox and radio by name; they are kept because the damage they undo is
   what somebody adding a shorthand back here would reintroduce, and the reset
   costs nothing. Several wrappers are DIVS
   holding boxes rather than labels around one text input, so their checkboxes
   and radios were being drawn as full-width text fields: .uc-location-field,
   .uc-cat-field (the category list), .uc-fund-field (the fundraising toggle)
   and .uc-image-field ("Reset to series image").

   THIS IS WHAT DEFEATED THE 3.10.0 LOCATION FIX. That fix set
   `.uc-radio-row input[type="radio"] { flex: 0 0 auto }`, which does win on
   specificity, but flex-basis: auto defers to `width`, and it never declared
   one. So width: 100% still applied, the browser painted the radio glyph in
   the middle of a full-row box, and the label was squeezed to the right edge
   and wrapped. Nothing overrode the rule because nothing addressed the
   property doing the damage.

   Two classes beat one, so this wins wherever a box sits inside a field. */
.uc-field input[type="checkbox"], .uc-field input[type="radio"] {
    width: auto; padding: 0; border: 0; border-radius: 0; background: none; }
.uc-field-row { display: flex; gap: 12px; }
.uc-field-row .uc-field { flex: 1; }
.uc-fieldset { border: 1px solid var(--p-border); border-radius: 10px; padding: 14px 16px; margin: 0; }
.uc-fieldset legend { font-size: 13px; font-weight: 600; padding: 0 6px; }
.uc-hint { font-size: 12px; color: var(--p-muted); margin: 6px 0 0; }
/* A checkbox label is body text. It was 14px/500, which is not a step, and
   the Classification card is almost entirely these: eight categories, every
   organizer, and a field label above each group trying to outrank them by one
   weight. Body puts the two a full step apart, which is what the ladder is for. */
/* TOP ALIGNED, NOT CENTRED (3.86.0), AND THIS IS THE ONE PLACE IT IS DECIDED.
   Categories and organizers are the same control wearing the same class, so
   `align-items: center` put the box level with the MIDDLE of a name that wrapped
   to two lines, as several organizer names do. One fix, both screens.

   The 2px is the offset that puts the box on the FIRST LINE rather than at the
   very top of the text block: a 16px box in a 20px line box wants (20-16)/2, and
   flush-top would sit it slightly high against the cap height. Measured, not
   guessed, at the 14px body size this control uses. */
/* ===========================================================================
   A BOX SITS AT THE TOP OF ITS LABEL. THIS IS THE THIRD TIME (3.93.0).

   IT HAS BEEN FIXED TWICE AND CAME BACK TWICE, AND THE REASON IS THE SHAPE OF
   THE FIX RATHER THAN THE VALUE IN IT. Both previous fixes set `align-items`
   on the ROW. `align-items` is a parent's suggestion: any later rule naming
   that row, at any specificity, silently takes it back, and three of them did.
   The comment above .uc-check even says "this is the one place it is decided",
   which was true when it was written and was not true a release later.

   SO THIS RULE NAMES THE BOX, NOT THE ROW. `align-self` on a flex item BEATS
   `align-items` on its container outright, and not on specificity: they are
   different properties on different elements, so there is no contest to lose.
   A new row written tomorrow with `align-items: center` on it gets a centred
   row and a top-aligned box, which is the outcome this rule exists to
   guarantee.

   THE 2px IS THE FIRST LINE, NOT THE TOP EDGE. A 13px box in a 20px line box
   wants about (20-13)/2 to sit on the text rather than above it, and flush-top
   reads slightly high against the cap height. Measured at the 14px body size
   these controls use, and it is the same 2px .uc-check has carried since
   3.86.0.

   IT DOES NOTHING WHERE THERE IS NOTHING TO ALIGN. `align-self` is inert
   unless the box is a flex or grid item, so a box inside a paragraph, a table
   cell or an absolutely positioned overlay is untouched by it.

   `.claude/checkbox-align-test.php` reads the box-bearing classes out of the
   SOURCE rather than from a list kept here, so a control added next month is
   covered without anybody remembering this. That is the part that makes it a
   fourth time rather than a fourth fix.
   ======================================================================== */
.uc-portal input[type="checkbox"], .uc-portal input[type="radio"] {
    align-self: flex-start; margin-top: 2px;
}

.uc-check { display: flex; align-items: flex-start; gap: 8px; font-size: 14px; font-weight: 400; margin-bottom: 8px; }
/* The box holds its size and the label takes the rest, so a two-word label
   never wraps because the control grew. The gap owns the spacing. */
.uc-check input[type="checkbox"], .uc-check input[type="radio"] { flex: 0 0 auto; margin: 2px 0 0; }
/* ---------------------------------------------------------------------------
   A TICK THAT IS NOT A CHOICE RIGHT NOW (3.64.0).

   "Add to calendar" in the Display card, while the event is taking
   registrations. The button is off the event page in that case, so the control
   would be settable and do nothing. It keeps its stored value and greys, and
   the line under it says where the calendar link goes instead.

   IT IS THE SAME GREY AS EVERY OTHER DISABLED CONTROL in this portal, #6B7280
   on the ambient surface, which is the .uc-field-nobulk pair. A second way of
   saying "you cannot set this" would be a second thing for a manager to learn.
   ------------------------------------------------------------------------- */
.uc-check-locked { color: #6B7280; }
.uc-check-locked input { cursor: not-allowed; }
.uc-calendar-note { margin: -4px 0 8px 24px; }

.uc-side-box { background: var(--p-bg); border: 1px solid var(--p-border); border-radius: 10px; padding: 14px; }
.uc-side-box h3 { margin-top: 0; }
.uc-form-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--p-border); }

/* ---------------------------------------------------------------------------
   THE EVENT EDITOR'S SAVE ROW IS THE POINT OF THE SCREEN (3.42.1)

   WHAT WAS WRONG. Save and Publish were a right-aligned row with a hairline
   over it, sitting between the last bento card and the cancel card, wearing the
   same border as every divider on the page. Nothing said these were the actions
   the whole screen exists for, and the destructive card underneath competed
   with them on equal terms.

   IT IS A BAND, NOT A BORDER. The row gets its own surface and sits clear of
   the cards on both sides, so it reads as the end of the form rather than as
   another rule inside it. That is the cheapest way to give a control weight
   without making it bigger than the brand allows: position and surrounding
   space, not size and colour.

   NO SECOND ACCENT AND NO SECOND YELLOW. Publish already carries the one
   yellow this design gives to actions, and adding a colour to the band it sits
   on would put two competing signals in one place. The band is a surface. See
   DESIGN.md on the single accent.

   ONLY IN THE EVENT EDITOR, deliberately. Every other screen's action row is a
   small form where the buttons are already the obvious next thing, and giving
   all of them a band would spend the emphasis everywhere and mean nothing
   anywhere.
   --------------------------------------------------------------------------- */
.uc-form-actions-primary {
    align-items: center;
    gap: 12px;
    margin-top: 30px;
    margin-bottom: 30px;
    padding: 18px 20px;
    border: 1px solid var(--p-border);
    border-radius: 12px;
    background: var(--p-surface-2, #f6f7f8);
    box-shadow: 0 1px 2px rgba(16, 24, 40, 0.04);
}
/* The buttons in that row are the largest controls on the page, which is the
   other half of the weight. .uc-btn is chrome and carries its own size ladder,
   so this is a size on a button rather than a step on the type scale. */
.uc-form-actions-primary .uc-btn { padding: 11px 20px; font-size: 15px; font-weight: 600; }
.uc-form-actions-primary .uc-btn-primary { padding: 11px 26px; }

/* A caption on the left, so the row is not two buttons floating in a box and
   the space between them and the edge is doing something. */
.uc-form-actions-note { margin: 0 auto 0 0; font-size: 13px; line-height: 1.45; color: var(--p-muted, #6B6764); }

@media (max-width: 600px) {
    .uc-form-actions-primary { flex-wrap: wrap; }
    .uc-form-actions-primary .uc-btn { flex: 1 1 auto; justify-content: center; }
    .uc-form-actions-note { flex: 1 1 100%; margin-bottom: 4px; }
}

/* ---------------------------------------------------------------------------
   THE PUBLIC REQUEST FORM (3.43.0)

   Its own page, its own document, and no navigation of any kind: somebody
   arriving here has no calendar account and nothing else on this site to go to.
   The width is a reading width rather than the portal's, because there is no
   sidebar taking the left third and a form at full window width is a form
   nobody finishes.

   IT REUSES portal.css RATHER THAN CARRYING ITS OWN. One stylesheet means the
   fields, the buttons and the type here are the same objects as everywhere
   else, so the ladder and the palette apply without a second copy to keep in
   step. What is added below is only the page frame and the picture grid.
   --------------------------------------------------------------------------- */
.uc-request-page { background: var(--p-bg, #f2f3f4); }
.uc-request-wrap { max-width: 720px; margin: 0 auto; padding: 40px 20px 64px; }
/* THE PADDING AS A NUMBER ITS CHILDREN CAN READ. The banner pulls back out
   through it to reach the card's edges, and a literal copied into that rule
   is correct only while this one does not move. That is exactly how the
   sidebar heading band came to sit 14px wider than its rows in 3.45.1. */
.uc-request-card { --uc-request-pad: 28px;
    padding: var(--uc-request-pad); border: 1px solid var(--p-border); border-radius: 14px;
    background: #fff; box-shadow: 0 1px 3px rgba(16, 24, 40, 0.05); }
.uc-request-card h1 { margin: 0 0 10px; font-size: 24px; font-weight: 800; }
.uc-request-card > .uc-hint { margin-bottom: 22px; }
.uc-request-card .uc-field { margin-bottom: 18px; }
/* A FIELDSET THAT IS ONE FIELD, stripped back to looking like one: the
   Categories checkboxes are a fieldset because they need a legend, not because
   they are a section.
   ONLY A FIELD, AND A SECTION MUST NEVER CARRY .uc-field. This is (0,2,1) and
   .uc-form-section-group is (0,1,0), so a section that took this class lost its
   boundary and its padding to these three lines and drew nothing. That is what
   3.68.0 found. The section class is now the only class those fieldsets carry;
   request-form-test.php fails if one of them takes .uc-field back. */
.uc-request-card fieldset.uc-field { border: 0; padding: 0; margin-inline: 0; }
.uc-request-card legend.uc-field-label { padding: 0; }

/* The honeypot. Off-screen rather than display:none, because some bots skip
   what is not rendered, and hidden from assistive technology as well so it is
   never read out to somebody filling this in. */
.uc-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ---------------------------------------------------------------------------
   PICKING A PICTURE WITH NO MEDIA LIBRARY

   wp.media needs an account, so this is radio buttons over the same calendar
   folder the editor's picker queries.

   A PICKER, NOT A GRID (3.65.0). This was a grid of every picture in the
   folder, drawn all at once. Workable at a dozen and unusable at two hundred,
   and the folder only grows. It is a .uc-picker now, which is the same
   disclosure the notification picker and the teams screen already wear, so
   everything below is the difference between a row of PEOPLE and a row of
   PICTURES and nothing else. The trigger, the search box, the panel and the
   list are declared once, up beside .uc-picker.
   --------------------------------------------------------------------------- */
.uc-image-picker { margin: 12px 0; }
/* Its trigger carries a thumbnail, and a picture has no baseline to sit on. */
.uc-image-picker > .uc-picker-toggle { align-items: center; }
/* The picture and its name, top-aligned now that the picture is 113px tall:
   centred, the name floated in the middle of a large image and read as a
   caption rather than as the answer to "which one". */
.uc-image-current { display: flex; align-items: flex-start; gap: 10px; min-width: 0; }
/* BIGGER, TWICE OVER (3.76.0), AND THEN THE WRONG WAY ROUND (3.78.0).
   ---------------------------------------------------------------------------
   48x27 and 64x36 were the sizes these were built at, and at those sizes a
   photograph is a smudge: somebody choosing between six pictures of people in
   a room cannot tell them apart, which is the whole job of the control. 3.76.0
   raised both, the trigger to 96 and the row to 132.

   RAISING THEM SEPARATELY INVERTED THEM, which is the fault and is not a rule
   living somewhere else. The TRIGGER is the picture somebody looks at to
   decide: it is what the form shows once the panel is shut and it is the
   answer to "which one did I choose". The ROW is what gets scanned past. The
   trigger ended up SMALLER than the rows it chooses from, which is backwards,
   and neither number was wrong on its own.

   SO THE TRIGGER IS THE BIGGEST PICTURE IN THE CONTROL, and the ordering is
   now the thing to preserve rather than either number: trigger, then row, then
   anything else. 16:9 throughout, matching every other place this calendar
   shows an event picture. */
.uc-image-current-thumb { flex: 0 0 auto; width: 200px; height: 113px; object-fit: cover;
    border-radius: 8px; border: 1px solid var(--p-border); }
/* It gets its own line at narrow widths rather than squeezing the name to
   nothing beside it. The toggle is already flex-wrap: wrap. */
@media (max-width: 600px) {
    .uc-image-current-thumb { width: 100%; max-width: 260px; height: auto; aspect-ratio: 16 / 9; }
}
.uc-image-current-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* THE SEARCH BOX IS NOT THERE UNTIL IT CAN WORK. portal.js reveals it. Without
   script the list still renders and a picture can still be chosen and sent; a
   box that cannot filter would be the one part of this that lied. Same
   mechanism as .uc-picker-tabbed on the notification picker. */
.uc-image-search { display: none; }
.uc-image-picker-live .uc-image-search { display: block; }

/* Taller than the people list, because each row is a picture rather than a
   line of text, and the whole point is being able to see enough of them. */
/* Taller again with the rows, or the panel shows two and a half of them. */
.uc-image-options { max-height: 420px; }
.uc-image-option { gap: 10px; }
.uc-image-option-thumb { flex: 0 0 auto; width: 132px; height: 74px; object-fit: cover;
    border-radius: 6px; border: 1px solid var(--p-border); background: var(--p-bg); }
.uc-image-option-blank { border-style: dashed; }
/* THE SAME BOX, CARRYING THE SERIES PHOTO (3.68.0). The "nothing chosen" row is
   a <span> rather than an <img>, so the picture arrives as a background and
   this is what makes it fill the box the way object-fit fills the others. The
   dashed edge goes with it: there is something in the box now. */
.uc-image-option-thumb-series { border-style: solid; background-size: cover;
    background-position: 50% 50%; background-repeat: no-repeat; }
.uc-image-option-text { min-width: 0; }
/* ONE NAME PER ROW (3.67.0), the picture's title where it has a real one and
   its file name where it does not. It was both, one above the other, which
   made a titled picture two lines and an untitled one a line with a gap above
   it. It breaks anywhere rather than widening the panel, because a file name is
   long and has no spaces. */
.uc-image-option-name { display: block; font-size: 13px; font-weight: 600; line-height: 1.3;
    overflow-wrap: anywhere; }
/* One line under the name, on the "nothing chosen" row only, saying what that
   row actually means once a series photo is in it. Helper step, 12/400 muted,
   which is the ladder's own. */
.uc-image-option-note { display: block; font-size: 12px; font-weight: 400; line-height: 1.4;
    color: var(--p-muted, #6B6764); }

/* ---------------------------------------------------------------------------
   WHAT IS IN THE CHOSEN FAQ SET (3.76.0)

   A read-only list under the set picker on the staff request form. Not fields:
   the rows are copied server-side at validate time, and a second editable copy
   here would be a second place the set's text can be changed.

   Boxed in the page tint so it reads as "here is what that is" rather than as
   more of the form. Every list is in the markup and portal.js hides all but
   the chosen one, so with no script this is several boxes and not none.
   ------------------------------------------------------------------------ */
.uc-faq-set-peek { margin: -4px 0 14px; }
.uc-faq-set-list {
    margin: 0 0 8px; padding: 10px 12px;
    border: 1px solid var(--p-border); border-radius: 8px;
    background: var(--p-surface-2, #f6f7f8);
}
.uc-faq-set-list:last-child { margin-bottom: 0; }
.uc-faq-set-list ul { margin: 4px 0 0; padding-left: 18px; }
.uc-faq-set-list li { font-size: 13px; line-height: 1.5; }

/* ---------------------------------------------------------------------------
   A REQUEST IN THE QUEUE, AND ON THE EVENT IT BECAME

   Pending has meant "an import that needs an image and a description". A staff
   request arrives filled in and needs reading rather than completing, so the
   row says which kind it is. A badge and a name, not a second table: two
   queues is one queue somebody stops checking.
   --------------------------------------------------------------------------- */
/* THE BADGE IS THE WHOLE MARKER, and there is no coloured edge on the row.
   One was written and the decoration audit refused it, correctly: the row
   already says "Staff request" in words, so an edge in the same colour repeats
   it and the colour carries nothing of its own. See DESIGN.md. */
.uc-badge-request,
.uc-badge-staff { background: #e3f7f9; color: #0C666F; }

/* A SECOND KIND NEEDS A SECOND COLOUR, or the badge stops being the marker and
   only the words are, at 11px, at the end of a title. Warm rather than teal
   because the two are read side by side in one column and hue is the fastest
   thing to tell apart there. Measured on this fill: 5.4:1, so it clears AA for
   normal text at the size the badge actually uses. The pair is declared once,
   as a pair, for the reason in DESIGN.md: a colour is fill or ink, never both,
   and splitting the declaration is how red ended up on red at 1.19:1. */
.uc-badge-community { background: #FDF0DC; color: #7A4A05; }

/* THE SUBMITTED FILE ON THE ROW, small and out of the way of the title.
   It is a working copy, so it is deliberately not sized or cropped like a card
   image: this is "what did they send", not a preview of anything published. */
.uc-submitted-thumb { float: left; margin: 0 10px 2px 0; line-height: 0; }
.uc-submitted-thumb img { width: 46px; height: 46px; object-fit: cover;
    border-radius: 6px; border: 1px solid var(--p-border, #D1D3D4); display: block; }

.uc-request-shot { margin-top: 14px; }
.uc-request-shot img { max-width: 100%; height: auto; margin-top: 6px;
    border-radius: 10px; border: 1px solid var(--p-border, #D1D3D4); display: block; }
.uc-request-shot .uc-hint { margin-top: 6px; }

/* THE EXTRA PICTURES A SUBMISSION SENT (3.96.0).
 *
 * A GROUP WITH ITS OWN LABEL, which is the whole of what distinguishes these
 * from the featured picture. Three thumbnails in a row with no label read as
 * three candidates for the event's image, and none of these is a candidate at
 * all: no picker lists them and approval copies none of them anywhere.
 *
 * THE THUMBNAILS ARE THE SAME 46px SQUARE the queue already uses, through the
 * same .uc-submitted-thumb class, so the featured one and these are the same
 * object drawn twice rather than two things that happen to look alike. Only the
 * label above them differs.
 *
 * FLOAT IS UNDONE, for the reason the queue row already undoes it: this list is
 * a flex row and a floated child in one is laid out twice and believed once. */
.uc-submitted-extras { flex: 0 0 auto; }
.uc-submitted-extras .uc-field-label { display: block; margin-bottom: 4px; }
.uc-submitted-extras-list { display: flex; flex-wrap: wrap; gap: 6px; }
.uc-submitted-extras-list > .uc-submitted-thumb { float: none; margin: 0; }
/* In the editor's panel the featured picture is shown at its own size, so the
   extras take a size of their own rather than the 46px a queue row uses: the
   panel is a column somebody is reading, not a list they are scanning. */
.uc-request-panel .uc-submitted-extras { margin-top: 14px; }
.uc-request-panel .uc-submitted-extras-list > .uc-submitted-thumb img {
    width: 120px; height: 90px; border-radius: 8px;
}
.uc-request-panel .uc-request-who { margin: 0 0 10px; font-size: 14px; line-height: 1.5; }
.uc-request-panel .uc-request-who .uc-muted { margin-left: 6px; }
/* A staff request's one line (3.113.3): no card, 13px --p-muted, the name a
   link. Two classes, to outrank the 14px rule above. */
.uc-request-line { margin: 0 0 16px; }
.uc-request-line .uc-request-who { margin: 0 0 6px; font-size: 13px; color: var(--p-muted); }
.uc-request-line .uc-hint { margin: 0 0 6px; }
.uc-request-notes { margin-top: 12px; padding: 12px 14px; border-radius: 10px;
    background: var(--p-surface-2, #f6f7f8); }
.uc-request-notes p { margin: 4px 0 0; font-size: 14px; line-height: 1.55; white-space: pre-wrap; }

/* ---------------------------------------------------------------------------
   CANCELLING IS SET APART, AND CLOSED (3.42.1)

   It read as the next section of the form: a bento card in the same rhythm as
   the cards above it, so somebody scrolling past Save landed straight in a set
   of radio buttons and a red button. A destructive action should take a
   deliberate act to reach, which is what the disclosure is for.

   QUIET WHEN CLOSED. The summary is a line of text with a chevron, not a red
   button: a closed disclosure that shouts is the same problem in a smaller box.
   The red appears once it is open, on the control that actually does it.

   The generous space above is doing the separating. There is no rule across the
   page, because the save band already ends the form and a second divider would
   be two endings.
   --------------------------------------------------------------------------- */
.uc-danger-zone { margin: 34px 0 40px; }
.uc-danger-disclosure > summary { list-style: none; cursor: pointer; }
.uc-danger-disclosure > summary::-webkit-details-marker { display: none; }
.uc-danger-disclosure > summary::marker { content: ""; }
/* ---------------------------------------------------------------------------
   THIS TOGGLE MOVED FROM QUIET TO DESTRUCTIVE (3.72.0), AND THAT IS A CHANGE
   OF MIND RATHER THAN A CORRECTION.

   WHAT IT WAS AND WHY. 3.42.1 put cancelling behind a closed disclosure so a
   manager scrolling past Save did not arrive at a card of radios and a red
   button reading like the next thing to fill in. That reasoning stands and the
   disclosure stays. What it also did was give the toggle the QUIET weight from
   the control standard, --p-muted 13px with no surface, which is the vocabulary
   for "a verb in a row of verbs". This is not one. It is the only control on
   the screen that stops an event happening, it sits alone under the form, and
   it was reported as missed.

   THE TWO DECISIONS ARE SEPARABLE. "Reached deliberately" is what the closed
   disclosure buys, and it is bought by the fold, not by the ink. "Recognised as
   destructive" is what the fill buys. Making it quiet bought the first at the
   cost of the second, and there was never a reason both could not be had.

   THE MEASURED VALUE IS THE STANDARD'S OWN. Solid #c0392b with white ink,
   5.44:1, which is the DESTRUCTIVE row in the button vocabulary above and the
   same pair .uc-btn-danger already carries. Nothing new is being mixed here.

   IT IS STILL NOT A .uc-btn. This is a <summary>, so it opens a disclosure
   rather than doing anything, and it keeps its chevron. What it takes from the
   destructive row is the surface and the ink, which is what says "this one is
   different from everything above it".
   ------------------------------------------------------------------------- */
.uc-danger-toggle {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 9px 16px; margin: 0;
    border-radius: 8px;
    border: 1px solid #c0392b;
    background: #c0392b;
    color: #fff;
    font-size: 14px; font-weight: 600;
}
.uc-danger-toggle:hover { color: #fff; background: #a33025; border-color: #a33025; }
.uc-danger-disclosure > summary:focus-visible { outline: 2px solid var(--p-text); outline-offset: 2px; border-radius: 8px; }
/* THE CHEVRON IS NOT DECLARED HERE (3.64.0). It was, and the declaration was
 * dead: `.uc-disclosure-chevron` was declared again 1350 lines below at the
 * same specificity, as a 28px ring, so the later one won and this quiet
 * disclosure wore a circle nobody chose. Exactly the shape of the 3.39.0
 * .uc-btn-danger fault, and now checked for every single-class rule in the
 * file by .claude/control-standard-audit.php. The glyph this one wanted is
 * the default there now, and the turn is the shared
 * `[open] > summary .uc-disclosure-chevron` rule. */
.uc-danger-body {
    margin-top: 12px; padding: 20px;
    border: 1px solid #e6c9c5;
    border-radius: 12px;
    background: #fdf7f6;
}
.uc-danger-body .uc-cancel-form { margin-top: 0; }

/* ---------------------------------------------------------------------------
   A SAVE BUTTON NEEDS AIR UNDER IT, NOT JUST OVER IT.

   On the series editor the Save Series row had 22px above it and nothing
   below, and the very next thing on the page is the Schedule card. So the most
   consequential control on the screen sat a few pixels off an unrelated
   section, which reads as though the button belongs to what is under it. The
   form's actions are the end of the form and the gap has to say so.

   36px, not the cards' own 20px: this is a boundary between a form and the
   next thing, which is a bigger break than the one between two cards.
   ------------------------------------------------------------------------- */
.uc-form > .uc-form-actions:last-child,
form > .uc-form-actions:last-child { margin-bottom: 36px; }

/* ---------------------------------------------------------------------------
   THE CONTROL SPACING BASELINE.

   The rule above is an instance fix, and Save Series was the third one: the
   RSVP settings form got `margin-top: 4px`, the import queue form got 16px,
   .uc-venue-actions and .uc-team-create-actions each got their own figure, and
   every time the answer was "add a margin to that one". Fixing the fourth the
   same way is what makes it a fifth.

   WHAT THE AUDIT SAID. Nineteen control rows and standalone control blocks in
   caladmin, counted by taking every class in the markup named `*-actions` plus
   the blocks that stand alone in the flow, and asking the stylesheet whether
   each says anything about the space above or below it. ELEVEN SAID NOTHING AT
   ALL:

     .uc-actions            .uc-page-head-actions   .uc-team-actions
     .uc-cat-actions        .uc-queue-actions       .uc-user-actions
     .uc-cat-form-actions   .uc-schedule-actions
     .uc-faq-set-actions    .uc-scope-switch
     .uc-head-actions

   Three of those also lay out with no gap of any kind: .uc-queue-actions,
   .uc-scope-switch and .uc-user-actions, so their buttons were flush
   horizontally as well. Only .uc-form-actions, .uc-view-tabs, .uc-filters-bar,
   .uc-image-buttons and the two rows patched by hand had any figure.

   THE BASELINE IS KEYED ON THE NAME, WHICH IS WHY IT CANNOT BE FORGOTTEN.
   `[class*="-actions"]` matches the convention the codebase already follows,
   so a row added tomorrow and called .uc-whatever-actions is spaced the moment
   it is named, with nothing to remember and no list to extend. Same move as
   "a heading at the top of a card IS the card's heading": follow from what the
   thing is rather than from a class somebody has to opt into.

   :where() CONTRIBUTES ZERO SPECIFICITY, so every figure above still wins.
   .uc-form-actions keeps its 22px, .uc-team-create-actions its 10px, the queue
   form its 16px. This is a floor for anything that never had one, not a ruling
   over anything that did.

   THE PARENT LIST IS THE WHOLE DISCRIMINATION, and it is deliberate. A margin
   is only ever right in block flow: on a flex child in a horizontal row it
   shoves the control down out of alignment. So the top margin applies only to
   rows that are a DIRECT CHILD of something that stacks: the page column, a
   card, a section, a form. .uc-team-actions inside .uc-team-row stays
   untouched and centred, because .uc-team-row is a horizontal flex row and is
   not on the list; the same .uc-team-actions inside .uc-team-members-form is
   the case that was reported and it gets its 14px, because a form stacks.

   ONE DISPLAY CHANGE, NAMED RATHER THAN LEFT TO BE FOUND. A zero-specificity
   fallback must not set `display` blind (see the control fallback further
   down), so this one is restricted to `div` by element type:
   every table cell named `-actions` is a td or a th and cannot be reached, and
   the two spans likewise. Of the 24 divs, exactly one does not already declare
   a display: .uc-queue-actions, which holds a single .uc-actions child and
   looks the same either way.
   ------------------------------------------------------------------------- */
:where(.uc-portal) :where(div[class*="-actions"]) {
    display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
}
:where(.uc-portal-content, .uc-card, .uc-section, .uc-form, form) >
:where([class*="-actions"], .uc-scope-switch, .uc-view-tabs) { margin-top: 14px; }
/* A single control standing on its own in a page or a card, with no row around
   it. Not extended to `form >`, where a lone .uc-btn is usually an inline
   wrapper inside a horizontal row of other people's buttons. */
:where(.uc-portal-content, .uc-card, .uc-section) > :where(.uc-btn) { margin-top: 14px; }

/* ---------- Page sections ----------
   A heading, a sentence saying what the section is for, and a rule. Users &
   Permissions was four cards in a row down one page with nothing saying where
   one subject ended and the next began. */
.uc-section { margin-bottom: 34px; }
.uc-section + .uc-section { padding-top: 28px; border-top: 2px solid var(--p-border); }
.uc-section-head { margin-bottom: 14px; }
/* The SECTION step: above a card heading, below the page title, and the only
   level between them. Montserrat, but not uppercase: at 20px that shouts. */
.uc-section-head h2 { margin: 0 0 4px; font-size: 20px; font-weight: 700;
    font-family: var(--uc-font-heading); color: var(--sfaf-darkgray); }
.uc-section-sub { margin: 0; font-size: 13px; color: var(--p-muted); }

/* ---------- Users ---------- */
/* Layout only. The box is the baseline's. */
.uc-inline-form select { max-width: 100%; }
.uc-user-id strong { display: block; }
/* No rule of its own. Both selects on this screen are the standard select,
   and this one was the smallest and faintest of the three sizes in use. */
/* ---------------------------------------------------------------------------
   THE EVENT EDITOR: BENTO CARDS

   Six columns, and each group of fields is a card that names itself. The old
   editor was one column of identically weighted labels, so the title, the
   fundraising toggle and the reply-to address all looked equally important and
   finding the date meant reading everything above it.

   THE CARDS HOLD UP WHEN FIELDS ARE LOCKED. An imported event disables its
   platform-owned controls and marks empty manager-owned ones amber. A card with
   three disabled inputs has to look deliberate rather than broken, so a locked
   field keeps the same shape and weight it always had and only the badge and
   the muted control say what it is. Nothing in this block changes when a field
   is locked except the field itself.
   ------------------------------------------------------------------------- */
/* TWO COLUMNS: TWO THIRDS AND ONE THIRD.

   THE SPLIT IS BY WHAT A CARD IS, not by how tall it happens to be. The main
   column is the event itself: what it is, how it is found, when, where, who
   hears about it, what people ask. The side column is secondary settings that
   are read rarely and changed rarely: capacity, the donate link, the
   organizer's address, which features show.

   WHY NOT SIX EQUAL COLUMNS, which this replaced: a card's width said nothing
   about what the card was for, so pairing was a height-matching exercise and
   the page read as a scatter. WHY NOT CSS MULTI-COLUMN, which came before
   that: columns fill top to bottom before moving right, so two cards stacked
   down a narrow strip while the page beside them sat empty.

   EACH COLUMN IS A FLEX STACK, so every card in it is full width and no card
   is ever beside another. There is no row for a short card to leave a hole in,
   which is what all the span tuning was for. align-items: start keeps the
   columns independent: the side column ends where its content ends rather than
   stretching to match the main one.

   DOM ORDER IS MAIN THEN SIDE, so at one column the event comes first and the
   settings follow, and tab order is what is on screen at both widths. The side
   column is rendered into a buffer first in PHP for a separate reason, to do
   with which card claims which field; see render_event_form(). */
.uc-bento { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    gap: 16px; align-items: start; margin-bottom: 20px; }
.uc-bento-main, .uc-bento-side { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.uc-bento-card { min-width: 0;
    background: var(--surface-2); border: 1px solid var(--p-border);
    border-radius: 12px; padding: 18px; overflow: hidden; }
/* The same band as .uc-card-head, on a card whose heading is a bare <h2>
   rather than a wrapper. Full bleed by the same negative-margin trick. */
.uc-bento-title { font-size: 14px; margin: -18px -18px 16px; padding: 10px 18px;
    background: var(--uc-band); border-bottom: 1px solid var(--p-border); }
.uc-bento-head { display: flex; align-items: center; justify-content: space-between; gap: 12px;
    flex-wrap: wrap; margin: -18px -18px 16px; padding: 8px 18px;
    background: var(--uc-band); border-bottom: 1px solid var(--p-border); }
.uc-bento-head .uc-bento-title { margin: 0; padding: 0; background: none; border: 0; }
.uc-bento-link { margin: 0 0 12px; font-size: 13px; display: flex; align-items: center; gap: 6px; }

/* One control width for the whole editor. Mixed widths were most of why it read
   as unfinished. */
.uc-bento .uc-field input[type="text"], .uc-bento .uc-field input[type="url"],
.uc-bento .uc-field input[type="email"], .uc-bento .uc-field input[type="date"],
.uc-bento .uc-field input[type="time"], .uc-bento .uc-field input[type="number"],
.uc-bento .uc-field select, .uc-bento .uc-field textarea,
.uc-bento .uc-location-custom input { width: 100%; }

/* Helper text is QUIETER THAN A LABEL, not the same size in a different colour.
   Field labels carry the weight; hints explain and get out of the way. */
.uc-bento .uc-hint { font-size: 12px; line-height: 1.5; color: var(--p-muted); font-weight: 400; }
/* The two short ones that stayed inline. They prevent a specific mistake, so
   they read as instruction rather than as background. */
.uc-bento .uc-hint-spec { color: var(--p-text); }
.uc-bento .uc-field-label { font-size: 13px; font-weight: 600; }
.uc-bento .uc-field { margin-bottom: 14px; }
.uc-bento .uc-field:last-child { margin-bottom: 0; }
.uc-bento .uc-card { background: transparent; border: 0; padding: 0; margin: 0; }
.uc-bento .uc-bento-link { margin: 0 0 12px; }
.uc-bento .uc-bento-link a { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.uc-repeat-line { margin: 0; font-size: 13px; }

/* One column below 980px: the main column first, then the side column, which
   is the order they are written in. Nothing is reordered at any width, so the
   tab order is always what is on screen. */
@media (max-width: 980px) {
    .uc-bento { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- Help disclosures ----------
   A "?" beside a label, opening a paragraph. A real button, so it answers to
   click, tap, Enter and Space, and carries aria-expanded; never hover, which no
   touch screen and no keyboard can produce. With the script gone the region is
   simply visible, so nothing behind one is ever unreachable. */
/* A CONTROL BOUNDARY, NOT A HAIRLINE (3.64.0). This is a 16px circle carrying
   one character, so its edge is the whole of what says a control is there, and
   it was drawn in the decorative --p-border at 1.26:1. The boundary token is
   3.33:1, which is what WCAG 1.4.11 asks of a control that has no label. */
/* IT KEEPS THE WHITE FILL, AND THAT IS NOT AN OVERSIGHT (3.64.0). Everything
   else pressable in caladmin took the Light Gray button face, because white
   is what a field wears and the two were indistinguishable. This one is a
   16px circle carrying one character, and its two states ARE white and solid
   teal: closed is white, open is filled. Giving the closed state the button
   face would put a grey circle and a teal circle a step apart instead of two
   steps, for the sake of a consistency nothing here was confused by. */
.uc-help-btn { display: inline-flex; align-items: center; justify-content: center;
    width: 16px; height: 16px; margin-left: 5px; padding: 0; border-radius: 50%;
    border: 1px solid var(--p-border-strong); background: #fff; color: var(--p-muted);
    font-size: 11px; font-weight: 700; line-height: 1; cursor: pointer; vertical-align: middle; }
.uc-help-btn:hover { color: var(--uc-accent-text); border-color: var(--uc-accent-text); }
.uc-help-btn:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: 1px; }
.uc-help-btn[aria-expanded="true"] { color: #fff; background: var(--uc-accent-text); border-color: var(--uc-accent-text); }
.uc-help-body { display: block; margin: 6px 0 0; padding: 8px 10px; border-radius: 8px;
    background: #fff; border: 1px solid var(--p-border);
    font-size: 12px; font-weight: 400; line-height: 1.5; color: var(--p-muted); }
.uc-help-body[hidden] { display: none; }

/* A HELP PANEL OPENING INSIDE A CARD'S TITLE BAND (3.72.0).

   Series, teams and private events carry their glyph on the card heading rather
   than on a field label, because the thing being explained is the card. The
   body is display:block, so it opens INSIDE the band, and the band is a tinted
   strip with 10px/18px padding and a bottom hairline: dropped in as-is the
   panel sat hard against the strip's edges and read as the strip having grown a
   second, paler strip.

   The negative margins cancel the band's own padding so the panel spans the
   full width of the card, and the top margin restores the gap the heading text
   needs. The white face and the hairline are the panel's own and are unchanged;
   what moves is where its edges are.

   TWO CLASSES, WHICH IS WHAT MAKES IT WIN. `.uc-help-body` is one class and
   this is two, so it outranks the base rule on points without an id or an
   important, and the base rule stays the one answer for a panel on a field
   label. */
.uc-bento-title .uc-help-body {
    margin: 10px -18px -10px;
    border-radius: 0;
    border-left: 0; border-right: 0; border-bottom: 0;
}
/* The heading is a heading again once the panel is under it: a bold 14px h2
   whose second line is a 12px panel needs the two to be separate blocks rather
   than one run of text. */
.uc-bento-title:has(.uc-help-body:not([hidden])) { padding-bottom: 0; }

/* ---------- Radio rows ----------
   Control first, label beside it, both hard left.

   THE PART THIS BLOCK CANNOT DO ON ITS OWN is up beside .uc-field, and that is
   why 3.10.0 looked unchanged on screen. The rows were never centred by a
   text-align they inherited; the radio itself was 100% wide, from
   `.uc-field input`, and a browser paints the glyph in the middle of the box it
   is given. flex: 0 0 auto here resolves its basis from `width`, so it could
   not undo that by itself. The width reset lives with the rule that caused it,
   where the next person to read `.uc-field input` will see it. */
.uc-radio-row { display: flex; align-items: flex-start; gap: 8px; margin: 0 0 6px;
    font-size: 14px; font-weight: 400; cursor: pointer; text-align: left; }
.uc-radio-row input[type="radio"] { flex: 0 0 auto; width: 16px; margin: 0; }   /* 16px, the baseline's size: auto left a 13 by 16 box (3.102.0) */
.uc-radio-row span { flex: 1 1 auto; }

/* ---------------------------------------------------------------------------
   THE RECURRENCE CONTROL.

   A radio group that looks like a switch, seven checkboxes that look like day
   circles, and a plain-language summary. Every one of them is a real input
   underneath: the visual is a sibling <span>, and the input itself is taken out
   of the flow rather than display:none'd, so it keeps its focus ring, its
   keyboard behaviour and its announcement.
   ------------------------------------------------------------------------- */
.uc-repeat { display: flex; flex-direction: column; gap: 12px; }

/* The Repeats switch IS the segmented control, declared up beside All events /
   My events so the two cannot drift. All that is left here is the mechanism:
   a real radio taken out of the flow, keeping its focus ring, its keyboard
   behaviour and its announcement, with the visible segment as its sibling. */
.uc-seg-opt { position: relative; }
.uc-seg-opt input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }

.uc-repeat-panel { display: flex; flex-direction: column; gap: 8px;
    padding: 12px 14px; border: 1px solid var(--p-border); border-radius: 10px; background: var(--p-bg); }
.uc-repeat-every { display: flex; align-items: center; gap: 8px; font-size: 14px; flex-wrap: wrap; }
/* Width, and nothing else: "every N weeks" is a two-digit answer and a
   full-width box for it says the wrong thing about how long the answer is.
   The box itself is the standard field, so the three controls inside the
   recurrence panel now match the three outside it. */
.uc-repeat-num { width: 74px; }
.uc-repeat-nth { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-left: 22px; }

/* THE DAY CIRCLES ARE CHECKBOXES. Round is a style; what a screen reader and a
   keyboard get is a labelled checkbox in a group, which is what it is. */
.uc-days { display: flex; gap: 6px; flex-wrap: wrap; }
.uc-day { position: relative; }
.uc-day input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.uc-day > span[aria-hidden] { display: flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; border-radius: 50%; border: 1px solid var(--p-border-strong);
    background: #fff; font-size: 13px; font-weight: 700; color: var(--p-text);
    cursor: pointer; user-select: none; }
.uc-day input:hover + span { background: var(--uc-band); }
.uc-day input:checked + span { background: var(--uc-accent-text); border-color: var(--uc-accent-text); color: #fff; }
.uc-day input:focus-visible + span { outline: 2px solid var(--uc-accent-text); outline-offset: 2px; }

/* ---------------------------------------------------------------------------
   THE DATES PICKER: Custom's whole schedule, or extras beside a pattern.

   ONE BLOCK FOR BOTH, because they are one control. What changes between the
   two readings is the label above it, which portal.js sets, and whether the
   event's own date is pinned to the top of the list.

   THE LIST IS AN <ol> AND IS NUMBERED, deliberately. The summary says "5 dates"
   and the manager has to be able to count five things on screen to believe it;
   an unnumbered list of five makes that a counting exercise. Each row holds a
   hidden input, so the row IS the field rather than a picture of one.

   .uc-dates-slots is the no-script path and is hidden by portal.js rather than
   by this file. A stylesheet that hid it would hide it from a browser with no
   script as well, which is the one case it exists for.
   ------------------------------------------------------------------------- */
.uc-dates-add { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.uc-dates-slots { display: flex; gap: 8px; flex-wrap: wrap; }
.uc-dates-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px;
    counter-reset: uc-date; }
.uc-dates-list:empty { display: none; }
.uc-dates-row { display: flex; align-items: center; gap: 10px; padding: 6px 10px;
    background: #fff; border: 1px solid var(--p-border); border-radius: 8px; font-size: 13px; }
.uc-dates-row::before { counter-increment: uc-date; content: counter(uc-date) "."; flex: 0 0 auto;
    min-width: 18px; color: var(--p-muted); font-weight: 700; font-variant-numeric: tabular-nums; }
.uc-dates-when { flex: 1 1 auto; min-width: 0; font-weight: 600; color: var(--p-text); }
/* The event's own date, pinned and not removable: it is the date the form
   above already carries, shown here so the count in the summary matches the
   number of rows a person can see. Tinted rather than merely unlabelled,
   because "why can I not remove this one" is the obvious question. */
.uc-dates-row-own { background: var(--uc-band); border-color: var(--sfaf-teal); }
.uc-dates-own-tag { flex: 0 0 auto; font-size: 12px; color: var(--p-muted); }

/* The sentence that says what all of it comes to, and how many events that is.
   Yellow is not used here: this is information, not an action. */
.uc-repeat-summary { margin: 0; padding: 10px 12px; border-radius: 8px;
    background: var(--uc-band);
    font-size: 13px; font-weight: 600; color: var(--p-text); }

/* ---------------------------------------------------------------------------
   NOTIFICATIONS: three questions, in the order they happen.
   ------------------------------------------------------------------------- */
.uc-notify-block { display: flex; flex-direction: column; gap: 20px; }
/* ---------------------------------------------------------------------------
   THE THREE SUBSECTIONS, READING AS THREE THINGS.

   "When somebody registers", "The morning-of reminder" and "Replies" answer
   three different questions and were running as one long block: 16px of
   padding and a hairline between them, with headings that were the right size
   in the scale but had no space around them to act on it. On the registrations
   screen, where all three are in a single card with no other structure, it was
   one column of controls from top to bottom.

   SPACE IS HALF THE SIGNAL, which is the same thing the type scale says about
   the subhead level: a heading with air over it reads as starting something.
   28px above the rule and 22px below it, so each subhead has a clear band of
   nothing before it. The rule itself stays a hairline rather than getting
   heavier, because the brand guide is explicit that rules and boxes are what
   clutter a layout (p.17), and the spacing is doing the work.
   ------------------------------------------------------------------------- */
.uc-notify-section { display: flex; flex-direction: column; gap: 10px;
    margin-top: 28px; padding-top: 22px; border-top: 1px solid var(--p-border); }
.uc-notify-section:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
/* The subhead leads its section, so it takes no space of its own: the section
   above it already supplies the break. */
.uc-portal .uc-notify-section > .uc-notify-subhead { margin: 0; }
/* The line under a subhead explains it and belongs to it, so it sits tight
   under the heading rather than at the section's own gap. */
.uc-portal .uc-notify-section > .uc-notify-subhead + .uc-hint { margin-top: -4px; }

/* THE CHOSEN RECIPIENTS, AS CHIPS, under the picker. The same shape as the
   address pills below them, so the card reads one way throughout: a list is
   for finding somebody, a chip is somebody who is on the list. */
.uc-rchips { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.uc-rchips-label { font-size: 12px; font-weight: 600; color: var(--p-muted); }
.uc-rchips-list { display: flex; flex-wrap: wrap; gap: 6px; }
.uc-rchip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 6px 4px 11px;
    border-radius: 99px; font-size: 13px; font-weight: 500; line-height: 1.4;
    background: var(--uc-band); color: var(--p-text); border: 1px solid var(--p-border-strong); }
/* A team is a different KIND of thing from a person and is marked as one,
   because "Philanthropy" and "Ann Rivera" otherwise look like two people. */
.uc-rchip-team { background: #fff; border-style: dashed; }
.uc-rchip-team .uc-rchip-text::before { content: "Team: "; color: var(--p-muted); font-weight: 600; }
.uc-rchip-x { border: 0; background: none; cursor: pointer; font-size: 16px; line-height: 1;
    padding: 0 4px; color: inherit; opacity: 0.7; border-radius: 99px; font-family: inherit; }
.uc-rchip-x:hover { opacity: 1; }
.uc-rchip-x:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: 1px; }
.uc-rchips-empty { margin: 0; font-size: 12px; }

/* "Anyone else": one address at a time, as removable pills. */
.uc-email-pills { display: flex; flex-wrap: wrap; gap: 6px; }
.uc-email-pill { position: relative; display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 10px; border-radius: 99px; font-size: 13px; font-weight: 500; margin: 0;
    background: var(--uc-band); color: var(--p-text); border: 1px solid var(--p-border-strong); }
.uc-email-pill input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.uc-email-pill-x { font-size: 15px; line-height: 1; opacity: 0.65; }
.uc-email-pill:hover .uc-email-pill-x { opacity: 1; }
.uc-email-pill input:focus-visible ~ .uc-email-pill-x { outline: 2px solid var(--uc-accent-text); outline-offset: 2px; }
/* With scripting off an unticked pill stays on screen, so it has to LOOK
   removed rather than silently still being there. */
.uc-email-pill input:not(:checked) ~ .uc-email-pill-text { text-decoration: line-through; opacity: 0.55; }
.uc-email-add { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.uc-email-add input { flex: 1 1 240px; min-width: 0; }
.uc-emails-field { gap: 8px; }

/* ---------- Categories as chips ---------- */
.uc-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.uc-chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 6px 4px 11px;
    border-radius: 99px; font-size: 13px; font-weight: 600; line-height: 1.4;
    background: color-mix(in srgb, var(--chip-color, #16BECF) 14%, #fff);
    color: color-mix(in srgb, var(--chip-color, #16BECF) 72%, #000); }
.uc-chip-remove { border: 0; background: none; cursor: pointer; font-size: 16px; line-height: 1;
    padding: 0 4px; color: inherit; opacity: 0.7; border-radius: 99px; }
.uc-chip-remove:hover { opacity: 1; }
.uc-chip-remove:focus-visible { outline: 2px solid currentColor; outline-offset: 1px; }
.uc-chips-empty { margin: 0 0 8px; font-size: 13px; color: var(--p-muted); }
.uc-chips-add { margin-bottom: 8px; }
/* + ADD CATEGORY AND + ADD ORGANIZER SHOW THEIR STATE (3.113.1). The chevron
   (drawn pointing right) turns down when shut and up when open, and the open
   button wears the hover face with an inset shadow, so it reads as pressed.
   portal.js sets aria-expanded; the rule keys on it. (Pending's Dismissed
   toggle shared this until 3.113.2, when Dismissed became a tab.) */
.uc-chips-add .uc-btn .uc-disclosure-chevron { transform: rotate(90deg); }
.uc-chips-add .uc-btn[aria-expanded="true"] .uc-disclosure-chevron { transform: rotate(-90deg); }
.uc-chips-add .uc-btn[aria-expanded="true"] {
    background: var(--p-btn-face-hover); border-color: var(--uc-accent-text);
    box-shadow: inset 0 2px 3px rgba(55, 52, 51, 0.22); }
/* The checkbox list, once folded away behind the Add button. Without script it
   is simply the visible control it has always been. */
.uc-chips-source { grid-template-columns: 1fr; max-height: 220px; overflow-y: auto;
    padding: 8px 10px; border: 1px solid var(--p-border); border-radius: 8px; background: #fff; }

/* ---------- Location ---------- */
.uc-location-field .uc-check { margin-bottom: 6px; }
.uc-location-venue, .uc-location-custom { margin: 0 0 12px 22px; }
.uc-location-on .uc-location-venue[hidden], .uc-location-on .uc-location-custom[hidden] { display: none; }

/* The online tick and what it swaps in.
   [hidden] IS RESTATED AS display:none HERE for the same reason it is above:
   these panels are display:flex/grid children in the bento layout, and a flex
   item's `display` beats the UA sheet's `[hidden] { display: none }`, so the
   attribute alone leaves the panel on screen. Only under .uc-location-on, so
   with scripting off nothing is hidden and every control still submits. */
.uc-online-check { margin-bottom: 4px; }
.uc-online-panel { margin: 0 0 12px 22px; padding-top: 4px; }
.uc-online-panel input[type="url"] { width: 100%; }
.uc-location-on .uc-online-panel[hidden],
.uc-location-on .uc-location-place[hidden] { display: none; }

/* ---------------------------------------------------------------------------
   THE TIME CONTROL: AN HOUR LIST BESIDE A MINUTE LIST (3.98.0).

   `<input type="time">` IS GONE FROM ALL TWELVE. Its `step` is a VALIDATION
   rule, not a picker rule: every browser enforces it on submit and none makes
   its spinner or its dropdown honour it, so a five-minute step was refusing
   6:07 while still needing thirty presses to reach 6:30. That is why this was
   asked for twice and "fixed" twice.

   TWO NATIVE SELECTS, so `:where(.uc-portal) :where(select)` above gives them
   the chevron and the end cap with no rule here, and the keyboard, the
   type-ahead and the phone's own wheel are the platform's.

   THE HOUR IS WIDER THAN THE MINUTE because "12 a.m." is a longer word than
   ":05", and `2fr 1fr` is that ratio said once rather than two widths guessed
   twice. Below 320px they stack, which is where the pair stops fitting beside
   a field label.
   ------------------------------------------------------------------------ */
.uc-timepick { display: grid; grid-template-columns: 2fr 1fr; gap: 8px; align-items: center; }
.uc-timepick select { width: 100%; min-width: 0; }
@media (max-width: 320px) {
    .uc-timepick { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------------------
   THE VIDEO PREVIEW (3.98.0).

   IT REPLACES A SENTENCE WITH A URL IN IT. The series case used to read "Leave
   this empty and the series video plays here: https://..." , which asks
   somebody to read an address and picture the video. Showing it is shorter and
   is the actual answer.

   16:9 BY ASPECT-RATIO, NOT BY THE PADDING TRICK. Both services hand back a
   16:9 player, and `aspect-ratio` on the wrapper with the frame filling it is
   the declaration that says so once. The old percentage-padding idiom needs an
   absolutely positioned child, and an absolutely positioned iframe inside a
   flex column is the shape that collapsed the card in 3.24.1.

   CAPPED, BECAUSE IT IS A PREVIEW. 420px is about the width at which a
   thumbnail stops being a check and starts being something somebody watches in
   the editor, and the field it sits in is a form control rather than a player.
   ------------------------------------------------------------------------ */
.uc-video-preview { display: flex; flex-direction: column; gap: 6px; margin: 0 0 12px; }
.uc-video-preview[hidden] { display: none; }
.uc-video-preview-note[hidden] { display: none; }
.uc-video-frame {
    width: 100%; max-width: 420px;
    aspect-ratio: 16 / 9;
    background: var(--p-sunken, #EDEDED);
    border: 1px solid var(--p-edge, #8C8D8E);
    border-radius: 10px;
    overflow: hidden;
}
.uc-video-frame iframe { display: block; width: 100%; height: 100%; border: 0; }

/* ---------------------------------------------------------------------------
   CAPACITY IS ONE ROW (3.98.0).

   It was two fields in two places, "Places in person" under the address and
   "Places online" under the meeting link, each beside the thing it limits. On a
   hybrid event that put the two halves of ONE decision, how many people are
   coming, at opposite ends of the card with a venue picker between them.

   ONE LABEL, ONE OR TWO BOXES. A non-hybrid event shows one box and no format
   name, because with one box the row's own label is the whole name. Ticking
   hybrid reveals the second box and both format names.

   THE BOXES SHARE THE ROW EQUALLY AND HAVE A FLOOR. `1 1 0` with a
   `min-width` is the pair that makes two number inputs split a row without
   either collapsing: a bare `flex: 1` lets an input shrink below its own
   intrinsic width, and a number input that has lost its spinner is a box
   nobody can tell is editable. Below 380px they stack, which is the width at
   which two boxes and their labels stop fitting side by side.
   ------------------------------------------------------------------------ */
.uc-capacity-boxes { display: flex; gap: 12px; align-items: flex-end; }
.uc-capacity-box { display: flex; flex-direction: column; gap: 4px; flex: 1 1 0; min-width: 120px; }
/* THE HELPER STEP, 12/400 MUTED, not a second field label. These name the two
   boxes under the row's own "Capacity", so they sit BELOW it in the hierarchy;
   13/600 would have made them equal to the label they sit under, and 12/600 is
   between two steps, which is what type-scale-sweep.php refuses. */
.uc-capacity-box-label { font-size: 12px; font-weight: 400; color: var(--p-muted); }
.uc-capacity-box input[type="number"] { width: 100%; }
.uc-capacity-box[hidden],
.uc-capacity-box-label[hidden] { display: none; }
@media (max-width: 380px) {
    .uc-capacity-boxes { flex-wrap: wrap; }
}

/* ---------------------------------------------------------------------------
   CATEGORIES (Series & Categories screen).

   Each row leads with the thing the category actually IS on the calendar: its
   colour, with its icon inside. A row that describes a colour in words and
   never shows it makes the manager save and go and look.
   ------------------------------------------------------------------------- */
.uc-cat-list { list-style: none; margin: 0; padding: 0; }
.uc-cat-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px;
    padding: 12px 0; border-top: 1px solid var(--p-border); }
.uc-cat-row:first-child { border-top: 0; }
.uc-cat-row-open { display: block; background: var(--p-bg); border-radius: 10px; padding: 14px 14px 16px; }
.uc-cat-swatch { display: inline-flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; border-radius: 9px; flex: 0 0 auto;
    background: var(--cat, #16BECF); color: var(--cat-ink, #373433); }
.uc-cat-id { flex: 1 1 240px; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.uc-cat-id .uc-muted { font-size: 12px; }
.uc-cat-actions { display: flex; align-items: center; gap: 10px; }
.uc-cat-actions form { margin: 0; }
.uc-cat-new { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--p-border); }
.uc-cat-form { display: flex; flex-direction: column; gap: 14px; max-width: 520px; }
.uc-cat-form-actions { display: flex; gap: 10px; align-items: center; }
.uc-cat-icon select { max-width: 260px; }

/* THE PALETTE IS THE PICKER. Ten radios, and nothing else can be chosen: a free
   hex field is a way to put an off-brand colour on the public calendar. The
   dot carries the colour; the accessible name is the colour's brand name, in
   the visually hidden span beside it. */
.uc-swatches { display: flex; flex-wrap: wrap; gap: 8px; }
.uc-swatch { position: relative; display: inline-flex; }
.uc-swatch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.uc-swatch-dot { display: block; width: 30px; height: 30px; border-radius: 50%;
    background: var(--cat); border: 1px solid var(--p-border-strong); cursor: pointer; }
.uc-swatch input:hover + .uc-swatch-dot { transform: scale(1.08); }
/* The chosen one is ringed rather than merely brighter, because two of the ten
   are pale enough that a brightness change would be invisible on them. */
.uc-swatch input:checked + .uc-swatch-dot {
    box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--uc-accent-text); }
.uc-swatch input:focus-visible + .uc-swatch-dot {
    outline: 2px solid var(--uc-accent-text); outline-offset: 3px; }

/* ---------------------------------------------------------------------------
   CHOOSING AN ICON BY LOOKING AT IT (3.76.0)

   The same arrangement as the swatches above, for the same reason: a closed set
   of things somebody has to SEE to choose between. The radio is the control and
   is visually hidden; the face beside it is what gets drawn and what carries
   the chosen and focused states.

   THE NAME STAYS UNDER THE GLYPH rather than becoming a tooltip. Thirty
   pictograms with no words is a memory test, and the title attribute is a
   mouse affordance a keyboard and a phone never see. Both, and the glyph
   leads.
   ------------------------------------------------------------------------ */
.uc-icon-choice { margin-top: 4px; }
.uc-icon-choice-head {
    margin: 12px 0 6px;
    font-size: 13px; font-weight: 600;
    color: var(--p-muted, #6B6764);
}
.uc-icon-choice-head:first-child { margin-top: 0; }
.uc-icon-choice-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
    gap: 6px;
}
.uc-icon-pick { position: relative; display: block; margin: 0; }
.uc-icon-pick input {
    position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer;
}
.uc-icon-pick-face {
    display: flex; flex-direction: column; align-items: center; gap: 4px;
    padding: 10px 4px;
    border: 1px solid var(--p-border); border-radius: 8px;
    background: var(--p-surface, #fff);
    color: var(--p-text);
    cursor: pointer;
    text-align: center;
}
.uc-icon-pick input:hover + .uc-icon-pick-face { background: var(--p-surface-2, #f6f7f8); }
/* Ringed and tinted, which is the chosen state the swatches use one of and the
   segmented control uses the other. Both here because a glyph is a shape rather
   than a colour: a ring alone reads as focus, and a tint alone is easy to miss
   in a grid of thirty. */
.uc-icon-pick input:checked + .uc-icon-pick-face {
    border-color: var(--uc-accent-text);
    box-shadow: inset 0 0 0 1px var(--uc-accent-text);
    color: var(--uc-accent-text);
}
.uc-icon-pick input:focus-visible + .uc-icon-pick-face {
    outline: 2px solid var(--uc-accent-text); outline-offset: 2px;
}
.uc-icon-pick-name { font-size: 12px; line-height: 1.25; }

/* ---------------------------------------------------------------------------
   A LIST THAT FOLDS AWAY (3.76.0)

   The Series and Categories lists, so the form under them is reachable without
   scrolling past twenty-five rows. A native <details>, so it works with nothing
   running; sfaf_fold_open() decides which way it starts, from the row count
   rather than from a decision per screen.

   THE SUMMARY IS THE CARD HEAD, which is why it takes that class as well: the
   band was already there and this is the same band with a chevron in it and a
   press attached. A second head above the real one would be two titles.

   list-style: none AND the ::-webkit-details-marker rule, because the default
   triangle is drawn by two different mechanisms depending on the browser and
   removing one leaves the other.
   ------------------------------------------------------------------------ */
.uc-list-fold { display: block; }
.uc-list-fold-head {
    display: flex; align-items: center; gap: 8px;
    cursor: pointer;
    list-style: none;
}
.uc-list-fold-head::-webkit-details-marker { display: none; }
.uc-list-fold-head:focus-visible {
    outline: 2px solid var(--uc-accent-text); outline-offset: -2px;
}
/* The chevron points down when shut and up when open, which is the direction
   every other disclosure in this file uses. */
.uc-list-fold > .uc-list-fold-head .uc-disclosure-chevron {
    display: inline-flex; transition: transform 120ms ease-out;
}
.uc-list-fold[open] > .uc-list-fold-head .uc-disclosure-chevron { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
    .uc-list-fold > .uc-list-fold-head .uc-disclosure-chevron { transition: none; }
}

/* ---------- Series schedule: the past, folded away ---------- */
.uc-schedule-pastfold { margin-top: 20px; padding-top: 14px; border-top: 1px solid var(--p-border); }
.uc-schedule-pastfold > summary { cursor: pointer; font-family: var(--uc-font-heading);
    font-size: 14px; font-weight: 600; color: var(--uc-accent-text); }
.uc-schedule-pastfold > summary:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: 2px; }

/* ---------- Venues screen ----------
   Four address fields, sized to what goes in them: street takes the room, ZIP
   and state do not need any. Below 720px they stack, because a two-character
   state box beside a full street on a phone is worse than a list. */
.uc-venue { padding: 14px 0; border-top: 1px solid var(--p-border); }
.uc-venue:first-of-type { border-top: 0; }
.uc-venue-grid { display: grid; gap: 12px;
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1.6fr) minmax(0, 1.1fr) 90px 110px; }
.uc-venue-grid .uc-field input { width: 100%; }
.uc-venue-composed { margin-top: 10px; }
/* THE EDITOR'S ADDRESS (3.107.0): the place name takes its own row, so its
   placeholder label is never cut, and the four address boxes share the next. */
@media (min-width: 901px) {
    .uc-location-grid { grid-template-columns: minmax(0, 1.6fr) minmax(0, 1.1fr) 90px 110px; }
    .uc-location-grid > .uc-field:first-child { grid-column: 1 / -1; }
}
@media (max-width: 900px) {
    .uc-venue-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
    .uc-venue-name, .uc-venue-street { grid-column: 1 / -1; }
}
@media (max-width: 520px) {
    .uc-venue-grid { grid-template-columns: minmax(0, 1fr); }
    .uc-venue-name, .uc-venue-street { grid-column: auto; }
}
.uc-venue-actions { display: flex; align-items: center; gap: 14px; margin-top: 10px; }
.uc-venue-delete { margin-top: 8px; }
.uc-venue-new { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--p-border); }
.uc-venue-new > summary { cursor: pointer; color: var(--uc-accent-text); font-weight: 600; }

/* ---------- FAQ card ---------- */
/* .uc-faq-saveset and .uc-offscreen-form went with "Save these as a set" in
   3.63.0. The offscreen rule existed only for that control's hidden form and
   had no other user, so it went with it rather than being left as a class
   nothing carries. */

/* The search box says it is working, since a submit is a page load. */
.uc-filters-bar.uc-searching input[type="search"] { opacity: 0.7; }

/* ---------- The schedule (series screen) ---------- */
.uc-schedule-sentence { margin: 0 0 14px; font-family: var(--uc-font-heading, inherit); font-size: 16px; font-weight: 600; }
/* Four actions now, and the fourth (Remove) lives on each row. The three that
   fold are one family and read as one, rather than as two controls and a new
   thing bolted on beside them. */
.uc-schedule-edit > summary, .uc-schedule-add > summary,
.uc-schedule-extend > summary { cursor: pointer; color: var(--uc-accent-text); font-weight: 600; margin-bottom: 8px; }
.uc-schedule-extend { margin-top: 10px; }
/* One field on its own row. `.uc-field input` is width: 100%, which is right in
   a two-up field row and reads as a fault when a single date field spans the
   whole card. Capped rather than dropped, so it still matches the date fields
   in the forms above it. */
.uc-schedule-extend .uc-field { max-width: 260px; }

/* ---------------------------------------------------------------------------
   THE PATTERN CONTROL: EACH FREQUENCY CARRIES ITS OWN PARAMETERS.

   The number field and the day circles sit INSIDE the radio's own label, so the
   row is one statement: "Every [2] week(s) on [M][W]". That is what lets the
   whole control work with no script at all, since every row is visible and the
   server reads sp_freq and ignores the rows that lost.

   .uc-radio-row is already `display: flex; align-items: center` with its span
   at `flex: 1 1 auto`, so the inline inputs need only to be allowed to sit on
   the text baseline and not to stretch. The wrap is what stops "Every [n]
   month(s) on the 14th" pushing the card wider on a narrow screen.
   ------------------------------------------------------------------------- */
.uc-sched-freq { display: flex; flex-direction: column; gap: 2px; margin-bottom: 14px; }
.uc-sched-freq .uc-radio-row span { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
/* `flex: 0 0 auto` against a flex item's default `0 1 auto`: the interval field
   declares width: 74px and, as a shrinkable item on a row that wraps, would be
   squeezed narrower than its own two digits before the row chose to wrap. */
.uc-sched-freq .uc-repeat-num { flex: 0 0 auto; }
/* Indented to the width of the radio and its gap, so the circles read as
   belonging to the Weekly row above rather than as a control of their own. */
.uc-sched-freq .uc-sched-days { margin: 2px 0 8px 24px; }
.uc-sched-freq .uc-repeat-nth { margin: 2px 0 4px 24px; }
.uc-sched-freq > .uc-hint { margin: 0 0 4px 24px; }

/* ---------------------------------------------------------------------------
   ADD A DATE: TWO ROUTES, PRESENTED AS TWO.

   They are deliberately different shapes, because they are different weights of
   action. The first folds open into a form, because it is three fields and is
   finished here. The second is a link out to the event editor and stays a link:
   dressing it as a second <details> would promise a form that is not there.
   ------------------------------------------------------------------------- */
.uc-schedule-routes { margin-top: 20px; padding-top: 14px; border-top: 1px solid var(--p-border); }
.uc-schedule-route { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; margin: 12px 0 0; }
.uc-schedule-route .uc-hint { margin: 0; }

/* ---------------------------------------------------------------------------
   THE PUBLISH PICKER (3.72.0).

   A LIST THAT SCROLLS RATHER THAN A PAGE THAT DOES. The import's biggest series
   carries dozens of upcoming drafts, and a bare list of them would push the
   button that acts on them off the bottom of the screen. The cap is on the LIST
   and the button sits under it, so what somebody is about to press is always in
   view beside what it is about to do.

   NO container-type HERE. 3.24.1: size containment zeroes an element's
   intrinsic size, and this list is a flex/grid child in the schedule column.
   max-height and overflow are what is wanted and they cost nothing.

   AN INELIGIBLE ROW HAS NO BOX, so it is indented to the column the ticked rows'
   text starts in rather than left hanging where a control would be. It reads as
   part of the same list, which it is, rather than as a row whose control failed
   to render.
   ------------------------------------------------------------------------- */
.uc-publish-picker { margin-top: 10px; }
.uc-publish-all { margin: 0 0 8px; font-weight: 600; }

.uc-publish-list {
    margin: 0 0 14px; padding: 4px 0;
    list-style: none;
    max-height: 340px; overflow-y: auto;
    border-top: 1px solid var(--p-border);
    border-bottom: 1px solid var(--p-border);
}
.uc-publish-row { margin: 0; padding: 5px 2px; font-size: 13px; line-height: 1.4; }
.uc-publish-row + .uc-publish-row { border-top: 1px solid var(--p-border); }
.uc-publish-row .uc-check { margin: 0; align-items: flex-start; gap: 8px; }

/* The date column is fixed so the titles line up down the list and the eye can
   run the dates on their own. tabular-nums keeps the digits from shifting. */
.uc-publish-when { flex: 0 0 auto; min-width: 116px; font-weight: 600; font-variant-numeric: tabular-nums; }
.uc-publish-when .uc-muted { font-weight: 400; }
.uc-publish-title { flex: 1 1 auto; }

.uc-publish-row.is-blocked {
    display: flex; align-items: flex-start; gap: 8px;
    /* The width of a checkbox plus its gap, so this row's date starts where a
       ticked row's date does. */
    padding-left: 26px;
    color: var(--p-muted, #6B6764);
}
/* THE REASON IS THE POINT OF THE ROW, so it is not muted twice over: the row is
   already grey and a fainter reason inside it would be the least readable thing
   on the screen. It keeps full-strength ink and gets its emphasis from the
   surface rather than from weight.

   12px / 400 IS THE HELPER STEP, and it is deliberately not 12px / 600. That
   pair sits between two rungs of the scale in DESIGN.md and
   .claude/type-scale-sweep.php refuses it, correctly: the honest ways to make
   this stand out more are a step up in size or a stronger surface, not a weight
   nothing else in the file uses at this size. The pill is the surface. */
.uc-publish-why {
    flex: 0 0 auto; margin-left: auto;
    font-size: 12px; font-weight: 400;
    color: var(--p-text);
    background: var(--p-surface-2, #f6f7f8);
    border: 1px solid var(--p-border);
    border-radius: 999px; padding: 1px 9px;
}

/* Nothing ticked. The button says what it would do, which is nothing. */
.uc-publish-picker button[disabled] { opacity: 0.55; cursor: not-allowed; }

@media (max-width: 560px) {
    /* The date and the title stack, so neither is truncated on a phone. */
    .uc-publish-row .uc-check { flex-wrap: wrap; }
    .uc-publish-when { min-width: 0; flex-basis: 100%; }
    .uc-publish-row.is-blocked { flex-wrap: wrap; }
    .uc-publish-why { margin-left: 0; }
}
.uc-schedule-list { list-style: none; margin: 0; padding: 0; }
.uc-schedule-row { display: grid; grid-template-columns: minmax(150px, 1.1fr) minmax(120px, 1fr) minmax(120px, 1fr) auto;
                   gap: 10px; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--p-border); font-size: 14px; }
.uc-schedule-row:last-child { border-bottom: none; }
.uc-schedule-date { font-weight: 600; }
.uc-schedule-time, .uc-schedule-meta { font-size: 13px; color: var(--p-muted); }
.uc-schedule-actions { display: flex; align-items: center; gap: 8px; justify-self: end; }
.uc-schedule-actions form { margin: 0; }
/* A date somebody chose rather than one the pattern produced. Tagged rather
   than left to the muted meta line, because this is the row a manager goes
   looking for when they wonder why one date did not move with the others, and
   it has to be findable by eye down a list of twenty. The Purple family's
   measured pair, 6.02:1, from sfaf_category_shades(); no new colour. */
.uc-tag-extra { display: inline-block; padding: 1px 8px; border-radius: 999px;
    background: #F1EAF4; color: #7F3A98; font-size: 11px; font-weight: 700;
    letter-spacing: 0.01em; }
/* A warning that is read before a button is pressed rather than after. Amber,
   like .uc-scope-banner-all and .uc-flash-attention, which are the other two
   "this will do something wide" surfaces. #92400E on #FFFBEB is 7.53:1. */
.uc-hint-warn { background: #fffbeb; color: #92400e; border: 1px solid #fcd34d;
    border-radius: 8px; padding: 8px 11px; }
/* The past is legible and plainly finished, not disabled-looking: nothing there
   offers an action, so nothing has to look switched off. */
.uc-schedule-past .uc-schedule-row { opacity: 0.72; }
@media (max-width: 720px) {
    .uc-schedule-row { grid-template-columns: 1fr auto; }
    .uc-schedule-time, .uc-schedule-meta { grid-column: 1 / 2; }
}

.uc-user-fixed { display: flex; flex-direction: column; gap: 4px; font-size: 12px; max-width: 260px; }
.uc-user-fixed .uc-field-label { color: var(--p-muted); }
.uc-check-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 6px; margin-top: 8px; }
/* No size override. 13px is the FIELD LABEL's size, so a checkbox in a grid
   rendered at exactly the size of the label above it. Density comes from the
   6px gap, not from shrinking the type below its step. */
.uc-check-grid .uc-check { margin-bottom: 0; }
/* Save and Remove, together, in the row's third column. .uc-user-remove is
   gone: it was a second form rendered after the row's closing tag, which is
   what put a bare "Remove" link under the list instead of against a person. */
.uc-user-actions { display: flex; align-items: center; gap: 14px; justify-content: flex-end; }

/* ---------------------------------------------------------------------------
   THE CONFIRMATION DIALOG.

   Sized to a question, not to a form: this asks one thing and offers two
   answers. Cancel is first in the source so showModal() lands focus on the
   safe one, and the destructive answer carries the danger colour rather than
   the primary yellow, which is reserved for the action a screen is FOR.
   --------------------------------------------------------------------------- */
.uc-confirm-modal { width: min(440px, calc(100vw - 32px)); max-width: none; padding: 0;
    border: 0; border-radius: 12px; background: #fff; color: var(--p-text, #1a1d21);
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.28); }
.uc-confirm-modal::backdrop { background: rgba(15, 23, 42, 0.55); }
.uc-confirm-msg { margin: 0; padding: 22px 24px 18px; font-size: 15px; line-height: 1.5; }
.uc-confirm-actions { display: flex; justify-content: flex-end; gap: 10px;
    padding: 0 24px 20px; }

/* ---------------------------------------------------------------------------
   THE EMAIL QUESTION (3.42.0)

   Wider than a plain confirmation because it carries a list: this one has to
   say what changed as well as what will happen, and old-to-new on one line is
   the whole point of showing it at all.

   THE TWO ANSWERS ARE THE SAME SIZE AS EACH OTHER, deliberately. Only one of
   them wears the primary colour, because it is the one that does the thing the
   dialog is named for, but neither is bigger and neither is pre-focused. The
   fault being fixed was mail going out by inaction, so nothing here should be
   reachable by pressing Return without reading.

   The values use ink and a strikethrough to separate old from new rather than
   weight, because 14px/600 is the card heading's step and a value in a list is
   not a heading. See DESIGN.md.
   --------------------------------------------------------------------------- */
.uc-notify-modal { width: min(520px, calc(100vw - 32px)); }
.uc-notify-modal-title { margin: 0; padding: 22px 24px 0; font-size: 20px; font-weight: 700; }
.uc-notify-modal .uc-confirm-msg { padding-top: 10px; padding-bottom: 14px; }
.uc-notify-changes { margin: 0 24px 18px; padding: 14px 16px; list-style: none;
    display: grid; gap: 12px; border-radius: 10px; background: var(--p-surface-2, #f6f7f8); }
.uc-notify-changes li { display: grid; gap: 3px; }
.uc-notify-change-label { font-size: 13px; font-weight: 600; }
.uc-notify-was { color: var(--p-muted, #6B6764); text-decoration: line-through; }
.uc-notify-arrow { color: var(--p-muted, #6B6764); padding: 0 4px; }
.uc-notify-changes li > span:not(.uc-notify-change-label) { display: inline; }
.uc-notify-actions { flex-wrap: wrap; }

/* ---------- Settings ---------- */
.uc-settings-section h2 { margin-bottom: 14px; }
.uc-settings-section .uc-field { margin-bottom: 12px; }
.uc-route { display: flex; align-items: center; gap: 12px; padding: 10px 0; flex-wrap: wrap; border-bottom: 1px solid var(--p-border); }
.uc-route:last-child { border-bottom: none; }
.uc-route .uc-check { margin-bottom: 0; min-width: 200px; }
.uc-route input[type=email], .uc-route input[type=url] { flex: 1; min-width: 220px; }
.uc-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--p-gray); flex-shrink: 0; }
.uc-dot.on { background: var(--p-green); box-shadow: 0 0 6px rgba(16,185,129,0.4); }
.uc-repeater-rows { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
.uc-repeater-row { display: flex; gap: 8px; align-items: center; }
.uc-repeater-row input { flex: 1; }
.uc-map-row { display: flex; flex-direction: column; gap: 6px; padding: 10px 0; border-bottom: 1px solid var(--p-border); }
.uc-map-cat { font-weight: 600; font-size: 13px; }
.uc-tier { margin-top: 14px; padding: 12px 14px; background: #eff6ff; border: 1px solid #bfdbfe; border-radius: 8px; font-size: 13px; color: #1e40af; }
.uc-series-thumb img { width: 60px; height: 40px; object-fit: cover; border-radius: 4px; display: block; }
.uc-series-thumb-none { display: inline-flex; align-items: center; justify-content: center; width: 60px; height: 40px; border-radius: 4px; background: var(--p-bg); font-size: 18px; }
.uc-img-source-tag { font-size: 11px; font-weight: 600; color: var(--p-muted); background: var(--p-bg); border: 1px solid var(--p-border); border-radius: 99px; padding: 1px 8px; margin-left: 6px; }
/* ---------------------------------------------------------------------------
   THE FAQ REPEATER ROW: QUESTION ABOVE ANSWER, NOT BESIDE IT.

   THIS WAS NEVER WRITTEN BEFORE 3.54.0. `git log -S` over this rule returns two
   commits, the 2.0 baseline and 2.8.0, and neither gave the row a direction; the
   `-G` form returns the same two. So the change was not written and reverted and
   not written and overridden. It simply never reached the file, which is the
   third possibility and the one worth checking first.

   WHAT THE FLEX ROW COST. `.uc-repeater-row` is `display: flex` with a default
   `row` direction, so a question sat in a `flex: 1` box beside an answer at
   `flex: 2` and truncated mid-word at any realistic length. Overriding the
   direction here rather than widening the input is the fix, because no width
   makes a one-line field the right shape for the thing above a paragraph.

   THE REMOVE BUTTON COMES OUT OF THE FLOW. In a column it would otherwise
   become a third full-width band under the answer, which reads as an action on
   the form rather than on the row. Absolutely positioned against the row's own
   corner, it stays attached to what it removes.
   ------------------------------------------------------------------------- */
/* A LIGHT NEUTRAL GROUND, SO A ROW READS AS ONE UNIT.
 *
 * It was --p-panel, which is #ffffff, sitting on a white card behind a 1px
 * outline, so four rows ran together into one field of boxes. The fields stay
 * white inside it, which is what makes the grouping legible: the row is the
 * ground and the controls sit on it.
 *
 * NEUTRAL, AND CARRYING NOTHING. 3.38.0 stripped the decorative teal edge off
 * every caladmin card on the rule that colour or shape must not be the sole
 * carrier of a fact. This background groups a row and means nothing else, so it
 * is the same gray the page already uses and gets no accent, no left border and
 * no tint. If it ever looks like it is saying something, it is wrong. */
.uc-faq-row {
    position: relative;
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    padding: 16px 16px 14px;
    background: var(--p-bg);
    border: 1px solid var(--p-border);
    border-radius: 10px;
}
/* The row itself sits on the page tint, so the two fields inside it have to
   say white deliberately rather than inherit it. The baseline already does;
   this is the case where the surface UNDER the control is not white and the
   statement "white means you type in this" needs restating. */
.uc-faq-row input[type=text],
.uc-faq-row textarea { background-color: var(--p-control-face); }
/* The editor is an iframe in a chrome of its own, so the white has to be asked
   for on the wrapper rather than inherited through it. */
.uc-faq-row .wp-editor-container { background: var(--p-panel); }

/* THE REMOVE CONTROL, UNDER THE ROW.
 *
 * It was a small red x absolutely positioned in the corner: hard to hit, easy
 * to hit by accident, and unlabelled. Removing somebody's typed work should be
 * findable and deliberate, so it is a button with words on it, at the end of
 * the row it acts on. Right-aligned, because it is not the thing to do here. */
.uc-faq-row-actions { display: flex; justify-content: flex-end; margin-top: 2px; }

/* The rows carry their own separation now, so the stack's own gap would be
   doubling it. Only the FAQ variant is boxed; every other repeater keeps the
   tight 8px list it was designed as. */
.uc-repeater-rows:has(.uc-faq-row) { gap: 14px; }

/* Full width. The 44px of right padding went with the corner button it was
   keeping a long question out from under. */
.uc-faq-row input[type=text] { flex: none; width: 100%; }

/* DANGER AS INK, NOT AS FILL. A solid red button on every row would be a wall
   of red on a set of ten, and the row is not a dangerous place to be. The
   neutral button carries a red word, and the confirmation carries the weight.
   Declared as a pair, so the two never come apart: 3.39.0 split a fill from its
   ink across two declarations and got red on red at 1.19:1. */
.uc-faq-row .uc-faq-remove { color: var(--p-danger-text); background: var(--p-btn-face); }
.uc-faq-row .uc-faq-remove:hover { color: #fff; background: var(--p-danger-text); border-color: var(--p-danger-text); }

/* TALLER. A box that scrolls inside a page that scrolls is the thing being
   fixed, so the floor is a real paragraph rather than three lines.
   `resize: vertical` is the baseline's, on every textarea in the portal, and
   is the no-script fallback's grip; the editor's own is TinyMCE's, turned on
   in SFAF_Rich_Text::settings(). They are separate mechanisms for one gesture
   and neither is declared here any more. */
.uc-faq-row textarea {
    flex: none;
    width: 100%;
    min-height: 180px;
    line-height: 1.5;
}

/* The editor replaces the textarea rather than wrapping it, so the breathing
   room has to be asked for on the wrapper it puts there instead. */
.uc-faq-row .wp-editor-wrap { width: 100%; }
.uc-faq-row .wp-editor-container { border-radius: 7px; overflow: hidden; }

/* Event form: featured image picker */
.uc-image-field .uc-field-label { font-size: 13px; font-weight: 600; display: block; margin-bottom: 6px; }
.uc-image-preview { margin-bottom: 10px; }
.uc-image-preview img { max-width: 280px; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; border-radius: 10px; border: 1px solid var(--p-border); display: block; }
.uc-image-buttons { display: flex; gap: 8px; align-items: center; margin-bottom: 10px; }
.uc-image-url-field { margin-top: 4px; }

/* ---------------------------------------------------------------------------
   ENTRANCE.

   EVERYTHING HANGS OFF html.uc-anim, WHICH IS SET IN THE HEAD, BEFORE THE
   FIRST PAINT. See the inline script in SFAF_Portal::head() for why it is
   there and not in portal.js. The short version: in 3.16.0 these classes were
   added on DOMContentLoaded, which is after the page has already painted
   itself complete, so the "entrance" was really a flicker back to zero and up
   again; and the call that added them was last in a chain of nineteen
   initialisers, any one of which could take it out by throwing.

   NO SCRIPT IS INVOLVED PAST THAT POINT. The stagger is :nth-child, not a
   custom property written by JavaScript, so once the class is on <html> the
   whole thing is CSS and nothing in portal.js can break it.

   NOTHING IS HIDDEN BY A BASE RULE. The hidden state lives in the animation's
   `from` with `both` fill, so with scripting off html.uc-anim never appears,
   no animation applies, and the page is a normal finished visible page. There
   is no arrangement in which content waits invisibly to be revealed.

   TRANSFORM AND OPACITY ONLY. No height, no margin, no top. Both are
   composited and neither causes layout, so nothing on the page moves while a
   card settles, which is the actual complaint about entrance animations rather
   than their length.
   ------------------------------------------------------------------------- */
@keyframes uc-rise { from { opacity: 0; transform: translate3d(0, 8px, 0); } to { opacity: 1; transform: none; } }
@keyframes uc-slide-in { from { opacity: 0; transform: translate3d(-10px, 0, 0); } to { opacity: 1; transform: none; } }

/* Sidebar: 30ms apart, from the left. --uc-nav-i is set on each item in PHP,
   so a new nav entry needs no CSS. .uc-anim-nav is a SECOND class, set only on
   the session's first load: every screen here is a full page load, and an
   unconditional stagger would replay on every click. */
.uc-anim-nav .uc-nav-item {
    animation: uc-slide-in 260ms cubic-bezier(0.16, 0.84, 0.44, 1) both;
    animation-delay: calc(var(--uc-nav-i, 0) * 30ms);
}
.uc-anim-nav .uc-portal-brand,
.uc-anim-nav .uc-portal-foot {
    animation: uc-slide-in 260ms cubic-bezier(0.16, 0.84, 0.44, 1) both;
}
.uc-anim-nav .uc-portal-foot { animation-delay: 240ms; }

/* Content: every top-level block of the screen, 300ms each, 40ms apart,
   ease-out, a few px of rise. The child selector is what makes this reach the
   page head, each card and each section without anything enumerating them, and
   what stops a card nested inside a section animating twice. */
.uc-anim .uc-portal-content > * {
    animation: uc-rise 300ms cubic-bezier(0.16, 0.84, 0.44, 1) both;
}
/* Capped at nine steps, so a long screen does not end with a card arriving
   most of a second after the page did. */
.uc-anim .uc-portal-content > *:nth-child(1) { animation-delay: 0ms; }
.uc-anim .uc-portal-content > *:nth-child(2) { animation-delay: 40ms; }
.uc-anim .uc-portal-content > *:nth-child(3) { animation-delay: 80ms; }
.uc-anim .uc-portal-content > *:nth-child(4) { animation-delay: 120ms; }
.uc-anim .uc-portal-content > *:nth-child(5) { animation-delay: 160ms; }
.uc-anim .uc-portal-content > *:nth-child(6) { animation-delay: 200ms; }
.uc-anim .uc-portal-content > *:nth-child(7) { animation-delay: 240ms; }
.uc-anim .uc-portal-content > *:nth-child(8) { animation-delay: 280ms; }
.uc-anim .uc-portal-content > *:nth-child(n+9) { animation-delay: 320ms; }

/* ASKED FOR IT, GET NONE OF IT. Belt and braces: the head script already
   refuses to set html.uc-anim when reduced motion is asked for, so none of the
   rules above can match. This is here for the case that matters more, a
   preference changed after the page loaded, and it is why the elements are
   given an explicit final state rather than merely animation: none. */
@media (prefers-reduced-motion: reduce) {
    .uc-anim-nav .uc-nav-item,
    .uc-anim-nav .uc-portal-brand,
    .uc-anim-nav .uc-portal-foot,
    .uc-anim .uc-portal-content > * { animation: none; opacity: 1; transform: none; }
}

/* ---------- Responsive ---------- */
@media (max-width: 900px) {
    .uc-form-grid { grid-template-columns: 1fr; }
    .uc-stats { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 720px) {
    .uc-portal-sidebar { position: fixed; left: -260px; top: 0; z-index: 100; transition: left 0.2s; box-shadow: 4px 0 24px rgba(0,0,0,0.2); }
    .uc-portal-sidebar.open { left: 0; }
    .uc-portal-menu-btn { display: block; }
    .uc-portal-content { padding: 18px; }
}

/* ---------------------------------------------------------------------------
   Third-party import queue (dashboard fetch report + Pending sub-sections)
   --------------------------------------------------------------------------- */
.uc-head-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* ONE DECLARATION, RECONCILING TWO (3.64.0). This was declared twice at the
   same specificity: `display: flex` up by the Users screen, so the add-user
   form could space its select and its button, and `display: inline` here, so a
   one-button form is transparent inside .uc-head-actions. The later one won,
   which meant the gap and the wrap up there had been dead the whole time and
   the Users form spaced its two controls with a space character.

   `inline-flex` is both: inline-level, so nothing about the one-button case
   changes, and a flex container, so the gap works. Inside .uc-head-actions it
   makes no difference at all, because a flex container blockifies its children
   whatever display they ask for. */
.uc-inline-form { display: inline-flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0; }

/* .uc-section-title is gone with 3.17.0. It was the second way of heading a
   card, a bare <h2> floating above the card it named, and it is what made the
   heading treatment look like it had been applied to some screens and not
   others. Everything it headed now has a .uc-card-head. */
/* Dark on SFAF yellow, 12.22:1. It was white on yellow at 1.38:1, which is
 * unreadable — the `#0E818C` fallback beside var(--uc-primary) never applied,
 * because --uc-primary is always defined a few lines above. Used on the two
 * pending-queue count chips and nowhere else. */
.uc-count-badge { display: inline-block; min-width: 20px; padding: 1px 8px; border-radius: 99px; background: var(--uc-primary, #FFD900); color: #1a1d21; font-size: 12px; font-weight: 700; text-align: center; }

.uc-source-badge { display: inline-block; padding: 2px 9px; border-radius: 99px; background: #e0f2f1; color: #0E818C; font-size: 11px; font-weight: 700; letter-spacing: .02em; white-space: nowrap; }
.uc-source-link { font-size: 12px; color: #6B7280; text-decoration: none; }
.uc-source-link:hover { text-decoration: underline; }

.uc-import-banner { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

.uc-card-muted { background: #f9fafb; }
.uc-help { margin: 0 0 12px; font-size: 13px; color: #6B7280; }

.uc-fetch-report { margin: 0; padding: 0; list-style: none; }
.uc-fetch-report > li { padding: 8px 0; font-size: 14px; }
.uc-fetch-report > li + li { border-top: 1px solid var(--uc-border, #e5e7eb); }
.uc-fetch-notes { margin: 6px 0 0 18px; padding: 0; list-style: disc; font-size: 12px; color: #6B7280; }
/* The status is in the sentence: summarize() writes "failed." and "not
   connected." A muted row for a source that did not run is dimming, not
   colour-coding, and stays. */
.uc-fetch-skip { color: #6B7280; }

/* Part B: refresh panel, change diff, removal-guard reporting */
.uc-flash-warn { background: #fef3c7; color: #92400e; }
.uc-flash-error { background: #fee2e2; color: #991b1b; }

.uc-refresh-panel { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 18px; }
.uc-refresh-panel .uc-flash, .uc-refresh-panel .uc-refresh-diff { flex-basis: 100%; margin-top: 4px; }
.uc-refresh-diff { font-size: 12px; }
.uc-refresh-diff td { vertical-align: top; word-break: break-word; }
.uc-diff-old { color: #6B7280; text-decoration: line-through; }
.uc-diff-new { color: #065f46; font-weight: 600; }

.uc-fetch-guard { margin: 6px 0 0; padding: 5px 9px; border-radius: 6px; background: #fef3c7; color: #92400e; font-size: 12px; }
.uc-fetch-guard-ok { background: #ecfdf5; color: #065f46; }

/* ---------------------------------------------------------------------------
   QUIET SUCCESS, LOUD FAILURE.

   Every row of this panel used to look the same: a left border in one of three
   colours and everything else at one weight. So "4 events updated" and "the
   source failed" were the same size, the same colour and the same distance
   from the edge, and the one row that needed to stop the reader did not.

   A failure now carries its own tint and states its line in the row's own
   weight. That is the whole difference: no icon, no second border, no box. The
   tint is the third instrument in the house order (space, hairline, tint), and
   it is reached for here because this is the one case on the screen where
   missing the row is the expensive outcome.
   --------------------------------------------------------------------------- */
.uc-fetch-line { font-weight: 600; }
.uc-fetch-fail { background: #fef2f2; border-radius: 0 6px 6px 0; }
.uc-fetch-fail .uc-fetch-line { color: #991b1b; }
.uc-fetch-skip .uc-fetch-line { font-weight: 500; }

/* WHICH EVENTS CHANGED. Subordinate to the summary line by size and colour,
   not by a box: this is supporting detail for the sentence above it, and a
   bordered panel here would be the third border in a card that already has
   one. Space and a quieter type size are enough to say "these belong to that". */
.uc-fetch-changed { margin: 6px 0 0; padding: 0 0 0 14px; list-style: none; font-size: 13px; }
.uc-fetch-changed > li { padding: 2px 0; }
.uc-fetch-changed > li + li { border-top: 1px solid var(--p-border); }
.uc-fetch-what { color: var(--p-muted); font-size: 12px; }
.uc-fetch-what::before { content: "changed: "; }
.uc-break { word-break: break-all; }

/* THE LAST AUTOMATIC FETCH, on the queue it fills.
 *
 * It borrows .uc-fetch-report and its three row states rather than growing a
 * second set: the manual report and this one are two accounts of the same job
 * and must not look like two different features. Only the box's own furniture
 * is here. */
/* 13/600 is the ladder's caption step. 12px is a step too, but only at 400, and
   this sits beside a 14px heading where 400 stops reading as a pair with it. */
.uc-lastrun-when { font-size: 13px; color: var(--p-muted); font-weight: 600; }
.uc-lastrun-summary { margin: 0; padding: 8px 0; font-size: 14px; }

/* ONE ALARM STYLE FOR BOTH FAULTS. A source that failed and a fetch that has
   not worked for an hour are the same news to somebody standing here — this
   queue is not what is live at the source — so they get one treatment and are
   told apart by what they say, not by which red they are. THE WORD IS IN THE
   TEXT: "failed", "nothing has fetched". Colour is never the only carrier, and
   this box is read by people who are looking for a reason to trust the queue. */
.uc-lastrun-alarm {
    margin: 0 0 10px;
    padding: 9px 12px;
    border-radius: 7px;
    background: #fef2f2;
    color: #991b1b;          /* 8.2:1 on that ground */
    font-size: 13px;
    line-height: 1.5;
}
.uc-lastrun-alarm + .uc-lastrun-alarm { margin-top: -2px; }

/* The cadence and where the rest of it lives. Quiet on purpose: it is the
   same two sentences on every load and must not compete with the run. */
.uc-lastrun-foot { margin: 8px 0 0; font-size: 12px; line-height: 1.5; color: var(--p-muted); }

/* ---------------------------------------------------------------------------
 * Field ownership states — locked, needs-attention, normal.
 *
 * NEVER COLOUR ALONE. Every state pairs its colour with an icon and with
 * words, so the meaning survives colour blindness, greyscale printing and a
 * forced-colours theme. "Normal" has no treatment at all: the absence of a
 * badge is what finished looks like, and a green tick on every completed
 * field would be noise on a form of twenty of them.
 *
 * Amber, never red, for the fields waiting on a person. A GoFundMe Pro
 * campaign arrives needing its image and description EVERY time by design, so
 * red would report a fault on every single import and quickly stop meaning
 * anything.
 * ------------------------------------------------------------------------ */
/* No margin here: .uc-field is a flex column with its own 6px gap, and the
 * image box (above) adds its own spacing where it needs it. */
.uc-field > .uc-field-label { font-size: 13px; font-weight: 600; display: block; }
.uc-state-icon { vertical-align: -2px; flex: 0 0 auto; }

/* ---------------------------------------------------------------------------
 * Edit scope — chosen before editing, stated while editing.
 *
 * The banner is STICKY because that is the requirement, not a flourish: a
 * manager scrolling a long form has to be able to see "editing all 12 upcoming
 * occurrences" at the moment they reach the save button, not only at the moment
 * they chose it.
 * ------------------------------------------------------------------------ */
.uc-scope { border: 2px solid var(--uc-accent, #16BECF); border-radius: 12px;
    padding: 18px 20px; margin-bottom: 18px; background: #f8feff; }
.uc-scope-title { margin: 0 0 6px; font-size: 17px; }
.uc-scope-lead { margin: 0 0 14px; font-size: 14px; line-height: 1.6; }
.uc-scope-buttons { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }

/* Two stacked lines inside one button: the choice, and what it does to the
 * other occurrences. The consequence belongs on the control that causes it,
 * not in a paragraph below that the pointer is already past. */
.uc-scope-btn { flex: 1 1 220px; display: flex; flex-direction: column; align-items: flex-start;
    gap: 4px; text-align: left; font-weight: 600; padding: 12px 14px; height: auto; }
.uc-scope-btn-sub { font-weight: 400; font-size: 12px; line-height: 1.45; color: var(--p-muted); }
.uc-scope-btn-all { border-color: #fcd34d; background: #fffbeb; }
/* The amber is the fact that this choice touches every occurrence, so the
   hover has to stay amber. It names its own fill for the same reason the
   yellow primary does. #92400e on #fef3c7 is the pending-pill pair. */
.uc-scope-btn-all:hover { background: #fef3c7; border-color: #f59e0b; }
.uc-scope-btn-all .uc-scope-btn-sub { color: #92400e; }
.uc-scope-dismiss { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--p-border); }
.uc-scope-noscript { margin: 10px 0 0; font-size: 13px; color: #92400e; }

/* ---------------------------------------------------------------------------
 * The scope question as a modal.
 *
 * The <dialog> is created by portal.js and the .uc-scope block above is moved
 * into it, so these rules only ever apply once the enhancement has taken. The
 * dialog itself is a transparent frame: the panel inside keeps its own border,
 * padding and background, which is why the same markup reads correctly in
 * both places.
 *
 * No reset of the browser's focus trap, backdrop or Escape handling is needed
 * or wanted here. That is the point of using a real dialog.
 * ------------------------------------------------------------------------ */
.uc-scope-modal { width: min(560px, calc(100vw - 32px)); max-width: none; padding: 0;
    border: 0; background: transparent; overflow: visible; color: var(--p-text, #1a1d21); }
.uc-scope-modal::backdrop { background: rgba(15, 23, 42, 0.55); }
.uc-scope-modal .uc-scope { margin: 0; box-shadow: 0 24px 60px rgba(0, 0, 0, 0.28); }

/* The page behind a modal must not scroll under it. */
body.uc-modal-open { overflow: hidden; }

.uc-scope-banner { position: sticky; top: 0; z-index: 20;
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    background: #E6F9FB; color: #0E818C; border: 1px solid #16BECF;
    border-radius: 10px; padding: 10px 14px; margin-bottom: 16px;
    font-weight: 600; font-size: 14px; }
/* Amber for the consequential one. The wording says the count as well, so this
 * is reinforcement and never the only signal. */
.uc-scope-banner-all { background: #fffbeb; color: #92400e; border-color: #fcd34d; }

/* ---------------------------------------------------------------------------
   THE PER-FIELD PENCIL IS GONE (3.23.0), AND SO ARE ITS THREE RULES.

   .uc-field-pencil-locked, .uc-pencil and .uc-inert were the affordance for
   unlocking one field at a time after a scope had been chosen. The scope modal
   asks that question once, in front of everything else, so the pencil was the
   same question a second time and a click on every field of every recurring
   event. Deleted rather than hidden: a rule for a control nothing renders is
   the thing somebody restyles and then wonders why nothing changed.

   WHAT STAYS IS THE ONE THING THAT WAS NEVER A LOCK. A field the chosen scope
   FORBIDS is not waiting to be opened, because no gesture opens it: the scope is
   what forbids it and changing the scope is the answer. It is disabled, greyed,
   and carries its reason underneath, because a control that silently refuses
   reads as broken and one that opens and then quietly does nothing is worse.
   --------------------------------------------------------------------------- */
.uc-field-nobulk input, .uc-field-nobulk textarea, .uc-field-nobulk select {
    background-color: #F3F4F6; color: #6B7280; cursor: not-allowed; }

/* The locked fieldset carries no border of its own — it is a mechanism, not a
 * visible grouping. */
.uc-scope-fields { border: 0; margin: 0; padding: 0; min-width: 0; }
.uc-scope-fields[disabled] { opacity: .55; }

/* [hidden] HAS TO WIN. The badge and the note below both set an explicit
 * `display`, which outranks the browser's own `[hidden] { display: none }` —
 * so the live completeness check would set the attribute and nothing would
 * disappear. Everything the check hides and reveals goes through this. */
.uc-portal [hidden] { display: none !important; }

.uc-field-flag { display: inline-flex; align-items: center; gap: 4px; margin-left: 6px;
    padding: 1px 7px; border-radius: 999px; font-size: 11px; font-weight: 600; vertical-align: middle; }
.uc-flag-locked { background: #F3F4F6; color: #4B5563; border: 1px solid #D1D5DB; }
.uc-flag-attention { background: #fef3c7; color: #92400e; border: 1px solid #fcd34d; }

.uc-field-locked input, .uc-field-locked textarea, .uc-field-locked select {
    background-color: #F9FAFB; color: #4B5563; border-color: #D1D5DB; cursor: not-allowed; }
.uc-field-attention { border-left: 3px solid #f59e0b; padding-left: 10px; margin-left: -13px; }
.uc-field-attention input, .uc-field-attention textarea { border-color: #f59e0b; background: #fffbeb; }

.uc-field-note { display: flex; align-items: flex-start; gap: 6px; margin: 4px 0 8px;
    padding: 7px 10px; border-radius: 6px; font-size: 12px; font-weight: 400; line-height: 1.5; }
.uc-field-note-locked { background: #F3F4F6; color: #4B5563; }
.uc-field-note-attention { background: #fffbeb; color: #92400e; }

.uc-flash-attention { background: #fffbeb; color: #92400e; border: 1px solid #fcd34d;
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* CONTRAST FIX (2.9.0). This rule already said `color: #fff`, and it lost.
 *
 * `.uc-portal a` (0,1,1) outranks `.uc-btn-source` (0,1,0), so every anchor
 * wearing this class was painted with the portal link colour #0E818C over the
 * #92400e background: a measured 1.53:1, far below the 4.5:1 AA floor for
 * normal text and genuinely unreadable.
 *
 * The fix is specificity, not a new colour. `.uc-portal a.uc-btn-source`
 * (0,2,1) beats the link rule, so the white this always intended actually
 * applies: 7.09:1 on the base background and 9.37:1 on hover, both AA and AAA.
 *
 * SCOPED ON PURPOSE. `.uc-btn-source` is used on exactly one element, the
 * "Open the campaign page" link, so this cannot disturb any other button. The
 * same specificity clash does affect other portal anchors that carry .uc-btn,
 * but harmlessly: the only other one is "Log out", which lands on teal-on-
 * white at 4.63:1 and still passes. `.uc-btn-primary` on an anchor would be
 * 3.34:1 and would NOT pass, but nothing in the portal renders that
 * combination today. If one is ever added, give it the same treatment here
 * rather than reaching for a different colour.
 */
.uc-btn-source,
.uc-portal a.uc-btn-source { background: #92400e; color: #fff; border-color: #92400e; margin-left: auto; }
.uc-btn-source:hover,
.uc-portal a.uc-btn-source:hover { background: #7c2d12; color: #fff; border-color: #7c2d12; }

/* Locked FAQ rows from the platform. */
.uc-locked-faqs { border: 1px solid #E5E7EB; border-radius: 8px; padding: 12px; background: #F9FAFB; }
.uc-faq-row-locked input, .uc-faq-row-locked textarea {
    background: #fff; color: #4B5563; border-color: #E5E7EB; cursor: not-allowed; }

/* Pending-queue indicator. Hover AND focus, so it is usable by keyboard, on a
 * phone and by anyone not using a mouse. The aria-label on the wrapper names
 * the fields, so a screen reader gets the same sentence the tooltip shows. */
/* Still used by the "submitted for review" table on the same screen, which is
   a genuine table of five short columns. The imported queue is a list now and
   marks itself with .uc-queue-item-needs. */
.uc-row-needs td { background: #fffdf5; }
.uc-needs-flag { position: relative; display: inline-flex; color: #b45309; margin-left: 6px; cursor: help; }
/* 5.02:1, up from 2.15:1. This is the keyboard focus indicator on the
 * needs-attention icon, so it is the one ring a keyboard user has to be able to
 * see; #f59e0b failed even the 3:1 non-text floor. Same amber family, darker. */
.uc-needs-flag:focus { outline: 2px solid #b45309; outline-offset: 2px; border-radius: 3px; }
.uc-needs-tip { position: absolute; left: 50%; bottom: calc(100% + 6px); transform: translateX(-50%);
    white-space: nowrap; background: #1F2937; color: #fff; padding: 4px 8px; border-radius: 5px;
    font-size: 11px; font-weight: 500; opacity: 0; visibility: hidden; transition: opacity .12s; z-index: 20; }
.uc-needs-flag:hover .uc-needs-tip, .uc-needs-flag:focus .uc-needs-tip { opacity: 1; visibility: visible; }
.uc-source-link-strong { color: #b45309; font-weight: 600; }

@media (prefers-reduced-motion: reduce) { .uc-needs-tip { transition: none; } }

/* ---------------------------------------------------------------------------
 * FAQ sets panel (event editor) and the sets screen.
 * ------------------------------------------------------------------------ */
.uc-faq-set-panel .uc-card-head h2 { display: inline-flex; align-items: center; gap: 7px; }
.uc-faq-set-actions { display: flex; flex-wrap: wrap; gap: 22px; }
.uc-faq-set-actions > form { flex: 1 1 300px; min-width: 260px; display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.uc-field-inline { width: 100%; }
.uc-faq-set-actions .uc-hint { margin: 0; }

/* The picker inside the FAQ block. Boxed and tinted because it is a control
 * that writes into the rows underneath it rather than one more field in the
 * list, and it has to read as belonging to them. */
.uc-faq-picker { margin: 0 0 16px; padding: 12px 14px; background: var(--p-bg, #f6f8fa);
    border: 1px solid var(--p-border, #e3e7ec); border-radius: 10px; }
.uc-faq-picker-row { display: flex; align-items: flex-end; flex-wrap: wrap; gap: 10px; }
/* Its own class rather than .uc-field, on purpose: see the note in
   SFAF_Portal::faq_set_picker(). So it has to state the layout .uc-field would
   have given it. */
.uc-faq-picker-label { flex: 1 1 240px; display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.uc-faq-picker-label > .uc-field-label { font-size: 13px; font-weight: 600; color: var(--p-text); display: block; }
.uc-faq-picker-label select { width: 100%; }
.uc-faq-picker-row .uc-btn { flex: 0 0 auto; }
/* "Manage sets", moved here from the card that no longer exists (3.72.0). At
   the end of the row and pushed to the far edge, so it reads as the way out of
   this control rather than as a second thing to press in it. The bottom padding
   matches the button's, so a link and a button sitting on one baseline line up
   on their text rather than on their boxes. */
.uc-faq-picker-row .uc-faq-manage { flex: 0 0 auto; margin-left: auto; padding-bottom: 10px; }
.uc-faq-picker .uc-hint { margin: 8px 0 0; }

/* A locked recurrence fieldset reads as one unit, so the whole box is tinted
 * rather than each control being outlined separately. */
.uc-fieldset-locked { background: #F9FAFB; border-color: #D1D5DB; }
.uc-fieldset-locked legend { color: #4B5563; }

/* ---------------------------------------------------------------------------
 * Per-event notification list, and the automation screen.
 * ------------------------------------------------------------------------ */

/* A picker that stays a fixed height whether there are three calendar users or
 * thirty, so the Publish button does not move down the page as staff are added. */
.uc-notify-users { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 2px 18px;
    max-height: 220px; overflow-y: auto; padding: 8px 10px; border: 1px solid var(--p-border); border-radius: 8px; background: #fff; }
.uc-notify-list { margin: 4px 0 0; padding-left: 18px; font-size: 13px; line-height: 1.7; color: var(--p-text); }

/* ---------------------------------------------------------------------------
 * The notification picker.
 *
 * A <details> the browser opens and closes on its own, so the disclosure needs
 * no script. The rules below marked "tabbed" only apply once portal.js has
 * added .uc-picker-tabbed, which is what keeps the no-script version showing
 * both panels stacked instead of hiding one with nothing able to bring it back.
 * ------------------------------------------------------------------------ */
.uc-notify-picker { margin-top: 14px; }
.uc-picker { border: 1px solid var(--p-border); border-radius: 10px; background: #fff; }
.uc-picker-toggle { display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
    flex-wrap: wrap; padding: 11px 14px; cursor: pointer; font-size: 14px; font-weight: 600;
    color: var(--p-text); list-style: none; border-radius: 10px; }
.uc-picker-toggle::-webkit-details-marker { display: none; }
.uc-picker-toggle::marker { content: ""; }
/* A THIRD ANSWER TO ONE QUESTION IS GONE (3.64.0). This drew its own marker as
   a text triangle in ::after, swapped for a second character when open, while
   every other disclosure in caladmin used the shared .uc-disclosure-chevron
   element and turned it. Two mechanisms means two sizes, two colours and two
   ways of failing; the glyph also sat at whatever weight the font gave it. The
   summary carries the element now, like the rest. */
.uc-picker-toggle .uc-disclosure-chevron { margin-left: auto; }
.uc-picker[open] > .uc-picker-toggle { border-bottom: 1px solid var(--p-border); border-radius: 10px 10px 0 0; }
.uc-picker-toggle:hover { background: var(--p-bg); }
.uc-picker-toggle:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: -2px; }
.uc-picker-count { font-weight: 400; font-size: 12px; color: var(--p-muted); }
.uc-picker-panel { padding: 12px 14px 14px; }

.uc-picker-tabs { display: none; gap: 4px; margin-bottom: 12px; border-bottom: 1px solid var(--p-border); }
.uc-picker-tabbed .uc-picker-tabs { display: flex; }
.uc-picker-tab { padding: 7px 14px; font-size: 13px; font-weight: 600; color: var(--p-muted);
    background: none; border: 1px solid transparent; border-bottom: 0; border-radius: 8px 8px 0 0;
    margin-bottom: -1px; cursor: pointer; }
.uc-picker-tab[aria-selected="true"] { color: var(--p-text); background: #fff;
    border-color: var(--p-border); border-bottom: 1px solid #fff; }
.uc-picker-tab:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: -2px; }

/* The per-panel headings are how the no-script version tells the two lists
   apart. Once the tabs are live they say the same thing twice, so they go. */
.uc-picker-tabbed .uc-picker-heading { display: none; }
.uc-picker-panel-body + .uc-picker-panel-body { margin-top: 18px; }
.uc-picker-tabbed .uc-picker-panel-body + .uc-picker-panel-body { margin-top: 0; }

.uc-picker-filter { display: block; margin-bottom: 8px; }
.uc-picker-filter input { width: 100%; }
/* Fixed height whether there are three calendar users or three hundred, so the
   Save button never moves as staff are added. */
.uc-picker-options { display: flex; flex-direction: column; gap: 2px; max-height: 240px;
    overflow-y: auto; padding: 4px; border: 1px solid var(--p-border); border-radius: 8px; }
.uc-picker-option { margin: 0; padding: 5px 7px; border-radius: 6px; font-weight: 400; }
.uc-picker-option:hover { background: var(--p-bg); }
.uc-picker-option:focus-within { outline: 2px solid var(--uc-accent-text); outline-offset: -2px; }
.uc-picker-option .uc-muted { margin-left: 6px; font-size: 12px; }
.uc-picker-empty { margin: 8px 0 0; }

/* THE GROUP HEADINGS ARE GONE WITH THE GROUPING (3.74.0, removed 3.80.0).
   The picker hides everything outside the chosen series now, so there is no
   second group to head. A series with nothing tagged gets a sentence instead:
   see .uc-picker-no-series. */

/* ---------------------------------------------------------------------------
   THE IMAGES SCREEN (3.74.0, rebuilt 3.78.0)

   WHAT IT LOOKED LIKE AND WHY. auto-fill at minmax(150px, 1fr) put six cards
   across, each holding a tick, a thumbnail, a name box, a Save, a series
   dropdown and an Add. Six controls in a 150px column, thirty controls on a
   screen. The dropdown clipped after the word "Add", so the one thing it
   exists to show, a series name, was the thing it could not show.

   THE FLOOR IS THE CONTROL, NOT THE PICTURE. 150px was chosen as "a thumbnail
   somebody can recognise a photograph in", which was the wrong question: the
   widest thing in the card is a select that has to render "Mobile Health
   Sites" without clipping, and that is what sets the minimum. 300px.

   FEWER, WIDER, AND THE CARD READS AS ONE THING. Three across on a normal
   window rather than six, one form per card rather than two, and both fields
   labelled rather than placeholder-only, which is the pattern that made it
   read as a wall of boxes.

   THE TICK IS ON THE PICTURE, not in a column beside it. There is no row to
   put a column in, and a box floating over the corner of the image it selects
   is what every photo library does, so it is what a person looks for.
   ------------------------------------------------------------------------ */
.uc-media-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 18px;
    margin: 16px 0 0; padding: 0;
    list-style: none;
}
.uc-media-item {
    position: relative;
    display: flex; flex-direction: column; gap: 10px;
    padding: 12px;
    border: 1px solid var(--p-border); border-radius: 12px;
    background: var(--p-surface, #fff);
}
/* A WHITE CARD ON THE PAGE TINT, WHICH IS THE OTHER WAY ROUND FROM BEFORE.
   These were tinted cards on a white card, so thirty of them read as one grey
   field with boxes in it. Every other card in this portal is white on the
   tint; this is that, and the grid sits directly on the page rather than
   inside a second card. */
.uc-media-thumb {
    width: 100%; aspect-ratio: 16 / 9;
    object-fit: cover;
    border-radius: 8px;
    background: var(--p-surface-2, #f6f7f8);
}
.uc-media-tick {
    position: absolute; top: 18px; left: 18px;
    display: inline-flex; margin: 0; padding: 4px;
    border-radius: 6px;
    background: rgba(255, 255, 255, 0.94);
    box-shadow: 0 1px 3px rgba(26, 29, 33, 0.18);
}
.uc-media-tick input[type="checkbox"] { margin: 0; width: auto; }
.uc-media-name {
    margin: 0;
    font-size: 13px; line-height: 1.4;
    word-break: break-word;
}
.uc-media-tags { display: flex; flex-wrap: wrap; gap: 5px; margin: 0; }
.uc-media-tag {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 3px 8px;
    border-radius: 999px;
    background: var(--p-surface-2, #f6f7f8);
    border: 1px solid var(--p-border);
    font-size: 12px; line-height: 1.4;
}
/* The x is a control on a chip, so it takes the chip's ink rather than the
   destructive red: taking a tag off is reversible in one press and puts the
   image back where it was. Red here would be the only red on the screen and
   would say the opposite. */
.uc-media-tag-off {
    display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px; padding: 0;
    border: 0; border-radius: 4px;
    background: none; color: var(--p-muted, #6B6764);
    cursor: pointer; line-height: 0;
}
.uc-media-tag-off:hover { color: var(--p-text); background: var(--p-surface, #fff); }

/* ONE FORM, TWO LABELLED FIELDS AND ONE SAVE. margin-top: auto on the form
   pushes it to the foot of the card, so a card with two tag chips and one with
   none still line their Save buttons up across a row. */
.uc-media-edit {
    display: flex; flex-direction: column; gap: 8px;
    margin-top: auto;
    padding-top: 10px;
    border-top: 1px solid var(--p-border);
}
.uc-media-edit .uc-field { margin: 0; }
.uc-media-edit select, .uc-media-edit input[type="text"] { width: 100%; }
.uc-media-edit-go { display: flex; justify-content: flex-end; gap: 8px; flex-wrap: wrap; }

/* ---------------------------------------------------------------------------
   WHAT EACH BOX ON A CARD IS FOR, SAID ONCE (3.81.0)

   ABOVE THE GRID, NOT UNDER EACH CARD. At fifty images a line per card is fifty
   copies of one paragraph, and the cards are already the dense thing on this
   screen. One block, read once, by the person who needs it.

   IT IS A CARD BUT IT IS NOT A CONTROL, so it takes the page's quieter ground
   rather than a white panel competing with the grid below it. Reading measure
   is capped: three full-width lines across a 1200px screen is a paragraph
   nobody finishes.
   ------------------------------------------------------------------------ */
.uc-media-legend { padding: 14px 16px; background: var(--p-surface-2, #f6f7f8); }
.uc-media-legend p { margin: 0 0 6px; max-width: 76ch; font-size: 13px; line-height: 1.5; color: var(--p-muted, #6B6764); }
.uc-media-legend p:last-child { margin-bottom: 0; }
.uc-media-legend strong { color: var(--p-text); }

/* ---------------------------------------------------------------------------
   THE ONE CONTROL ON A CARD THAT TAKES SOMETHING AWAY (3.81.0)

   NOT RED AND NOT YELLOW. Red is this portal's destructive treatment and this
   deletes nothing: the file stays, the attachment stays, and the Removed view
   puts it back in one press. Yellow means "this is the thing to act on", and
   Save is that on this card. So Remove is a plain control that reads as
   secondary to the Save beside it, and the confirmation carries the detail.
   ------------------------------------------------------------------------ */
.uc-btn-quiet { color: var(--p-muted, #6B6764); }
.uc-btn-quiet:hover { color: var(--p-text); border-color: var(--p-border-strong); }

/* ---------------------------------------------------------------------------
   THE UPLOAD PANEL AND THE GRID WERE TWO DENSITIES (3.78.0)

   A full card with a 20px-padded field row, sitting above a grid of tight
   cards. It is a folded disclosure now, shut by default: adding a picture is
   something an admin does occasionally and looking at the library is what
   everybody does every time, so the occasional one should not be the first
   thing on the screen taking the most space.

   Same native <details> as the Series and Categories lists, and the same
   summary-is-the-card-head arrangement. No scripted show and hide.
   ------------------------------------------------------------------------ */
.uc-media-upload { margin-bottom: 18px; }
/* ---------------------------------------------------------------------------
   THE TWO COLUMNS LINE UP AT THE TOP, NOT THE BOTTOM (3.82.0)

   flex-end was reaching for the right thing: two controls of different heights
   sharing a baseline. It cannot get there, because only one of these columns
   has anything under its control. The File column is label, input, and two
   lines of hint; the Series column is label and a select. Bottom-aligned, the
   hint pushes the whole File column up, so the two LABELS end up on different
   lines and the input sits above the select it is meant to sit beside.

   Top-aligned, the labels are on one line, the two controls are on the next,
   and the hint hangs below the column it belongs to, which is where a hint goes
   everywhere else on these screens.
   ------------------------------------------------------------------------ */
.uc-media-upload .uc-field-row { align-items: flex-start; }
/* FOUR FIELDS ON A GRID, NOT A FLEX ROW (3.86.0).

   WHY THE FLEX ROW MISALIGNED. Two columns, one with a hint under it and one
   without, so the columns were different heights and nothing tied their
   contents together: the labels lined up only when the content happened to make
   them. Four fields turned that from a blemish into a mess.

   `align-items: start` with a real row boundary is what fixes it. Every label
   is the first thing in its cell and every cell starts on the row line, so the
   labels are on one line because the GRID says so. The hints hang below and
   move nothing.

   ONE COLUMN WHEN NARROW, on the container rather than the window: this screen
   is inside caladmin's own column and the window is not what decides its width. */
/* THE PICTURE ON THE LEFT, WHAT IS TYPED ABOUT IT ON THE RIGHT (3.87.0).

   THE 2x2 GRID THIS REPLACES DID NOT FIX THE ALIGNMENT and could not. A file
   input, a select and two text boxes have different intrinsic heights, so
   whatever grid they are put in, their labels drift apart. Splitting by KIND is
   the fix: nothing has to line up across the gap, so nothing can fail to.

   THE LEFT COLUMN IS FIXED, so the preview appearing cannot resize the fields
   beside it. The right column takes the rest. */
/* THE SENTENCE IN AN EMPTY wp.media GRID (3.90.0). Inside WordPress's own frame,
   so it is deliberately plain and sits below the grid rather than replacing
   anything: overwriting a core view is how a media picker breaks on a core
   update. Quiet and centred, because it explains rather than offers. */
.uc-media-empty-note {
    margin: 0; padding: 18px 20px;
    font-size: 14px; line-height: 1.5; text-align: center;
    color: var(--p-muted, #6B7280);
}

.uc-upload-panel {
    display: grid;
    grid-template-columns: 220px minmax(0, 1fr);
    gap: 18px;
    align-items: start;
}
.uc-upload-pic { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
/* THE WELL HOLDS ITS SIZE EMPTY OR FULL, at the 16:9 a card crops to, so
   choosing a file changes what is in the box and never the layout around it. */
.uc-upload-thumb {
    position: relative;
    aspect-ratio: 16 / 9; width: 100%;
    display: flex; align-items: center; justify-content: center;
    border: 1px dashed var(--p-border); border-radius: 10px;
    background: var(--p-bg, #F9FAFB);
    overflow: hidden;
}
.uc-upload-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.uc-upload-thumb-empty { font-size: 12px; color: var(--p-muted); }
/* THE THREE TYPED FIELDS ARE ONE STACK, so every label is the first line of an
   identical block and they line up by construction. */
.uc-upload-fields { display: flex; flex-direction: column; gap: 14px; min-width: 0; }

@media (max-width: 720px) {
    .uc-upload-panel { grid-template-columns: 1fr; }
    .uc-upload-thumb { max-width: 260px; }
}
/* The grid's own card carries the tint, so a white .uc-media-item reads as a
   card ON something rather than a box IN nothing. That is the one-white-card
   rule this portal already uses everywhere, restored: it was tinted cards on a
   white card, which made thirty of them one grey field. */
.uc-media-library { background: var(--p-surface-2, #f6f7f8); }
/* "no name yet", beside the label and only on a card that has none. Helper
   step, muted, so it reads as a state rather than as a second label. */
.uc-media-unnamed { margin-left: 6px; font-weight: 400; color: var(--p-muted, #6B6764); }
.uc-media-filter { margin: 0; flex: 0 1 280px; }
.uc-media-filter select { width: 100%; }

/* ---------------------------------------------------------------------------
   A PRIMARY BUTTON THAT CANNOT DO ANYTHING STOPS BEING PRIMARY (3.78.0)

   "Tag 0 images" rendered in brand Yellow while disabled. Yellow appears once
   on a screen and means "this is the thing to act on", and DESIGN.md is
   explicit that it is for actions; a control that is inert must not wear it,
   because the one thing a person scans for is then pointing at something that
   does nothing.

   Opacity alone was what it had, and 55% yellow is still yellow. This drops
   the treatment entirely: a disabled primary is a plain disabled control, and
   it goes back to yellow the moment something is ticked.

   SCOPED TO THE TICK PICKERS, which is every screen that has one: the events
   list, the schedule's bulk publish and this. One answer for all three.
   ------------------------------------------------------------------------ */
.uc-bulk-cat .uc-btn-primary[disabled],
.uc-pending-bulk .uc-btn-primary[disabled],
.uc-publish-picker .uc-btn-primary[disabled] {
    background: var(--p-surface-2, #f6f7f8);
    border-color: var(--p-border);
    color: var(--p-muted, #6B6764);
}

/* ---------------------------------------------------------------------------
   TEAMS (Users screen).

   A TEAM IS A DISCLOSURE THAT CONTAINS ITS OWN MEMBERS. The closed list is
   names and sizes and nothing else; opening one shows who is in it, an Add
   member picker of the calendar users who are not, and the Save that commits
   both. Rename and Delete moved inside the panel too, so a team's verbs are
   all in one place instead of half of them on the closed row.

   THE ROW IS NO LONGER A HORIZONTAL FLEX OF NAME AND BUTTONS. It holds one
   <details> at full width, which is what lets the open panel use the whole
   card instead of the column left over beside a row of actions.
   ------------------------------------------------------------------------- */
.uc-team-list { list-style: none; margin: 0; padding: 0; }
.uc-team-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px;
    padding: 13px 0; border-top: 1px solid var(--p-border); }
.uc-team-row:first-child { border-top: 0; }
.uc-team-row-open { background: var(--p-bg); border-radius: 10px; padding: 13px 12px; }
.uc-team-manage { flex: 1 1 100%; min-width: 0; }

/* The summary IS the row: chevron, name, count. Same disclosure shape as the
   RSVP settings card, so the marker means the same thing on both screens. */
.uc-team-summary { display: flex; align-items: center; gap: 10px; cursor: pointer;
    padding: 4px 6px; margin: -4px -6px; border-radius: 8px; list-style: none; }
.uc-team-summary::-webkit-details-marker { display: none; }
.uc-team-summary::marker { content: ""; }
.uc-team-summary:hover { background: var(--uc-band); }
.uc-team-summary:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: -2px; }
.uc-team-id { flex: 1 1 260px; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.uc-team-name-text { font-size: 15px; }
.uc-team-count { font-size: 13px; color: var(--p-muted); }
.uc-team-panel { margin-top: 12px; padding: 14px; background: var(--p-bg);
    border: 1px solid var(--p-border); border-radius: 10px; }
.uc-team-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.uc-team-actions form { margin: 0; }
.uc-team-rename { flex: 1 1 100%; display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; }
.uc-team-rename .uc-team-name { flex: 1 1 260px; }
.uc-team-members-form { margin: 0; }
.uc-team-none { margin: 8px 0 0; font-size: 13px; }
/* Rename and Delete, plainly subordinate to the membership editing above them
   and separated from it, so Delete is never the neighbour of Save. */
.uc-team-admin-actions { display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
    margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--p-border); }
.uc-team-admin-actions form { margin: 0; }
.uc-team-new { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--p-border); }
.uc-team-create { max-width: 420px; }
.uc-team-create-actions { display: flex; gap: 10px; align-items: center; margin-top: 10px; }
.uc-team-blocked { margin: 8px 0 0; padding-left: 18px; font-size: 13px; line-height: 1.7; }

/* Add member: a second, quieter disclosure inside the first. It is a summary
   rather than a button because it opens something in place, which is what the
   chevron already means one level up. */
.uc-team-add { margin-top: 14px; }
.uc-team-add-toggle { display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
    padding: 6px 12px; border: 1px solid var(--p-border-strong); border-radius: 8px;
    background: #fff; font-size: 13px; font-weight: 600; list-style: none; }
.uc-team-add-toggle::-webkit-details-marker { display: none; }
.uc-team-add-toggle::marker { content: ""; }
.uc-team-add-toggle:hover { border-color: var(--uc-accent-text); color: var(--uc-accent-text); }
.uc-team-add-toggle:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: 2px; }
.uc-team-add-body { margin-top: 10px; }
.uc-team-add-body .uc-picker-options { background: #fff; }

/* MEMBER ROWS ARE ONE LINE: name, address, and the control that takes them
   out. They were in a repeat(auto-fill, minmax(180px, 1fr)) grid, so at any
   real width the name wrapped onto a second line while the rest of the row
   stayed empty. A member list is a list, not a grid. */
.uc-member-list { list-style: none; margin: 8px 0 0; padding: 6px 8px; max-height: 260px;
    overflow-y: auto; border: 1px solid var(--p-border); border-radius: 8px; background: #fff; }
.uc-member-row { margin: 0; }

/* ---------------------------------------------------------------------------
   A MEMBER, AND THE CONTROL THAT REMOVES THEM.

   The control is a ticked checkbox covering the whole row, drawn as an x. It
   is not a button, because a button would have to either post on the spot or
   carry its own staging in JavaScript, and neither is what was asked for: the
   removal is STAGED and the form's Save is what commits it.

   WITH SCRIPTING OFF NOTHING VANISHES. An unticked row stays where it is and
   goes struck through, so "this person is about to be taken out" is on screen
   to be read, and pressing Cancel or reloading brings them back untouched.
   Same pattern, and the same reasoning, as the "anyone else" address pills.
   ------------------------------------------------------------------------- */
.uc-member-chip { position: relative; display: flex; align-items: flex-start; gap: 9px;
    margin: 0; padding: 6px 8px; border-radius: 6px; font-size: 13px; font-weight: 400;
    cursor: pointer; }
.uc-member-chip:hover { background: var(--p-bg); }
.uc-member-chip input { position: absolute; opacity: 0; width: 100%; height: 100%;
    top: 0; left: 0; margin: 0; cursor: pointer; }
.uc-member-chip input:focus-visible ~ .uc-member-x { outline: 2px solid var(--uc-accent-text); outline-offset: 2px; border-radius: 4px; }
.uc-member-body { flex: 1 1 auto; min-width: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 9px; }
.uc-member-x { flex: 0 0 auto; align-self: center; display: inline-flex; color: var(--p-muted); opacity: 0.7; }
.uc-member-chip:hover .uc-member-x { opacity: 1; color: var(--p-danger); }
.uc-member-chip input:not(:checked) ~ .uc-member-body { text-decoration: line-through; opacity: 0.55; }
.uc-member-chip input:not(:checked) ~ .uc-member-x { opacity: 1; color: var(--p-danger); }
.uc-member-name { font-weight: 600; white-space: nowrap; }
.uc-member-email { flex: 1 1 auto; min-width: 0; font-size: 12px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.uc-visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* THE REQUIRED MARK (3.99.0). The label's own colour and weight, never red:
   "Fields marked * are required" at the top of the form is what says what it
   means, and a red that meant "required" would be the colour errors use saying
   something that is not an error. Nothing but a gap, so it reads as part of
   the label. [hidden] is restated because a conditional mark is toggled with
   it and a later display rule would otherwise win. */
.uc-req { color: inherit; font-weight: inherit; margin-left: 0.2em; }
.uc-req[hidden] { display: none; }
/* The line that says what the mark means. Two classes, because .uc-hint sets
   its margin with one and this has to clear the card below it. */
.uc-hint.uc-required-note { margin: 0 0 14px; }

/* ---------------------------------------------------------------------------
   REGISTRATIONS: the event's settings, closed, and left aligned.

   CLOSED WHEN THE PAGE OPENS, always. It used to open itself whenever the list
   was empty. Somebody arriving here came for the registrations.

   THE CHEVRON IS A REAL AFFORDANCE. It was a 3px text triangle in the muted
   grey, which is the least a disclosure can do and still technically have a
   marker. It is now a 28px ringed control at the head of the row, in the
   measured teal, that rotates a quarter turn on open, so it reads as a button
   before it is pressed and reports its state after. It sits on a <summary>,
   which is a real interactive element: click, tap, Enter and Space all work
   with no script at all.

   EVERYTHING IS HARD LEFT. justify-content was space-between, which threw the
   status line to the far right edge of a 1100px card, a hand-span away from
   the heading it describes. The two lines stack under the chevron now.
   ------------------------------------------------------------------------- */
/* The one card whose head is a <summary> rather than a .uc-card-head. It takes
   the same band, because a disclosure is still a card and a manager should not
   have to work out that this one is a different kind of thing. */
.uc-rsvp-settings { padding: 0; }
.uc-rsvp-settings-toggle { display: flex; align-items: center; justify-content: flex-start;
    gap: 12px; padding: 11px 16px; cursor: pointer; font-size: 14px; text-align: left;
    list-style: none; border-radius: 0 12px 0 0;
    background: var(--uc-band); border-bottom: 1px solid var(--p-border); }
.uc-rsvp-settings-toggle::-webkit-details-marker { display: none; }
.uc-rsvp-settings-toggle::marker { content: ""; }
.uc-rsvp-settings-toggle:hover { background: var(--uc-band-alt); }
.uc-rsvp-settings-toggle:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: -2px; }
.uc-rsvp-settings[open] > .uc-rsvp-settings-toggle { border-bottom: 1px solid var(--p-border); }
.uc-rsvp-settings-id { display: flex; flex-direction: column; gap: 2px; min-width: 0; text-align: left; }
.uc-rsvp-settings-name { font-size: 14px; }
.uc-rsvp-settings-id .uc-muted { font-size: 12px; }

/* ---------------------------------------------------------------------------
   THE DISCLOSURE MARK. ONE MECHANISM, AND THE PLAIN GLYPH IS THE DEFAULT
   (3.64.0).

   There were THREE answers to "does this open?" in one stylesheet: this
   element, a text triangle drawn in .uc-picker-toggle::after, and, on seven
   summaries, nothing at all. Somebody meeting "Change the pattern" or "Extend
   the series" had a line of teal text and no reason to think it opened.

   AND THE DEFAULT WAS BACKWARDS. This class was declared as a 28px white ring,
   which is right on a summary that IS a card's head band and wrong everywhere
   else, so it had to be undone by hand, once, for .uc-team-add-toggle. The
   other place that needed it undone did try: `.uc-disclosure-chevron` was
   declared as a bare glyph 1350 lines above here, at the same specificity, and
   lost, so the quiet cancel disclosure wore a white circle nobody chose and the
   rule saying otherwise read as if it worked. Same shape as the 3.39.0
   .uc-btn-danger fault. The default is now the glyph, which is what most of
   them want, and the ring is named by the three that are card heads. Adding a
   disclosure tomorrow gets the right mark without a second rule.

   COLOUR IS INHERITED, deliberately. The glyph is part of the sentence it sits
   in, so it is teal on a teal line, dark gray on the yellow pill and muted on
   the cancel toggle, and no summary needs a rule about it.
   ------------------------------------------------------------------------- */
.uc-disclosure-chevron { display: inline-flex; align-items: center; justify-content: center;
    flex: 0 0 auto; color: inherit; transition: transform .18s ease; }

/* THE RING, FOR A SUMMARY THAT IS A CARD'S HEAD. The band is a surface and the
   ring is a control on it, which is why these three and no others. */
.uc-rsvp-settings-toggle .uc-disclosure-chevron,
.uc-faq-set-toggle .uc-disclosure-chevron,
.uc-team-summary .uc-disclosure-chevron {
    width: 28px; height: 28px; border-radius: 50%;
    border: 1px solid var(--p-border-strong); background: #fff; color: var(--uc-accent-text);
    transition: transform .18s ease, background-color .18s ease, border-color .18s ease; }
.uc-rsvp-settings-toggle:hover .uc-disclosure-chevron {
    background: var(--uc-accent-text); border-color: var(--uc-accent-text); color: #fff; }

[open] > .uc-rsvp-settings-toggle .uc-disclosure-chevron,
[open] > summary .uc-disclosure-chevron { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) { .uc-disclosure-chevron { transition: none; } }
.uc-rsvp-settings-form { padding: 16px; display: flex; flex-direction: column; gap: 14px; }
.uc-rsvp-settings-form .uc-form-actions { margin-top: 4px; }

/* Consent is marked, and it says what it is a mark FOR. A bare tick in a
   column headed "Updates" is not a record of anything anybody agreed to. */
.uc-optin-yes { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 600;
    padding: 2px 8px; border-radius: 99px;
    background: color-mix(in srgb, var(--uc-primary, #16BECF) 14%, #fff);
    color: color-mix(in srgb, var(--uc-primary, #16BECF) 72%, #000); }

/* WHO RELEASED A PLACE, when it was not the registrant (3.105.0). The helper
   step under the status pill, on its own line. The Remove cell never wraps, so
   the column is as wide as the word and no wider. */
.uc-rsvp-removed-by { display: block; margin-top: 4px; font-size: 12px; font-weight: 400; line-height: 1.4; color: var(--p-muted); }
.uc-rsvp-actions { white-space: nowrap; text-align: right; }
.uc-rsvp-actions form { margin: 0; }

/* ---------- Removing a series ----------
   Two options, each a real block with its own consequence written under it,
   because one of them deletes events and the other does not. */
.uc-remove-lead { font-size: 15px; margin: 0 0 16px; }
.uc-remove-goes { margin: 16px 0 0; }
.uc-remove-options { display: flex; flex-direction: column; gap: 12px; margin-bottom: 18px; }

/* ---------------------------------------------------------------------------
   THE OPTION CARD: A CHOICE WITH A CONSEQUENCE WRITTEN UNDER IT.

   ONE DECLARATION, THREE PLACES (3.64.0). This existed three times: here for
   the two ways to remove a series, as `.uc-scope-options .uc-radio-opt` for
   which occurrences an edit touches, and as `.uc-cancel-visibility
   .uc-radio-opt` for what a cancelled event does on the public calendar. All
   three are a radio, a bold clause and a sentence saying what happens.

   THE THIRD ONE MATCHED NOTHING, which is the part worth writing down.
   `.uc-scope-options` is in no renderer, so the rule that drew the card for
   `.uc-radio-opt` never ran, and the only live rule for that class was the
   cancel card's, which gave it no box at all. Reading the stylesheet said
   "option cards"; the screen said "a list of radios". Neither was lying and
   the two did not agree. The card is declared here now and both class names
   name it.

   IT IS NOT A BUTTON AND MUST NOT LOOK LIKE ONE. Pressing it chooses; a
   separate control does the thing. So it keeps the white "you are working in
   this" fill and the hairline BETWEEN things, and it never takes the button
   face. That is the whole of the rule the standard exists for.
   ------------------------------------------------------------------------- */
.uc-remove-option,
.uc-radio-opt { display: flex; align-items: flex-start; gap: 11px; padding: 14px 16px;
    border: 1px solid var(--p-border-strong); border-radius: 10px; cursor: pointer;
    background: var(--p-control-face); font-size: 14px; line-height: 1.5; }
.uc-remove-option:hover,
.uc-radio-opt:hover { border-color: var(--uc-accent-text); }
.uc-remove-option:focus-within,
.uc-radio-opt:focus-within { outline: 2px solid var(--uc-accent-text); outline-offset: 1px; }
.uc-remove-option > input[type="radio"],
.uc-radio-opt > input[type="radio"] { margin-top: 3px; flex: 0 0 auto; }
.uc-remove-body { display: flex; flex-direction: column; gap: 6px; min-width: 0; flex: 1 1 auto; }
.uc-remove-option-danger { border-color: color-mix(in srgb, #c0392b 40%, var(--p-border)); }
.uc-remove-sub { display: flex; flex-direction: column; gap: 4px; margin-top: 8px;
    padding-left: 12px; border-left: 2px solid var(--p-border); }
.uc-remove-sub-label { font-size: 12px; font-weight: 600; color: var(--p-muted); }
.uc-remove-picker { margin-left: 22px; max-width: 320px; }
/* White on #C0392B is 5.13:1; on the darker hover, 6.65:1. `.uc-portal a` is
   (0,1,1) and would repaint an anchor wearing this with the page's link teal,
   which is the same specificity accident documented at .uc-btn-source, so the
   anchor case is named explicitly. */

/* ===========================================================================
 * THE THREE ACTIONS AT THE FOOT OF THE EVENT EDITOR (3.94.0).
 *
 * WHAT IT WAS. Save in a band, Cancel a whole disclosure section with its own
 * heading, Delete a card with its own heading and paragraph. Three blocks for
 * three buttons. AND CANCEL AND DELETE WERE BOTH RED, which is the fault under
 * the mess: the two actions with the most different consequences on this screen
 * looked identical. One is reversible and keeps every registration; the other
 * keeps nothing and tells nobody.
 *
 * COLOURED BY CONSEQUENCE. Green go, amber caution, red stop. These are SYSTEM
 * STATES, not brand: DESIGN.md's palette rule is about what a visitor sees on
 * the public calendar, and caladmin is a set of controls for one person doing a
 * job. Going outside the palette is allowed here and only here.
 *
 * EVERY ONE MEASURED, because green and amber with white text are the two that
 * are usually wrong. The obvious 600-weight shades both fail:
 *
 *     #16A34A green 600   white text 3.30:1   FAILS
 *     #D97706 amber 600   white text 3.19:1   FAILS
 *     #15803D green 700   white text 5.02:1   passes
 *     #B45309 amber 700   white text 5.02:1   passes
 *     #c0392b the red we already have   white text 5.44:1   passes
 *
 * THE AMBER IS ALREADY ON THIS SCREEN. #B45309 is the needs-attention flag and
 * the strong source link, measured at 5.02:1 in 3.68.0. The red is unchanged
 * from .uc-btn-danger. Only the green is new, and it is the same 700 weight as
 * the amber so the row is one family rather than three borrowed palettes.
 *
 * THE HOVERS GO DARKER, NEVER LIGHTER: 7.17, 7.09 and 6.98 to one.
 * ======================================================================== */
.uc-editor-actions,
.uc-portal .uc-form-actions-primary {
    display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
}

.uc-portal .uc-btn-go { background: #15803D; border-color: #15803D; color: #fff; }
.uc-portal .uc-btn-go:hover { background: #12652F; border-color: #12652F; color: #fff; }
.uc-portal .uc-btn-caution { background: #B45309; border-color: #B45309; color: #fff; }
.uc-portal .uc-btn-caution:hover { background: #92400E; border-color: #92400E; color: #fff; }
.uc-portal .uc-btn-stop { background: #c0392b; border-color: #c0392b; color: #fff; }
.uc-portal .uc-btn-stop:hover { background: #a33025; border-color: #a33025; color: #fff; }

/* ---------------------------------------------------------------------------
   THE ROW READS DESTRUCTIVE TO PRIMARY, LEFT TO RIGHT (3.97.0, 3.98.0).

       a draft        Delete   Save draft     Publish
                      red      YELLOW         GREEN, largest

       an existing    Delete     Cancel event   Save changes     (3.113.3)
       event          red link   outlined       GREEN, largest

   FROM 3.113.3 DELETE IS A RED TEXT LINK ON BOTH ROWS and Cancel event is
   outlined, so an existing event's bar has one solid button. What follows
   about two reds is the 3.98.0 reasoning, kept for the record.

   CANCEL EVENT IS RED, NOT AMBER (3.98.0), because it takes the event off the
   public calendar and mails everybody who registered. Amber said "careful" for
   something that belongs beside Delete in consequence; the two reds together
   are the honest reading, and they are told apart by their labels and by the
   chevron, which only Cancel event has because only it opens something.

   ORDER ON SCREEN AND ORDER IN THE MARKUP ARE DIFFERENT THINGS, AND THAT IS
   THE WHOLE REASON THIS IS `order` AND NOT A REWRITE OF THE PHP. A browser
   sends an Enter keypress in a text field to the form's FIRST SUBMIT BUTTON in
   DOCUMENT order, and Delete must never be that button. Save draft is first in
   the markup and stays first, so Enter still saves a draft, which is the safe
   answer and the one 3.94.0 already chose. Moving Delete to the left of the row
   visually costs nothing, because `order` does not move it in the document.

   > DELETE IS ALSO NOT A SUBMIT OF THIS FORM AT ALL. It carries
   > `form="uc-delete-event-N"`, so its form owner is the delete form emitted
   > after this one, and implicit submission of the event form cannot reach it
   > whatever the order. Two mechanisms, and the test asserts both, because the
   > `form=` attribute is one edit away from being dropped by somebody tidying.

   YELLOW ON SAVE DRAFT AND GREEN ON PUBLISH IS MARK'S DECISION, and it inverts
   what DESIGN.md says about yellow being the primary action. DESIGN.md records
   the exception by name so a later pass does not "correct" it back. The short
   version: on this row yellow marks the IN-BETWEEN action, the one you press
   while you are still working, and green marks the thing that puts the event in
   front of the public.

   PUBLISH IS THE LARGEST, which is the part that carries "this is the main
   action" now that it is not the only coloured button. Size, not hue.
   ------------------------------------------------------------------------ */
.uc-editor-actions .uc-editor-delete  { order: -1; }
.uc-editor-actions .uc-cancel-open    { order: 2; }
/* ONE SOLID BUTTON ON AN EXISTING EVENT'S BAR (3.113.3). Delete is a red text
   link at the far left, ahead of the note, whose auto margin sets it apart from
   the buttons on the right. Cancel event is the plain button outlined: its
   control edge and no face. Two classes beat .uc-btn and its :hover, so both
   states are named. */
.uc-editor-actions .uc-editor-delete  { margin-right: 20px; font-size: 14px; }
.uc-editor-actions .uc-cancel-open,
.uc-editor-actions .uc-cancel-open:hover { background: transparent; }
/* ITS EDGE IS --p-muted, NOT --p-border-strong (3.113.4): on the grey bar the
   control edge measured 3.07:1 and read as no button at all. On the white bar
   from 3.113.5, #6B6764 is 5.60:1. Hover still turns it teal. */
.uc-editor-actions .uc-cancel-open { border-color: var(--p-muted); }
.uc-editor-actions .uc-cancel-open:hover { border-color: var(--uc-accent-text); }
.uc-editor-actions .uc-editor-save    { order: 3; }
.uc-editor-actions .uc-editor-publish { order: 4; }
/* A submission waiting for review (3.113.2): Reject, Save changes, Approve. */
.uc-editor-actions .uc-editor-reject  { order: 2; }
.uc-editor-actions .uc-editor-approve { order: 4; }
/* Open, the cancel panel still takes the whole width and drops to the end. The
   rule below sets order: 20, which is past every one of these. */

/* THE MAIN ACTION IS THE BIGGEST THING IN THE ROW. Padding and type size, so it
   grows in both axes rather than becoming a long thin bar.

   TWO ROWS, TWO MAIN ACTIONS (3.98.0). A draft's row ends in Publish; an
   existing event's has no Publish at all and ends in Save changes, which is
   then the thing somebody came to press. Both are green and both are the
   largest thing in their row, which is one rule rather than a special case:
   GREEN AND BIG MARK WHATEVER PUTS THE EVENT IN FRONT OF PEOPLE, yellow marks
   the in-between save. Before this, an existing event's row was a red Delete, a
   red Cancel event and a yellow Save changes, so the only safe button in it was
   also the quietest. */
.uc-editor-actions .uc-editor-publish,
.uc-editor-actions .uc-editor-approve,
.uc-editor-actions .uc-editor-save-main {
    padding: 13px 30px;
    font-size: 15px;
}
/* ---------------------------------------------------------------------------
   THE CENTRED DIALOGS (3.112.1): Cancel event, Delete, and a tag's Delete.

   The panel is drawn in the page and portal.js lifts it into a <dialog> when
   its button is pressed. In the dialog it is the dialog's one child and
   carries the padding, as every dialog here does. With no script it stays in
   the page and reads as a card under the row it belongs to.
   --------------------------------------------------------------------------- */
.uc-dialog { width: min(560px, calc(100vw - 32px)); }
.uc-dialog-panel {
    margin-top: 16px; padding: 18px 20px;
    border: 1px solid var(--p-border); border-radius: 12px; background: #fff;
}
.uc-dialog .uc-dialog-panel {
    margin: 0; padding: 22px 24px 20px; border: 0; border-radius: 0;
    max-height: calc(100vh - 48px); overflow: auto;
}
/* Two classes: `.uc-portal h2` is a class and a type, (0,1,1), and would set
   the title at 16px under a 15px lead. */
.uc-dialog-panel .uc-dialog-title { margin: 0 0 8px; font-size: 20px; font-weight: 700; }
.uc-dialog-lead { margin: 0 0 14px; font-size: 15px; line-height: 1.5; }
.uc-dialog-panel .uc-cancel-form { display: flex; flex-direction: column; gap: 14px; }
.uc-dialog-panel fieldset { margin: 0; padding: 0; border: 0; }
.uc-dialog-panel legend { margin-bottom: 6px; font-weight: 600; }
.uc-dialog-actions { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: 10px; margin-top: 18px; }
.uc-dialog-panel form > .uc-dialog-actions:first-of-type { margin-top: 4px; }

/* What is left of the delete card: the sentence for when it is refused. */
.uc-delete-block { margin-top: 10px; }

/* ---------------------------------------------------------------------------
   THE EDITOR'S ACTION BAR IS STICKY TO THE FOOT OF THE WINDOW (3.107.0).

   Full editor width, WHITE --p-panel under one Dark Gray #373433 rule, with a
   soft shadow cast upward so the bar floats over the page (3.113.5). No side
   borders, no radius. 3.113.4 made it the canvas grey --p-bg under a Light
   Gray #D1D3D4 rule, and it blended into the grey page behind the cards;
   before that it was white under a --p-border hairline, and nothing told it
   from the white cards scrolling beneath. The Dark Gray rule is what does
   that now. It stays visible while the form scrolls under it and sits in the
   flow at the very end.

   (0,3,0) on purpose: .uc-form-actions-primary draws the band it used to be at
   (0,1,0), and .uc-portal .uc-form-actions-primary sets its flex at (0,2,0).

   WHILE CANCEL EVENT IS OPEN THE BAR GOES BACK INTO THE FLOW. The open panel is
   radios and a paragraph, and pinned to the foot of a phone it would be taller
   than the window.

   AT 390px every button stays reachable: the note takes its own line and the
   buttons share the next one, wrapping rather than scrolling sideways, and the
   white runs to both edges of the window.
   ------------------------------------------------------------------------ */
.uc-portal .uc-form-actions-primary.uc-editor-bar {
    position: sticky; bottom: 0; z-index: 15;
    margin: 24px 0 0; padding: 12px 20px;
    border: 0; border-top: 1px solid #373433; border-radius: 0;
    background: var(--p-panel); box-shadow: 0 -4px 12px rgba(55, 52, 51, 0.12);
}
.uc-portal .uc-editor-bar .uc-form-actions-note { font-size: 12px; }
/* A SUBMISSION WAITING FOR REVIEW (3.113.2): Approve is the main action and
   its size, so above 600px the caption shrinks and wraps rather than pushing
   Approve onto a line of its own. Below, the caption has its own line anyway. */
@media (min-width: 601px) {
    .uc-portal .uc-editor-bar:has(.uc-editor-approve) .uc-form-actions-note { flex: 1 1 0; min-width: 0; }
}
@media (max-width: 600px) {
    /* White from edge to edge of the window (3.113.5): out through the 18px
       gutter .uc-portal-content has below 720px, and back in by the same, so
       the buttons stay where they were. */
    .uc-portal .uc-form-actions-primary.uc-editor-bar { margin: 24px -18px 0; padding: 10px 18px; gap: 8px; }
    .uc-portal .uc-editor-bar .uc-btn { padding: 10px 12px; font-size: 14px; }
    /* The note takes the first line here, so Delete takes the last, on its own. */
    .uc-editor-actions .uc-editor-delete { order: 30; flex: 1 1 100%; margin: 0; text-align: left; }
}

/* ---------------------------------------------------------------------------
   THE REGISTRATION CARD (3.107.0). Its body is hidden by portal.js while Accept
   RSVPs is off; [hidden] is restated because nothing else may out-rank it. The
   questions are a section of the card, set off by space and one hairline, not a
   card inside it.
   ------------------------------------------------------------------------ */
.uc-registration-body { margin-top: 14px; }
.uc-registration-body[hidden] { display: none; }
.uc-registration-questions { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--p-border); }
.uc-portal .uc-registration-questions > .uc-subhead { margin: 0 0 8px; }

/* AN OUTLINED BUTTON, THE "+ Add question" STYLE (3.107.0), for Insert image:
   1px --uc-accent-text edge and text, --uc-band on hover, the accent ring on
   focus. On a <summary>, so the marker goes too. */
.uc-portal .uc-outline-btn {
    display: inline-flex; align-items: center; align-self: flex-start; padding: 8px 16px;
    border: 1px solid var(--uc-accent-text); border-radius: 8px; background-color: transparent; cursor: pointer;
    font-family: inherit; font-size: 13px; font-weight: 600; line-height: 1.4; color: var(--uc-accent-text);
    list-style: none;
}
.uc-portal .uc-outline-btn:hover { background-color: var(--uc-band); }
.uc-portal .uc-outline-btn:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: 2px; }
.uc-portal summary.uc-outline-btn::-webkit-details-marker { display: none; }
.uc-portal summary.uc-outline-btn::marker { content: ""; }

/* PLACEHOLDERS IN THE EDITOR ARE --p-muted (3.107.0), 5.60:1 on white. The
   address boxes are labelled by them, so they have to be read, not guessed. */
.uc-bento input::placeholder, .uc-bento textarea::placeholder { color: var(--p-muted); opacity: 1; }

/* A chosen picture outside the series, said under the picker (3.107.0). */
.uc-bento .uc-image-outside { margin: 6px 0 0; }

/* ORGANIZER CHIPS ARE NEUTRAL (3.107.0). A category's colour means that
   category; an organizer has none, so its chips take the text colour's tint. */
.uc-org-field .uc-chip { --chip-color: var(--p-text); }

.uc-btn-danger { background: #c0392b; border-color: #c0392b; color: #fff; }
.uc-btn-danger:hover { background: #a33025; border-color: #a33025; color: #fff; }
.uc-portal a.uc-btn-danger, .uc-portal a.uc-btn-danger:hover { color: #fff; }

/* The Remove series control, alone at the foot of the series editor. It takes
   the space a card would have taken so the button does not sit against the
   Schedule above it. */
.uc-series-remove-row { margin-top: 32px; padding-top: 24px; border-top: 1px solid var(--p-border); }

/* ---------- Registrations ---------- */
.uc-page-head-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.uc-orphan-note { margin-top: 14px; }

/* Run status. Colour is never the only signal — the word itself is the value in
 * the cell — so this reads the same to anyone who cannot separate the hues. */
.uc-cron-ok { color: #15803d; font-weight: 600; }
.uc-cron-partial, .uc-cron-stale { color: #92400e; font-weight: 600; }
.uc-cron-failed, .uc-cron-failing { color: #b91c1c; font-weight: 600; }
.uc-cron-skipped, .uc-cron-never { color: var(--p-muted); font-weight: 600; }
.uc-cron-task { font-size: 13px; line-height: 1.5; margin-bottom: 4px; }
.uc-cron-task:last-child { margin-bottom: 0; }

/* ---------------------------------------------------------------------------
 * Series lifecycle: edit scope, removal choices, orphan repair.
 * ------------------------------------------------------------------------ */

/* .uc-scope-options AND .uc-removal-options ARE GONE, AND THEY WERE ALREADY
 * GONE (3.64.0). Neither class appears in any renderer or in portal.js. They
 * were the pre-3.23.0 markup for the same two questions the scope modal and
 * .uc-remove-options ask now, and the rules outlived it.
 *
 * The one that mattered is `.uc-scope-options .uc-radio-opt`, which drew the
 * option card: a border, a fill, 9/12 of padding. It matched nothing, so the
 * only live `.uc-radio-opt` was the cancel card's, which had a rule giving it
 * no box at all. That is why the same class read as two different controls
 * depending on where you looked it up, and why the reading in the stylesheet
 * did not agree with the screen. The card is declared once now, at
 * .uc-remove-option, and the cancel options wear it. */

/* A danger card wears its warning on the band, not on the heading text. The
   heading is already uppercase and tracked like every other card heading, so
   colouring it as well was two signals doing one job. #7F1D1D on #FEF2F2
   measures 9.16:1; the band's own edge carries no meaning, which is why the
   words say "Remove" and the colour only agrees with them. */
.uc-card-danger { border-color: #fecaca; }
.uc-card-danger > .uc-card-head,
.uc-card-danger > h2:first-child,
.uc-card-danger > h3:first-child { background: #FEF2F2; border-bottom-color: #FECACA; color: #7F1D1D; }
.uc-card-danger > .uc-card-head h2,
.uc-card-danger > .uc-card-head h3 { color: #7F1D1D; }

/* Dashboard: what needs a person, and what has happened. Read-only lists. */
.uc-attention-list { margin: 0; padding-left: 18px; font-size: 14px; line-height: 1.9; }
.uc-activity-list { margin: 0; padding: 0; list-style: none; font-size: 13.5px; }
.uc-activity-list li { display: flex; gap: 12px; padding: 7px 0; border-bottom: 1px solid var(--p-border); }
.uc-activity-list li:last-child { border-bottom: 0; }
.uc-activity-when { flex: 0 0 110px; color: var(--p-muted); }
.uc-activity-what { min-width: 0; }

/* Inline email validation. Same two signals, same wording, same JavaScript as
 * the public forms and the WordPress admin: see public/js/sfaf-email.js. */
.uc-portal input.uc-invalid,
.uc-portal textarea.uc-invalid { border-color: #dc2626; box-shadow: 0 0 0 1px #dc2626; }
.uc-portal input.uc-invalid:focus,
.uc-portal textarea.uc-invalid:focus { outline: 2px solid #dc2626; outline-offset: 1px; }
.uc-portal .uc-field-error { margin: 5px 0 0; font-size: 13px; line-height: 1.45; color: #b91c1c; font-weight: 600; }

/* ---------------------------------------------------------------------------
 * Sortable table headings and list paging (Events list).
 * ------------------------------------------------------------------------ */

/* The heading is the click target, so it has to look like one. The active
 * column is marked by a character as well as by weight and colour, because
 * weight alone is not a signal anybody can rely on. */
.uc-table th.uc-sortable { padding: 0; }
.uc-table th.uc-sortable > a { display: block; padding: 12px; color: inherit; text-decoration: none;
    font-weight: inherit; white-space: nowrap; }
.uc-table th.uc-sortable > a:hover { background: var(--p-bg, #F7F8FA); color: var(--p-text); }
.uc-table th.uc-sortable > a:focus-visible { outline: 2px solid var(--p-accent, #16BECF); outline-offset: -2px; }
.uc-table th.uc-sorted > a { color: var(--p-text); font-weight: 800; }
.uc-sort-mark { font-size: 10px; }

/* Present but invisible: the sort state has to be readable by a screen reader
 * without printing a sentence into every column heading. */
.screen-reader-text { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }

.uc-list-pagination { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
    gap: 12px; margin-top: 14px; }
.uc-list-total { margin: 10px 0 0; }
.uc-list-pages { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.uc-page-num { display: inline-block; min-width: 30px; padding: 5px 8px; text-align: center;
    border: 1px solid var(--p-border); border-radius: 6px; font-size: 13px; text-decoration: none; color: inherit; }
.uc-page-num:hover { background: var(--p-bg, #F7F8FA); }
.uc-page-current { background: var(--uc-primary, #FFD900); border-color: var(--uc-primary, #FFD900);
    color: #373433; font-weight: 700; }

/* Working indicator on a slow action (Fetch updates, Run now). */
.uc-btn[disabled] { opacity: .65; cursor: progress; }
.uc-spinner { display: inline-block; width: 13px; height: 13px; margin-right: 7px; vertical-align: -2px;
    border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%;
    animation: uc-spin .7s linear infinite; }
@keyframes uc-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .uc-spinner { animation-duration: 2.4s; } }
.uc-action-error { margin: 10px 0 0; padding: 10px 14px; border-radius: 8px;
    background: #fef2f2; color: #b91c1c; font-size: 13px; font-weight: 600; }

/* ===========================================================================
 * THE MANAGER-OWNED PANEL, ON BOTH SCREENS
 *
 * One render, so one set of rules. The editor drops it into the main column
 * of the form; the pending queue puts it in a disclosure under the row it
 * belongs to. Nothing here is queue-specific except the disclosure itself.
 * ======================================================================== */
.uc-manager-panel { display: flex; flex-direction: column; gap: 16px; }
.uc-manager-panel .uc-fund-field { padding: 14px 16px; background: var(--uc-bg, #f7f8fa); border: 1px solid var(--uc-border, #e2e5ea); border-radius: 10px; }
.uc-manager-panel .uc-fund-field .uc-hint { margin-top: 6px; }

/* Collapsed by default: a queue is for scanning, and a dozen open panels
   would stop it being one. */
/* ---------------------------------------------------------------------------
   THE IMPORTED QUEUE: A LIST OF EVENTS, NOT A TABLE OF COLUMNS.

   It was five columns wide, and a table gives every column the same weight, so
   the title, the platform badge, a timezone string, an address and two verbs
   all arrived at once with nothing saying which was the thing. A queue is
   scanned for WHICH EVENT this is and then decided about, which is a heading
   and a supporting line.

   THE HIERARCHY IS MADE WITH SIZE AND WEIGHT, not with rules or colour, which
   is what the brand guide asks for (p.17). Title 16/600 in the text colour;
   everything under it 13/400 in the secondary grey. One hairline between rows.
   ------------------------------------------------------------------------- */
.uc-queue-list { list-style: none; margin: 0; padding: 0; }
/* 22px, not 16. Rows carrying a title, a meta line, a link and a disclosure
   need more air between two of them than there is inside one, or the hairline
   is doing all the separating on its own and the list reads as one block. */
.uc-queue-item { padding: 22px 0; border-top: 1px solid var(--p-border); }
.uc-queue-item:first-child { border-top: 0; padding-top: 4px; }
/* Waiting on a person: the palest amber, pulled out to the card's padding edge
   so the row is marked without a box being drawn around it. Never red, because
   a GoFundMe Pro campaign arrives in this state by design every time. */
.uc-queue-item-needs { background: #fffdf5; box-shadow: -20px 0 0 #fffdf5, 20px 0 0 #fffdf5; }

.uc-queue-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.uc-queue-id { flex: 1 1 320px; min-width: 0; }
.uc-portal .uc-queue-title { margin: 0 0 4px; font-family: var(--uc-font-heading);
    font-size: 16px; font-weight: 600; line-height: 1.3; letter-spacing: 0;
    text-transform: none; color: var(--sfaf-darkgray); }
.uc-queue-title a { color: inherit; }
.uc-queue-title a:hover { color: var(--uc-accent-text); }

/* Source, when and where, in the order somebody reads them. Wraps as a group
   rather than as one run-on sentence, so a long address takes its own line
   instead of pushing the date off the row. */
.uc-queue-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px;
    margin: 0; font-size: 12px; font-weight: 400; line-height: 1.5; color: var(--p-muted); }
.uc-queue-links { margin: 6px 0 0; font-size: 12px; }
.uc-queue-actions { flex: 0 0 auto; padding-top: 2px; }

/* ---------------------------------------------------------------------------
   ONE QUEUE, WITH CONTROLS ABOVE IT (3.49.0)

   The queue was three stacked blocks and is one list. These are the two
   controls that replaced the stacking: a filter for what kind of thing a row
   is, and a sort for when it arrived.

   THE COUNT RIDES ON THE TAB. A filter that hides rows has to say how many it
   is hiding, or "Nothing waiting" under a narrowed list reads as "your work is
   done" when four things are waiting one tab away. Quiet by default and
   inheriting the tab's own colour when the tab is active, because it is a
   detail of the tab rather than a second thing to look at.
   --------------------------------------------------------------------------- */
.uc-tab-count { margin-left: 6px; font-size: 11px; font-weight: 700; color: var(--p-muted); }
.uc-view-tab-active .uc-tab-count { color: inherit; }

/* Sits inside the card, above the list, and reads as a caption rather than a
   toolbar: this is one small choice about an order, not a second bar of
   controls competing with the tabs directly above it. */
.uc-queue-sort { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 12px;
    margin: 0 0 4px; font-size: 12px; }
.uc-queue-sort-label { color: var(--p-muted); font-weight: 600; }
.uc-queue-sort-link { color: var(--p-muted); font-weight: 600; text-decoration: none;
    padding: 2px 0; border-bottom: 1px solid transparent; }
.uc-queue-sort-link:hover { color: var(--uc-accent-text); }
.uc-queue-sort-link:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: 2px; border-radius: 3px; }
/* The active one is the only one wearing the text colour, and it carries the
   arrow. Weight alone would not say which of two links is the live one. */
.uc-queue-sort-active { color: var(--p-text); border-bottom-color: currentColor; }

/* THE THUMBNAIL IS A FLEX ITEM HERE, NOT A FLOAT. It floats inside the old
   table cell it was written for; a float is ignored on a flex child, so
   without this it would shrink under the row's `gap` and stop being square. */
.uc-queue-row > .uc-submitted-thumb { flex: 0 0 auto; float: none; margin: 2px 0 0; }

/* ---------------------------------------------------------------------------
   THE SUBMITTED PICTURE AND ITS BUTTON (3.72.0).

   The thumbnail gained a control under it, so it needed a wrapper to be the
   flex item instead of being one itself. The float reset moves onto that
   wrapper's child for the reason above: the float rule is still the one this
   thumbnail carries everywhere else, and it is still ignored here.

   THE COLUMN IS THE THUMBNAIL'S WIDTH. A button wider than the picture it acts
   on would drag the whole row's first column out and push the title sideways on
   every queue item, including the ones with no picture at all. 12px type in a
   small button fits "Use this image" in that width on two lines, and two lines
   under a 46px square is the right shape for a caption. */
.uc-submitted-shot { flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; gap: 5px; width: 46px; }
.uc-submitted-shot > .uc-submitted-thumb { float: none; margin: 0; }
/* THE COLUMN HOLDS A PICTURE AND NOTHING ELSE NOW (3.95.0). It had a button
   under the thumbnail and two rules sizing it; the button never worked and was
   removed, so both rules matched nothing and are gone with it. Dead CSS is
   worse than no CSS, because the next person reads it as a description of the
   screen. */
/* Already the picture. A statement, not a control, so it takes the muted
   helper step rather than anything that reads as pressable. */
.uc-submitted-note { margin: 0; font-size: 12px; font-weight: 400; line-height: 1.25; text-align: center; color: var(--p-muted, #6B6764); }
/* THE PICTURE WARNING (3.93.0, moved 3.95.0). #b45309 is the amber already
   measured for this screen at 5.02:1, used on the needs-attention flag and the
   strong source link. Amber and not red, the same reasoning as the
   missing-fields mark on this row: a small picture is a step in the job, not a
   fault, and the submission was taken.

   IT IS NO LONGER IN THE 46px PICTURE COLUMN. 3.93.0 put it under the
   thumbnail, beside the button that was there then; with the button gone it
   was a sentence alone in a column too narrow to read one in. It sits with the
   row's other sentences now and takes their size. */
.uc-submitted-warn {
    margin: 0 0 4px; font-size: 12px; font-weight: 400; line-height: 1.4;
    color: #b45309;
}

/* ---------------------------------------------------------------------------
   A DATE ON A CLOSED DAY (3.105.0).

   THE CLOSURE'S OWN COLOUR, NOT A SYSTEM ONE. This stylesheet also dresses the
   two public forms, where DESIGN.md allows palette colours only, so the line
   and the pending flag take the Red family's ink and tint: the same pair the
   calendar draws a closure in, #AD1C0D, 6.10:1 on #FDE9E7, 7.12:1 on
   white and 6.58:1 on the caladmin canvas #F5F6F7, all measured. The words carry it; the red agrees with them.

   The line is the field-label step, because it is read at the moment of
   choosing a date. The flag is the helper step, in the pending row's meta.
   ------------------------------------------------------------------------- */
.uc-closed-warn { display: block; margin: 6px 0 0; font-size: 13px; font-weight: 600; line-height: 1.45; color: #AD1C0D; }
.uc-closed-warn[hidden] { display: none; }
.uc-closed-flag { display: inline-block; padding: 0 8px; border-radius: 99px; background: #FDE9E7; color: #AD1C0D;
    font-size: 12px; font-weight: 400; line-height: 1.6; }

/* The approval prompt lives in the actions column when JavaScript is off, and
   that column sizes to its content. Unbounded, its two sentences would make
   the column wider than the row it belongs to. */
.uc-queue-actions .uc-approve-ask { max-width: 320px; }

/* ---------------------------------------------------------------------------
   THE DISCLOSURE IS SUBORDINATE TO ITS ROW, AND NOW LOOKS IT.

   The comment here already said "quieter than the meta line above it, and
   carrying no card of its own" while the rule underneath gave it a 1px border,
   a 10px radius and a white background. So the subordinate element was the
   only thing on the screen wearing a card, the row it belonged to was not, and
   the most prominent object in the queue was a collapsed disclosure. The
   description was right and had simply never been what the code did.

   No border, no fill, no radius. The summary is sized to its own text instead
   of spanning the row, so it reads as a link under the row rather than as a
   bar across it, and `width: fit-content` gets that without changing `display`
   away from list-item, which would take the marker with it.

   Open, the form is grouped by ONE HAIRLINE down its left and an indent. That
   is the house order: space first, then a hairline, and a box not at all.
   --------------------------------------------------------------------------- */
.uc-queue-item > .uc-queue-panel { margin: 10px 0 0; }
.uc-queue-panel { border: 0; border-radius: 0; background: none; }
.uc-queue-panel > summary { width: fit-content; cursor: pointer; padding: 2px 0;
    font-size: 13px; font-weight: 600; color: var(--p-muted); list-style: revert; }
.uc-queue-panel > summary:hover { color: var(--uc-accent-text); }
.uc-queue-panel > summary:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: 2px; border-radius: 4px; }
.uc-queue-panel[open] > summary { margin-bottom: 10px; }
.uc-queue-form { padding: 0 0 4px 16px; border-left: 2px solid var(--p-border); }
.uc-queue-form .uc-form-actions { display: flex; align-items: center; gap: 14px; margin-top: 16px; }

@media (max-width: 720px) {
    .uc-queue-actions { flex: 1 1 100%; padding-top: 8px; }
}

/* ---------------------------------------------------------------------------
   THE PENDING QUEUE'S BULK BAR (3.103.0).

   The events list's bar, stacked: one panel with one Apply, and an action
   row, separated from the list by the same hairline the events list uses
   and carrying no card of its own.
   --------------------------------------------------------------------------- */
.uc-pending-bulk {
    display: flex; flex-direction: column; gap: 10px;
    margin: 0 0 14px; padding: 0 0 14px;
    border-bottom: 1px solid var(--p-border);
}
.uc-pending-bulk-row { display: flex; align-items: flex-end; flex-wrap: wrap; gap: 12px; }
/* ONE PANEL, THREE CONTROLS SIDE BY SIDE (3.104.0), and one Apply under them.
   The two tick lists scroll inside a fixed height so a long organizer list
   cannot push Apply off the screen; below 720px the columns stack. */
.uc-pending-panel { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; align-items: start; }
.uc-pending-panel-col { margin: 0; min-width: 0; }
.uc-pending-panel-list { display: flex; flex-direction: column; gap: 6px; max-height: 180px; overflow-y: auto; margin-top: 8px; padding: 8px 10px; border: 1px solid var(--p-border); border-radius: 8px; }
@media (max-width: 720px) {
    .uc-pending-panel { grid-template-columns: 1fr; }
}
.uc-pending-bulk button[disabled] { opacity: 0.55; cursor: not-allowed; }

/* The row's tick, first in the row and level with the title's first line. */
.uc-queue-tick { flex: 0 0 auto; padding-top: 3px; }
.uc-queue-tick input[type="checkbox"] { margin: 0; width: auto; }

/* WHY A ROW WILL NOT PUBLISH YET, in the amber the picture warning uses on
   this row (#b45309, 5.02:1). A step in the job, not a fault. */
.uc-queue-hold { margin: 0 0 4px; font-size: 12px; font-weight: 400; line-height: 1.4; color: #b45309; }

/* EVERY ROW A PUBLISH HELD, NAMED (3.103.0). Under the outcome sentence, on
   the warn flash, one line per event with the title as the way in. */
.uc-held p.uc-held-head { margin: 0; }
.uc-held-list { margin: 6px 0 0; padding-left: 18px; font-weight: 400; }
.uc-held-list li { margin: 2px 0; }
.uc-held-list a { color: inherit; text-decoration: underline; }

/* ---------------------------------------------------------------------------
   THE FOUR EMAILS, BEHIND A DISCLOSURE (3.25.0).

   Reuses the team picker's inline disclosure rather than inventing a third
   kind: same summary pill, same chevron, same states. What is added here is
   only the spacing between a switch and the line that explains it, because
   these labels are a sentence each and read as a block without it.

   THE NOTE UNDER EACH SWITCH IS INDENTED TO THE LABEL TEXT, not to the
   checkbox, so the four notes line up with the four things they describe
   rather than with the boxes.
   ------------------------------------------------------------------------- */
.uc-notify-kinds .uc-check { margin-top: 12px; }
.uc-notify-kinds .uc-check:first-of-type { margin-top: 4px; }
.uc-notify-kind-note { margin: 2px 0 0 26px; }
/* THE TWO ALWAYS SENT (3.113.1): no box, so the label is indented to where the
   ticked ones' text starts, with the pill after it. The first rule above
   matches the first <label>, which is no longer the first row. */
.uc-notify-kinds .uc-notify-always { margin: 12px 0 0; padding-left: 26px; font-size: 14px; line-height: 1.5; }
.uc-notify-kinds input[type="hidden"] + .uc-notify-always { margin-top: 4px; }
.uc-notify-kinds .uc-notify-always ~ .uc-check:first-of-type { margin-top: 12px; }
.uc-notify-kinds .uc-notify-always-tag { margin-left: 6px; text-transform: none; }

/* ---------------------------------------------------------------------------
   WHO HEARS AND EMAILS FOR THIS EVENT ARE CONTROLS (3.113.0).

   Each is a subhead, a status line and the secondary button. The button is
   the <summary> of the disclosure that holds the panel, so it opens with no
   script; it is sized to its label, and the panel opens under it in the
   picker's bordered box. The status line is 14px --p-text, the card's body
   line, and the section's 10px gap is the only space around it.
   --------------------------------------------------------------------------- */
.uc-portal .uc-notify-status { margin: 0; font-size: 14px; line-height: 1.5; color: var(--p-text); }
.uc-portal .uc-notify-picker > .uc-notify-status { margin-bottom: 10px; }
.uc-notify-choose > .uc-notify-choose-btn { width: fit-content; list-style: none; }
.uc-notify-choose > .uc-notify-choose-btn::-webkit-details-marker { display: none; }
.uc-notify-choose > .uc-notify-choose-btn::marker { content: ""; }
.uc-notify-choose > .uc-picker-panel {
    margin-top: 10px;
    border: 1px solid var(--p-border); border-radius: 10px; background: #fff;
}

/* ---------------------------------------------------------------------------
   TEAMS AS AN ACCESS MODEL (3.35.0).

   Three small surfaces, all of them reference rather than decoration: who can
   edit an event, what an access level grants, and the reassignment a removal
   asks for. Each stays inside a control shape the portal already has, so
   nothing here introduces a new pattern to keep in step.
   ------------------------------------------------------------------------- */

/* The editor's "Who can edit this" card. */
.uc-access-organizer { margin: 0 0 10px; font-size: 13.5px; line-height: 1.5; }
.uc-access-organizer .uc-muted { display: block; margin-top: 2px; font-size: 12.5px; line-height: 1.5; }
.uc-access-teams { display: flex; flex-direction: column; gap: 6px; margin: 10px 0; }
.uc-access-teams .uc-check { align-items: flex-start; }
.uc-access-teams .uc-muted { margin-left: 6px; font-size: 12px; }
/* Team and access (3.110.1): two groups, teams then people; the people list
   scrolls past eight names rather than lengthening the side column. */
.uc-access { margin-top: 12px; }
.uc-access-group { margin: 0 0 12px; padding: 0; border: 0; min-width: 0; }
.uc-access-group > legend { padding: 0; margin: 0 0 4px; }
.uc-access-people { display: flex; flex-direction: column; gap: 6px; max-height: 260px; overflow-y: auto; padding: 8px 10px; border: 1px solid var(--p-border); border-radius: 8px; background: var(--p-panel); }
.uc-access-people .uc-check { margin: 0; }
.uc-public-heading { margin: 20px 0 8px; font-size: 16px; font-weight: 600; color: var(--p-text); }
/* The notify tick is a different question from the boxes above it, so a rule
   separates them rather than a gap somebody has to interpret. */
.uc-access-notify { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--p-border); }

/* What each access level can do. The 3.10.0 disclosure, wearing the same
   toggle as the RSVP settings panel: a summary, so click, tap, Enter and
   Space all work with no script at all. */
/* ONE DECLARATION EACH (3.64.0). All three of these were declared twice, here
   and again 220 lines down beside the organizer rows, at the same specificity.
   The later one won for what it named and this one survived for what it did
   not, so reading either gave the wrong padding, the wrong size, or a card that
   is not there. Merged, at the values that were actually reaching the screen.

   The disclosure is INSIDE the add-user card, not a card of its own further up
   the page (3.38.0): help anywhere other than beside the control it explains is
   help nobody finds at the moment they need it. */
.uc-role-help { margin: 0 0 16px; border: 1px solid var(--p-border);
    border-radius: 10px; background: var(--p-bg); }
.uc-role-help-toggle { display: flex; align-items: center; gap: 8px; cursor: pointer;
    padding: 10px 14px; font-size: 13.5px; list-style: none; }
.uc-role-help-toggle::-webkit-details-marker { display: none; }
.uc-role-help-toggle::marker { content: ""; }
.uc-role-help-toggle:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: -2px; }
.uc-role-help-body { padding: 0 14px 14px; }
.uc-role-help-list { margin: 0; }
.uc-role-help-list dt { margin: 12px 0 2px; font-size: 13px; font-weight: 600; }
.uc-role-help-list dt:first-child { margin-top: 0; }
.uc-role-help-list dd { margin: 0; font-size: 13px; line-height: 1.6; color: var(--p-muted); max-width: 78ch; }

/* Reassign before removing. Attention-coloured because it is a refusal, and
   the refusal is the point: nothing was removed and something is needed. */
.uc-reassign { margin-top: 12px; padding: 14px 16px; border: 1px solid var(--p-border-strong);
    border-radius: 10px; background: #fffbeb; }
.uc-reassign-head { margin: 0 0 8px; font-size: 13.5px; line-height: 1.5; }
.uc-reassign-events { margin: 0 0 12px; padding-left: 18px; font-size: 13px; line-height: 1.7; }
.uc-reassign-events .uc-muted { margin-left: 6px; font-size: 12px; }
.uc-reassign-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px; }
.uc-reassign-form label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; font-weight: 600; }

/* ---------------------------------------------------------------------------
   CANCELLING (3.36.0).

   A cancelled event is not an error state and not a warning: it is a decision
   somebody made, and the screen says so plainly rather than shouting. The red
   is reserved for the button that performs it and for the pill that reports it,
   which are the two places a colour is carrying an actual consequence.
   ------------------------------------------------------------------------- */
.uc-cancel-card.is-cancelled { border-color: #b91c1c; }
/* Body, and the red ink is what carries it. There is no 700 at this size on the
   ladder, and the card title above already says the event is cancelled, so the
   weight was doing the title's job a second time. */
.uc-cancel-state { margin: 0 0 8px; font-size: 14px; font-weight: 400; color: #b91c1c; }
.uc-cancel-state .uc-muted { display: block; margin-top: 2px; font-size: 12px; font-weight: 400; }
.uc-cancel-form { margin-top: 12px; }
.uc-cancel-visibility { margin: 0 0 12px; padding: 0; border: 0; }
/* A legend over a set of radio options is a field label, and takes that step. */
.uc-cancel-visibility legend { padding: 0; margin-bottom: 8px; font-size: 13px; font-weight: 600; }
/* THESE ARE OPTION CARDS NOW (3.64.0), and it is a visible change on this
 * card. They were a bare stack of radios at 13px, because the rule that drew
 * the card was scoped to markup that no longer exists and this ancestor rule
 * was the only one reaching them. A choice between leaving a cancelled event
 * listed and taking it off the public calendar is exactly the kind the card
 * exists for: two consequences, written under the thing that causes them.
 * All that is left here is the space between two of them. */
.uc-cancel-visibility .uc-radio-opt { margin-bottom: 8px; }
.uc-cancel-visibility .uc-radio-opt strong { display: block; }
/* NO SECOND .uc-btn-danger HERE (3.39.0). This file already declares one,
   white on #c0392b at 5.44:1. A second rule at the same specificity set
   colour and border-colour and inherited the first rule's background, so the
   delete button rendered #b91c1c on #c0392b: two reds, 1.19:1, very close to
   invisible. That is the category-chip mistake from before 3.15.0, one colour
   used as both tint and ink. Measured by .claude/destructive-contrast.php,
   which now fails if this class is declared twice again. */

/* The count and the tick, wherever the prompt appears. One block, three
   callers: cancelling one event, cancelling a series, and saving a move. */
.uc-notice-block { margin: 12px 0; padding: 12px 14px; border: 1px solid var(--p-border-strong);
    border-radius: 10px; background: var(--p-bg); }
.uc-notice-count { margin: 0 0 8px; font-size: 13.5px; line-height: 1.5; }
.uc-notice-block .uc-hint { margin-top: 6px; }
.uc-change-notice { max-width: 78ch; }

/* Cancelled, in a list of events. Beside the status pill and never instead of
   it: a cancelled event is still published or still a draft, and the row has to
   say both. */
.uc-pill-cancelled { background: #fef2f2; color: #b91c1c; border-color: #b91c1c; }

.uc-cancel-instead { border-color: #b91c1c; }

/* ---------------------------------------------------------------------------
   ORGANIZERS (3.37.0).

   The list is plain text with actions, which is the shape Teams took in 3.20.0
   and for the same reason: a screen made of live inputs invites an accidental
   edit on every visit and gives no reading of what is there. Editing is a
   disclosure per row, opened deliberately.

   THE SPACING BASELINE APPLIES HERE, and is not left to the container to
   supply. .uc-organizer-row carries its own padding rather than relying on the
   card, because 3.34.0 found five screens that looked correct only because
   every child happened to carry some and one that did not.
   ------------------------------------------------------------------------- */
/* THESE TWO ARE DECLARED FURTHER DOWN, with the rules that made the closed
   disclosure stop looking like a panel (3.38.0). Both were declared HERE as
   well, at the same specificity and with different values, so the pair that
   reached the screen was the later one and this pair read as if it worked.
   3.64.0 removed them rather than reconciling them, because there is nothing
   here the later block does not say. */
.uc-organizer-add-body .uc-field { margin-bottom: 12px; }

/* Padding and align-items are NOT here: the row rhythm block below declares
   both, later and at the same specificity, and its values are the live ones. */
.uc-organizer-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "id actions" "edit edit";
    gap: 4px 12px;
    border-bottom: 1px solid var(--p-border);
}
.uc-organizer-row:last-child { border-bottom: 0; }
.uc-organizer-id { grid-area: id; min-width: 0; }
.uc-organizer-id strong { display: block; font-size: 14px; line-height: 1.4; }
.uc-organizer-id .uc-muted { display: block; margin-top: 2px; font-size: 12px; line-height: 1.5; }
.uc-organizer-id code { font-size: 11.5px; }
.uc-organizer-actions { grid-area: actions; display: flex; gap: 8px; align-items: center; }
.uc-organizer-edit { grid-area: edit; margin-top: 8px; }
.uc-organizer-edit-body { margin-top: 10px; padding: 14px 16px;
    border: 1px solid var(--p-border); border-radius: 10px; background: var(--p-bg); }
.uc-organizer-edit-body .uc-field { margin-bottom: 12px; }
.uc-organizer-delete { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--p-border); }
.uc-organizer-delete .uc-hint { display: block; margin-top: 6px; }

/* Add one without leaving the event form. A disclosure under the picker, so it
   is out of the way until it is wanted and costs nothing when it is not. */

/* The pointer to the WordPress fallback screen. Present, and quiet: it is a
   fallback, not a route anybody should be taking by default. */
.uc-help-quiet { margin-top: 16px; font-size: 12.5px; color: var(--p-muted); }

@media (max-width: 640px) {
    .uc-organizer-row { grid-template-columns: minmax(0, 1fr); grid-template-areas: "id" "actions" "edit"; }
}

/* ---------------------------------------------------------------------------
   THE LEADING ACTION ON A LIST SCREEN LEADS (3.38.0).

   Every list screen's add control was a white outline disclosure on a white
   card, so nothing on the screen led. The submit INSIDE it was already primary,
   which is the wrong half: the control somebody has to find first is the one
   that opens the form, not the one that closes it.

   .uc-add-toggle is the one class for that control, worn by Organizers and
   Venues. Teams and Series reach the same place through a link, so they take
   .uc-btn-primary directly. Per-row Edit toggles keep .uc-team-add-toggle and
   stay quiet: on a screen of twelve organizers, twelve yellow controls would
   mean none of them led either.

   YELLOW WITH INK, which is the only permitted text-on-yellow pair in the brand
   guide, and yellow is reserved for actions. See DESIGN.md.
   ------------------------------------------------------------------------- */
.uc-add-toggle {
    display: inline-flex; align-items: center; gap: 8px;
    cursor: pointer; list-style: none;
    padding: 9px 16px; margin: 0;
    border: 1px solid var(--sfaf-yellow, #FFD900);
    border-radius: 8px;
    background: var(--sfaf-yellow, #FFD900);
    color: var(--p-text);
    font-size: 13.5px; font-weight: 700;
}
.uc-add-toggle::-webkit-details-marker { display: none; }
.uc-add-toggle::marker { content: ""; }
.uc-add-toggle:hover { filter: brightness(0.95); }
.uc-add-toggle:focus-visible { outline: 2px solid var(--p-text); outline-offset: 2px; }

/* ---------------------------------------------------------------------------
   A SET ON THE FAQ SETS SCREEN, COLLAPSED (3.63.0).

   Every set rendered fully expanded, so the screen was every question of every
   set at once. Each one is a <details> now, closed by default.

   THE SUMMARY IS THE CARD'S OWN HEAD, not a button. It wears the same band,
   the same full-bleed negative margins and the same type as .uc-card-head, so
   a closed set reads as a card that has a head and nothing else yet, rather
   than as a new kind of control. The negative margins are restated rather than
   inherited: .uc-card-head is a class this element does not carry, and giving a
   <summary> two classes that both set margin is how they come to disagree.

   DELIBERATELY NOT .uc-add-toggle, which is yellow. Yellow means "act on this"
   and is reserved for the one control that leads a screen, which here is
   "Create a set". A page of twelve yellow set headers would mean none of them
   led. See DESIGN.md.

   NO name ATTRIBUTE ON THESE, so two can be open at once: somebody comparing
   two sets needs both, and a named group is exclusive.
   ------------------------------------------------------------------------- */
.uc-faq-set { padding: 20px; }
.uc-faq-set-toggle {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    cursor: pointer; list-style: none;
    margin: -20px -20px 0; padding: 11px 20px;
    background: var(--uc-band); border-bottom: 1px solid var(--p-border);
    /* 14 / 600 is the card-heading step, which is what this is. It was written
       at 700 and the sweep caught it: between two steps, the headings above and
       below it stop reading as a hierarchy. See DESIGN.md. */
    font-size: 14px; font-weight: 600; color: var(--p-text);
}
.uc-faq-set[open] > .uc-faq-set-toggle { margin-bottom: 16px; }
.uc-faq-set-toggle::-webkit-details-marker { display: none; }
.uc-faq-set-toggle::marker { content: ""; }
.uc-faq-set-toggle:hover { filter: brightness(0.97); }
.uc-faq-set-toggle:focus-visible { outline: 2px solid var(--p-text); outline-offset: -2px; }
.uc-faq-set-name { flex: 1 1 auto; }

/* Duplicate and Delete on one line, the quiet button first. Delete keeps
   .uc-link-danger and is not a button, so it does not compete. */
.uc-faq-set-ops { display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
    margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--p-border); }
.uc-faq-set-ops form { margin: 0; }

/* The card wrapping an add disclosure has no business looking like a panel
   until it is open: closed, it is one control. */
.uc-organizer-add { padding: 0; border: 0; background: none; margin-bottom: 20px; }
.uc-organizer-add[open] { padding: 20px; border: 1px solid var(--p-border);
    background: var(--p-panel); border-radius: 12px; }
.uc-organizer-add-body { padding: 16px 0 0; }

/* ---------------------------------------------------------------------------
   ROW RHYTHM (3.38.0, item 2b).

   The organizer rows ran into each other: a hairline between them and nothing
   else, so twelve organizers read as one block of text. Alternating surface
   gives the eye somewhere to rest without adding a rule per row, and the name
   gets the weight it should have had.
   ------------------------------------------------------------------------- */
.uc-organizer-row { padding: 16px; align-items: center; }
.uc-organizer-row:nth-child(even) { background: var(--p-bg); }
.uc-organizer-row:hover { background: var(--uc-band, #f1f5f9); }
.uc-organizer-id strong { font-size: 14px; font-weight: 600; }
.uc-organizer-id .uc-muted + .uc-muted { margin-top: 4px; }

/* The role help disclosure is declared once, up beside .uc-role-help-list. */

/* ---------------------------------------------------------------------------
   SERIES PREFILL, AT CREATION (3.38.0).

   The first card on a new event, because what it is one of decides most of the
   rest. Hidden until a series is chosen, and hidden again when the choice goes
   back to none: a panel of checkboxes about nothing is worse than no panel.
   ------------------------------------------------------------------------- */
/* No margin of its own (3.107.1): it sits in the main column, whose 16px gap is
   the space between every card. The 18px it had added to that gap. */
.uc-prefill { margin-top: 14px; padding: 14px 16px; border: 1px solid var(--p-border);
    border-radius: 10px; background: var(--p-bg); }
.uc-prefill-head { margin: 0 0 10px; font-size: 13.5px; line-height: 1.5; }
.uc-prefill-opts { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
.uc-prefill-opts .uc-check { align-items: flex-start; }
.uc-prefill-opt-text { display: block; font-size: 13px; line-height: 1.45; }
.uc-prefill-opt-text strong { display: block; font-weight: 700; }
.uc-prefill-opt-text .uc-muted { display: block; font-size: 12px; margin-top: 1px; }
/* The image row shows the picture (3.64.2). Sized in the stylesheet and cropped
   to the 16:9 the cards use, so a portrait file cannot make this row twice the
   height of the five around it. 160 x 90 with the cards' 12px radius since
   3.108.1; it was 56 x 32 at 4px. */
.uc-prefill-thumb { display: block; width: 160px; height: 90px; margin-top: 4px;
    object-fit: cover; border-radius: 12px; border: 1px solid var(--p-border); }
.uc-prefill-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.uc-prefill-said { margin: 10px 0 0; font-size: 12.5px; }

/* ---------------------------------------------------------------------------
   THE SAME PANEL ON THE STAFF REQUEST FORM (3.77.0)

   initRequestPrefill() builds its rows with named classes rather than a <strong>
   and a .uc-muted, because it has a third line the caladmin card does not: what
   the row would overwrite. The three below give it the same look the card has,
   so the two panels are one thing on two screens rather than two that resemble
   each other.
   ------------------------------------------------------------------------ */
.uc-prefill-opt-label { display: block; font-size: 13px; font-weight: 600; line-height: 1.45; }
.uc-prefill-opt-value { display: block; font-size: 12px; line-height: 1.4; margin-top: 1px;
    color: var(--p-muted, #6B6764); overflow-wrap: anywhere; }
/* WHAT IT WOULD TAKE BACK, IN ATTENTION INK AND NOT IN RED. Overwriting an
   answer somebody typed is worth saying and is not destructive: the row stays
   ticked, the decision stays theirs, and red here would be the only red on a
   form nobody is about to break anything on. Same ink as
   .uc-field-note-attention above.

   AND IT IS THE HELPER STEP, 12/400, NOT A BOLDER ONE. It was 12/600 and the
   type sweep was right to refuse it: the sentence itself says what happens, so
   the ink is reinforcement rather than the carrier, and a weight between two
   steps buys nothing the words do not already have. */
.uc-prefill-opt-warn { display: block; font-size: 12px; line-height: 1.4; margin-top: 2px;
    color: #92400e; }

/* The rich text editor, inside a bento card (3.38.0). TinyMCE brings its own
   chrome; this only stops it overflowing a card that has a radius. */
.uc-field .wp-editor-wrap { margin-top: 4px; }
.uc-field .wp-editor-container { border-radius: 8px; overflow: hidden; border: 1px solid var(--p-border-strong); }
.uc-field .mce-toolbar-grp { border-bottom: 1px solid var(--p-border) !important; }

/* The FAQ set create rows on the FAQ Sets screen. */

/* ---------------------------------------------------------------------------
   THE TWO PUBLIC FORMS (3.46.0)

   SFAF_Request and SFAF_Submit draw the same card in the same document, so
   everything here applies to both and nothing is written twice. The banner and
   the grouped fieldset are the community form's alone, because it is the one
   with a campaign behind it and a stranger filling it in.
   --------------------------------------------------------------------------- */

/* THE SERIES IMAGE, FULL BLEED ACROSS THE TOP OF THE CARD. It pulls back out
   through the card's own padding, so the number is read from the variable the
   card sets rather than copied here: a padding that changes and an escape that
   does not is the fault the sidebar heading band shipped in 3.45.1. */
.uc-submit-banner { margin: calc(-1 * var(--uc-request-pad)) calc(-1 * var(--uc-request-pad)) 20px;
    line-height: 0; overflow: hidden; border-radius: 12px 12px 0 0; }
/* THE WHOLE PICTURE, AT ITS OWN PROPORTIONS (3.47.0).

   BEFORE: `max-height: 220px` with `object-fit: cover`, which crops. A series
   image is prepared for CARDS, which are 16:9, so a 1200x675 picture at the
   card's aspect was being cut to roughly 1200x220, a 5.5:1 letterbox. That
   takes about two thirds of the height out of the middle of somebody's
   artwork, and on a campaign banner the part that goes is usually the part
   with the logo or the faces in it.

   AFTER: no height cap and no cover, so the image is shown whole at its
   natural proportions. On a 720px card a 16:9 image is 405px tall, which is
   a banner rather than a strip and is the shape the picture was made in.

   WHY NOT A SECOND, WIDER IMAGE. It would be a second place to put the
   artwork, which is the setting this form deliberately does not have, and it
   would be empty for every campaign whose series predates it. Showing the
   whole of the one image that exists is correct for any shape somebody
   uploads; cropping is only correct when you know what is in the frame. If a
   campaign later wants a distinct banner, the honest fix is a wider series
   image, not a second field here. */
.uc-submit-banner img { width: 100%; height: auto; display: block; }

/* ---------------------------------------------------------------------------
   THE BANNER IS A LIVE PREVIEW, AND THE ZOOM IS SHORT (3.80.0)

   260ms, AND THAT NUMBER IS THE WHOLE OF THE CARE HERE. Somebody comparing
   three programmes will change the series select three times, and a reveal that
   is a pleasure the first time is an obstruction the third. Long enough to read
   as the picture arriving; short enough that nobody waits for it.

   scale AND opacity TOGETHER, from 1.04. Scaling DOWN to rest means the picture
   never renders larger than its box, so there is nothing to clip and no moment
   where it overhangs the card: the overflow: hidden above is a second belt
   rather than the thing holding it in.

   IT PLAYS ON THE ELEMENT, NOT THE IMAGE, so a picture that is still decoding
   does not animate an empty box and then pop. portal.js adds the class after
   setting src, and takes it off and forces a reflow first so the animation
   restarts on the second and third change rather than playing once.

   NOTHING DEPENDS ON IT. With the class never added the banner is simply
   there, which is what a browser with reduced motion gets by the rule below
   and what a browser with no script gets by never reaching initFormBanner(). */
.uc-submit-banner.is-in { animation: uc-banner-in 260ms cubic-bezier(.2, .7, .3, 1) both; }
@keyframes uc-banner-in {
    from { opacity: 0; transform: scale(1.04); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .uc-submit-banner.is-in { animation: none; }
}

/* ---------------------------------------------------------------------------
   WHAT WAS ATTACHED, AND WHAT IS GOING TO HAPPEN TO IT (3.80.0)

   A thumbnail, small, under the file input. It is not the banner and must not
   look like it: an uploaded file is a WORKING COPY that an approver decides
   about, and the event's picture goes on being the series' one until they do.

   THE THUMBNAIL IS THERE TO SAY IT ARRIVED. Somebody who attaches a photograph
   and sees nothing whatever change will attach it again, or give up and think
   the form is broken. THE LINE UNDER IT IS THERE TO STOP THE THUMBNAIL SAYING
   MORE THAN THAT, which is the reason they are one block and not two.
   ------------------------------------------------------------------------ */
.uc-upload-preview { margin-top: 10px; }
.uc-upload-preview img {
    display: block; width: 100%; max-width: 220px; height: auto;
    border: 1px solid var(--p-border); border-radius: 8px;
}
.uc-upload-preview .uc-hint { margin: 6px 0 0; }

/* ---------------------------------------------------------------------------
   NOTHING TAGGED TO THIS SERIES YET (3.80.0)

   IT REPLACES A FALLBACK, IT DOES NOT DECORATE ONE. The picker used to show
   the whole folder when a series had no pictures of its own, which is
   indistinguishable from the filter not working and was reported as exactly
   that twice. This is the sentence that says which it is, and it names who to
   ask, because the person reading it cannot tag an image themselves.
   ------------------------------------------------------------------------ */
.uc-picker-no-series { margin: 0; padding: 14px 4px; font-size: 13px; line-height: 1.5; }

/* ---------------------------------------------------------------------------
   ONE SECTION MECHANISM ON BOTH REQUEST FORMS (3.68.0).

   WHAT WAS WRONG, AND IT WAS NOT THE TYPE. 3.66.0 fixed the type: a group
   heading had been set at the field-label step, so a heading and the labels
   under it rendered identically. That fix was right and is untouched. What it
   could not fix is that a rule between sections is the only thing dividing
   them, on a white card, in black text, and there were TWO mechanisms drawing
   it, of which one was silently losing:

     .uc-request-card fieldset.uc-field    (0,2,1)  border: 0; padding: 0
     .uc-form-section-group                (0,1,0)  border-top: 1px; padding: 18px 0 0

   One class loses to one class plus one type, which is the recurring fault on
   this project. So the picture section and the team section had no rule and no
   top padding at all, while the <h2> sections beside them did, and a form of
   six sections drew four dividers.

   THE FIX IS ONE MECHANISM AND A SURFACE, NOT A SPECIFICITY WAR. Every section
   on both forms is now a <fieldset class="uc-form-section-group"> with a
   <legend class="uc-field-group-title">, and none of them carries .uc-field, so
   the reset above cannot reach them. .uc-field-group and .uc-form-section were
   the other two spellings of this and are gone; nothing outside these two forms
   ever used either.

   > AND THE SAME FAULT ONE LEVEL ALONG, WHICH IS 3.68.1. The reset was three
   > properties, but the CLASS carrying it was also `display: flex`, and that was
   > holding a floated legend inert. Taking the class away to stop the reset
   > matching took the layout mode with it. **A section declares its own display
   > below**, so it can never again depend on a class it should not carry.

   THE SURFACE CARRIES NO INFORMATION, which is what DESIGN.md's decoration rule
   requires of it. One neutral tint and one neutral hairline, the same on every
   section of both forms, so it groups without claiming that any section is a
   state, a category or a warning. It is the treatment the community form's
   three groups already had; what changed is that the staff form has it too.

   NO NEW TYPE STEP. The legend keeps .uc-field-group-title, which is the
   Subhead step 16/600 that 3.66.0 settled on, declared once below.
   ------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
   THE SECTION DECLARES ITS OWN LAYOUT MODE, AND THAT IS THE WHOLE OF 3.68.1.

   WHAT 3.68.0 BROKE. The legend was floated, to get it out of the fieldset's
   top border so the panel's edge could draw unbroken. That float had existed
   since 3.66.0 and HAD NEVER RUN: both fieldsets carrying the rule also carried
   .uc-field, which is `display: flex`, and float computes to none on a flex
   item. Removing .uc-field, which is what 3.68.0 did to stop the reset above
   reaching a section, switched the float on for the first time.

   A LIVE FLOAT AND A FLEX SIBLING DO NOT SHARE A LINE. Every first child of
   every section on both forms is .uc-field, .uc-field-row, .uc-check or
   .uc-check-grid, and all four are flex or grid containers. A flex or grid
   container establishes its own formatting context, so it refuses to overlap a
   float and is placed BESIDE it; and a flex item's `min-width: auto` means it
   cannot shrink to nothing, so it overflowed into a narrow column at the right
   with the heading on the left. Only the first child sat at the float's
   vertical position, which is why every field after it was correct.

   SO THE FIX IS TO DECLARE THE LAYOUT MODE HERE rather than inherit one by
   accident from a class the section should not carry. A flex column stacks the
   legend above the fields inside the padding, exactly as the float was trying
   to, and it does it by making the float impossible rather than by arranging
   for it to be harmless. The float, the width and the clearfix are gone with
   it: there is nothing left to clear.

   NO GAP, DELIBERATELY. The children carry their own margins, `.uc-field` at
   18px and the hints at their own values, and a gap on top of those would move
   every field on both forms. Flex changes the stacking mechanism and nothing
   about the spacing.
   ------------------------------------------------------------------------- */
.uc-form-section-group { display: flex; flex-direction: column;
    margin: 0 0 20px; padding: 16px 18px;
    border: 1px solid var(--p-border, #D1D3D4); border-radius: 12px;
    background: var(--p-surface-2, #f6f7f8); margin-inline: 0; }
.uc-form-section-group > legend { padding: 0; margin: 0 0 14px; }
.uc-form-section-group > .uc-hint { margin: 0 0 12px; }
.uc-form-section-group .uc-field:last-child { margin-bottom: 0; }

/* THE SUBHEAD STEP, 16/600, DECLARED ONCE (3.66.0). It sat unused between Field
   label 13/600 and Section 20/700, and it is what a group heading is for. A
   <legend> cannot inherit `.uc-portal h2`, so the pair is stated here and
   nowhere else. */
.uc-field-group-title { font-size: 16px; font-weight: 600; }

/* THE FILE INPUT IS LEFT AS A FILE INPUT. A styled one is a label with the
   real control hidden behind it, and that loses the filename the browser shows
   after choosing, which is the only feedback this form gives that anything was
   attached at all. */
.uc-field-upload input[type="file"] { display: block; width: 100%; padding: 10px 12px;
    border: 1px dashed var(--p-border-strong, #9aa0a6); border-radius: 10px;
    background: #fff; font-size: 14px; }
.uc-field-upload input[type="file"]:focus-visible { outline: 2px solid var(--p-teal-text, #0C666F);
    outline-offset: 2px; }
.uc-request-upload { margin-top: 16px; padding-top: 14px;
    border-top: 1px solid var(--p-border, #D1D3D4); }

/* Turnstile draws its own widget in its own iframe. This only reserves the
   room, so the button below it does not jump when the widget arrives. */
.uc-turnstile { min-height: 68px; }
/* ---------------------------------------------------------------------------
   THE BASELINE THE TWO PUBLIC FORMS WERE MISSING (3.47.0)

   These pages are new surfaces built outside caladmin's chrome, and they picked
   up the card and the field styles while missing two things every portal screen
   has. The same thing happened to Automation and to FAQ Sets, so this is the
   third instance rather than a one-off.

   1. PROSE RHYTHM. .uc-request-card styled h1, the lead hint and .uc-field, and
      never plain <p>. Every paragraph on a confirmation page was therefore at
      the browser default 1em, which is neither the portal's scale nor
      consistent with the hints beside it.

   2. THE ACTION ROW. The submit forms used .uc-form-actions-primary; the four
      terminal pages put their only action in a bare <p>. So the button lost the
      row's border, its 30px separation and its size step, and a neutral white
      .uc-btn on a white card is the SECONDARY weight being asked to be the only
      thing on the page. Those pages now use the same row and the primary
      weight, which is a markup fix rather than a rule added here.
   --------------------------------------------------------------------------- */
.uc-request-card p { margin: 0 0 14px; line-height: 1.6; }
.uc-request-card p:last-child { margin-bottom: 0; }
/* The action row is the end of the page, so it does not also carry the card's
   bottom margin under it. */
.uc-request-card .uc-form-actions-primary:last-child { margin-bottom: 0; }

/* THE REVEALED FIELD. Hidden only once the script has decided, never by CSS
   alone: see the note in portal.js. [hidden] needs saying because .uc-field is
   display:block and would win. */
.uc-reveal-target[hidden] { display: none; }
.uc-address-parts { margin-top: 4px; }

/* State and ZIP sit beside a city that needs the room. */
.uc-field-narrow { flex: 0 0 auto; max-width: 110px; }

/* NO COLOURED EDGE ON THE PUBLIC GROUP, AND THE AUDIT WAS RIGHT TO REFUSE IT.
   One was written, arguing that the internal/public distinction is the most
   consequential thing on this form. It is, but colour is not the only thing
   carrying it: the legend says "Contact for the event" and the hint above the
   fields says in bold that it appears on the public listing. Where the words
   already say it, an edge in brand teal is decoration, and DESIGN.md keeps
   accent edges only where colour is the SOLE carrier. The words stay; the
   edge goes. */

/* The picture's title moved with the grid it was clamping (3.65.0). It is
   .uc-image-option-name now, declared beside the rest of the picker. */

/* ---------------------------------------------------------------------------
   THE APPROVAL PROMPT (3.48.0)

   The panel sits in the pending row and portal.js lifts it into the dialog. It
   is styled for BOTH places, because without JavaScript it never moves, and a
   block that only looks right inside a dialog would be the fallback looking
   broken rather than plain.
   --------------------------------------------------------------------------- */
.uc-approve-ask { margin: 8px 0 0; padding: 12px 14px; border: 1px solid var(--p-border);
    border-radius: 10px; background: var(--p-surface-2, #f6f7f8); text-align: left; }
.uc-approve-ask[hidden] { display: none; }
.uc-approve-who { margin: 0 0 10px; font-size: 14px; line-height: 1.5; }
.uc-approve-who .uc-muted { margin-left: 6px; }
.uc-approve-ask .uc-check { display: flex; gap: 8px; align-items: flex-start; margin-bottom: 8px; }
.uc-approve-ask .uc-hint { margin: 2px 0 0; }

/* Wider than a one-sentence confirm, because this one carries two decisions and
   a sentence explaining what the second sends. */
.uc-approve-modal { max-width: 480px; }
.uc-approve-modal .uc-approve-ask { margin-top: 12px; }

/* ---------------------------------------------------------------------------
   GET A FORM LINK (3.49.0)

   One line on the dashboard, closed, that opens the two public form links.
   It sits above the numbers and must not read as a card: this is opened when a
   campaign launches, not on the daily visit, so it takes a summary's worth of
   space and no more. Quiet ink, no fill, no border, and the accent only on
   hover and focus.
   --------------------------------------------------------------------------- */
.uc-form-links { margin: 0 0 16px; }
/* IT IS STILL A <summary> AND MUST STAY ONE. The no-JavaScript path works
   because a disclosure opens by itself, and the noscript block listing every
   campaign's link is what somebody gets then. A <button> with no script does
   nothing at all, so this is styling and nothing else.

   The primary treatment itself comes from .uc-btn and .uc-btn-primary above,
   which this selector was added to. Only what a summary needs on top of a
   button is here. */
.uc-form-links-open {
    /* The disclosure triangle goes, because the control now reads as a button
       and, with the script running, it opens a dialog rather than expanding.
       display:inline-flex drops the marker in most engines on its own; these
       two are the ones that do not follow it. */
    list-style: none;
    width: fit-content;
}
.uc-form-links-open::-webkit-details-marker { display: none; }
.uc-form-links-open::marker { content: ""; }
.uc-form-links-open svg { flex: 0 0 auto; }

/* Open in place, which is what happens with no JavaScript. Indented under one
   hairline, the house order for a subordinate block: space, then a rule, and
   no box at all. In the dialog the padding comes from the modal instead. */
.uc-form-links[open] .uc-form-links-body { margin: 10px 0 0; padding-left: 14px;
    border-left: 1px solid var(--p-border); }
.uc-form-links-modal .uc-form-links-body { margin: 0; padding: 20px 20px 4px; border-left: 0; }

.uc-portal .uc-form-links-title { margin: 0 0 12px; font-family: var(--uc-font-heading);
    font-size: 16px; font-weight: 600; line-height: 1.3; letter-spacing: 0;
    text-transform: none; color: var(--sfaf-darkgray); }
/* Only shown inside the dialog: opened in place, the summary directly above it
   has already said what this is, and a heading repeating it is noise. */
.uc-form-links:not(.uc-form-links-modal) .uc-form-links-title { display: none; }
.uc-form-links-modal .uc-form-links-title { display: block; }

.uc-form-link + .uc-form-link { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--p-border); }
.uc-portal .uc-form-link h3 { margin: 0 0 2px; font-family: var(--uc-font-heading);
    font-size: 14px; font-weight: 600; line-height: 1.3; letter-spacing: 0;
    text-transform: none; color: var(--sfaf-darkgray); }
.uc-form-link .uc-hint { margin: 0 0 8px; }
.uc-form-link-pick { margin-bottom: 10px; }
.uc-form-link-pick .uc-field { margin: 0; }

/* The field takes the room and the button takes what it needs. The link is
   long, so it wraps to its own line rather than squeezing to nothing. */
.uc-form-link-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.uc-form-link-url { flex: 1 1 260px; min-width: 0; font-family: var(--uc-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 12px; padding: 8px 10px; border: 1px solid var(--p-border); border-radius: 6px;
    background: var(--p-bg); color: var(--p-text); }
.uc-copy-btn { flex: 0 0 auto; min-width: 84px; }

/* The no-JavaScript list. Every campaign's link, written out, because the
   picker above it is the part that is missing and the links are not. */
.uc-form-link-all { margin: 10px 0 0; padding: 0; list-style: none; font-size: 12px; }
.uc-form-link-all li + li { margin-top: 8px; }
.uc-form-link-all code { display: block; margin-top: 2px; word-break: break-all; color: var(--p-muted); }

/* Wider than a confirmation, because it holds a picker and two long links. */
.uc-form-links-modal { width: min(560px, calc(100vw - 32px)); }

/* ---------------------------------------------------------------------------
   A PICTURE SOMETHING IS RELYING ON (3.83.0)

   Where the Remove button would be. Not a warning and not an error: it is a
   statement of what is true, and the reason there is nothing to press. Muted
   and small, because it is a footnote on a card rather than a thing to act on,
   and it wraps rather than widening the card.
   ------------------------------------------------------------------------ */
.uc-media-inuse {
    font-size: 11px; line-height: 1.35; color: var(--p-muted, #6B6764);
    text-align: right; cursor: help;
}

/* ---------------------------------------------------------------------------
   PREFERENCES (3.102.0). Four fieldsets in one card, a gap between each.
   The digest line on a user row is its own line under the address.
   ------------------------------------------------------------------------ */
.uc-prefs .uc-fieldset { margin: 0 0 14px; }
.uc-user-id .uc-user-digest { display: block; margin-top: 2px; }

/* ---------------------------------------------------------------------------
   THE WAITLIST ON THE REGISTRATIONS LIST (3.106.0).

   The counts sit under the page head, as body text. Each waitlist is its own
   card under the registrants. Its pills keep their case: .uc-pill capitalises,
   which is right for one word and turns "Needs a call" into three. Waiting and
   passed are the pill's own grey; an open offer is teal, --uc-accent-text on the band
   --uc-band at 4.94:1; a call to make is amber, #92400E on #FFFBEB at 7.53:1,
   caladmin's system colour for a step in the job.
   ------------------------------------------------------------------------- */
.uc-rsvp-counts { margin: 0 0 16px; font-size: 14px; font-weight: 400; line-height: 1.5; color: var(--sfaf-darkgray); }
.uc-rsvp-counts strong { font-weight: 600; }
.uc-waitlist { margin-top: 20px; }
.uc-waitlist .uc-pill { text-transform: none; }
.uc-waitlist .uc-pill-offered { background: var(--uc-band); color: var(--uc-accent-text); }
.uc-waitlist .uc-pill-offered_manual { background: #FFFBEB; color: #92400E; }
.uc-waitlist .uc-rsvp-actions form { display: inline-block; margin-left: 8px; }

/* ---------------------------------------------------------------------------
   EMAIL TEMPLATES (3.106.0).

   The list of messages down the left, the chosen one on the right as it will
   arrive. At phone width the two stack, list first. Everything is tokens: the
   control edge --p-border-strong, the teal band and its ink --uc-accent-text (4.94:1)
   for a chip and for the chosen message, and --p-danger-text for a
   chip that the next Backspace will remove.
   ------------------------------------------------------------------------- */
.uc-tpl-top { display: flex; gap: 16px; margin: 0 0 16px; }
.uc-tpl-lang { max-width: 220px; }
.uc-tpl-cols { display: grid; grid-template-columns: minmax(200px, 250px) minmax(0, 1fr); gap: 24px; align-items: start; }
.uc-tpl-list ul { list-style: none; margin: 0; padding: 0; }
.uc-tpl-list ul ul { margin: 2px 0 6px 16px; }
.uc-tpl-group { display: block; padding: 8px 10px 2px; font-size: 13px; font-weight: 600; line-height: 1.3; color: var(--sfaf-darkgray); }
.uc-tpl-pick { display: block; width: 100%; min-height: 36px; padding: 8px 10px; border: 0; border-radius: 6px;
    background: transparent; color: var(--sfaf-darkgray); font: inherit; font-size: 14px; font-weight: 400; text-align: left; cursor: pointer; }
.uc-tpl-pick:hover { background: var(--uc-band); }
.uc-tpl-pick[aria-pressed="true"] { background: var(--uc-band); color: var(--uc-accent-text); font-weight: 600; }
.uc-tpl-pick:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: 1px; }
.uc-tpl-main { min-width: 0; }
.uc-tpl-subject { margin: 0 0 10px; font-size: 14px; font-weight: 400; line-height: 1.5; }
.uc-tpl-preview { display: block; width: 100%; height: 640px; border: 1px solid var(--p-border); border-radius: 8px; background: var(--p-control-face); }
.uc-tpl-state { margin: 8px 0 0; font-size: 12px; font-weight: 400; line-height: 1.5; color: var(--p-muted); }
.uc-tpl-form { margin-top: 20px; display: flex; flex-direction: column; gap: 14px; }
.uc-tpl-form[hidden] { display: none; }
.uc-tpl-tokens { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.uc-tpl-token { min-height: 32px; padding: 4px 10px; border: 1px solid var(--p-border-strong); border-radius: 99px;
    background: var(--p-control-face); color: var(--sfaf-darkgray); font: inherit; font-size: 12px; font-weight: 400; cursor: pointer; }
.uc-tpl-token[hidden] { display: none; }
.uc-tpl-editor { min-height: 140px; padding: 10px 12px; border: 1px solid var(--p-border-strong); border-radius: 6px;
    background: var(--p-control-face); font-size: 14px; font-weight: 400; line-height: 1.6; white-space: pre-wrap; overflow-wrap: anywhere; }
.uc-tpl-editor-line { min-height: 0; white-space: nowrap; overflow-x: auto; }
.uc-tpl-editor:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: 1px; }
.uc-tpl-chip { display: inline-block; margin: 0 1px; padding: 0 6px; border: 1px solid transparent; border-radius: 4px;
    background: var(--uc-band); color: var(--uc-accent-text); font-size: 13px; font-weight: 600; line-height: 1.5; white-space: nowrap; user-select: all; }
.uc-tpl-chip.is-armed { border-color: var(--p-danger-text); }
@media (max-width: 760px) {
    .uc-tpl-cols { grid-template-columns: minmax(0, 1fr); }
    .uc-tpl-preview { height: 520px; }
}

/* ---------------------------------------------------------------------------
   QUESTIONS FOR REGISTRANTS (3.106.2, redrawn 3.106.3).

   THE EDITOR IS ITS OWN CARD, a .uc-bento-card under the Location card, so
   the column's 16px gap and the card's 18px padding are the standard ones.
   Each question is a sub-card on the page tint --p-bg with the hairline
   --p-border and the 8px radius: an item in the section, not another
   section. Its top row is the question box taking the width, then Required,
   In person only and the remove button; under about 540px of row the box takes the
   whole line and the rest wraps under it. Answer style is the segmented
   control. Options are a tight list of grip, box, tick and remove.

   EVERY ICON IS A BUTTON with a 32px target, --p-muted on the tint (5.18:1,
   over the 3:1 a glyph needs), --p-text on hover over --p-border, and the
   accent ring on focus. "+ Add option" is a link-coloured text button lined
   up with the option boxes (32px grip plus the 8px gap); "+ Add question" is
   an outlined button in the accent, at its own width.
   ------------------------------------------------------------------------ */
.uc-questions-card .uc-questions-hint { margin: 0 0 12px; }
.uc-questions .uc-q-list { list-style: none; margin: 0 0 12px; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.uc-questions .uc-q { display: flex; flex-direction: column; gap: 10px; padding: 12px;
    background: var(--p-bg); border: 1px solid var(--p-border); border-radius: 8px; }
.uc-questions .uc-q-top { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; }
.uc-questions .uc-q-text { flex: 1 1 260px; min-width: 0; margin: 0; }
.uc-questions .uc-q-text input { width: 100%; }
.uc-questions .uc-q-ticks { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; }
.uc-questions .uc-q-ticks .uc-check,
.uc-questions .uc-q-option .uc-check { margin: 0; }
.uc-questions .uc-q-style { align-self: flex-start; }
.uc-questions .uc-q-options { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.uc-questions .uc-q-option { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.uc-questions .uc-q-option > input[type="text"] { flex: 1 1 180px; min-width: 0; }
/* The tick and the remove travel together: beside the box on a wide row,
   and on a narrow one wrapped under it at the right-hand end. */
.uc-questions .uc-q-option-tail { display: inline-flex; align-items: center; gap: 8px; margin-left: auto; }
.uc-questions .uc-q-option.is-dragging { background: var(--p-border); }
.uc-questions .uc-icon-btn {
    display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
    width: 32px; height: 32px; padding: 0; margin: 0;
    border: 0; border-radius: 6px; background-color: transparent; color: var(--p-muted); cursor: pointer;
}
.uc-questions .uc-icon-btn:hover { background-color: var(--p-border); color: var(--p-text); }
.uc-questions .uc-icon-btn:focus-visible,
.uc-questions .uc-o-add:focus-visible,
.uc-questions .uc-q-add:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: 2px; }
.uc-questions .uc-q-grip { cursor: grab; }
.uc-questions .uc-o-add {
    align-self: flex-start; margin: 0 0 0 40px; padding: 2px 0;
    border: 0; background-color: transparent; cursor: pointer;
    font-family: inherit; font-size: 13px; font-weight: 600; line-height: 1.4; color: var(--uc-accent-text);
}
.uc-questions .uc-o-add:hover { text-decoration: underline; }
.uc-questions .uc-q-add {
    align-self: flex-start; padding: 8px 16px;
    border: 1px solid var(--uc-accent-text); border-radius: 8px; background-color: transparent; cursor: pointer;
    font-family: inherit; font-size: 13px; font-weight: 600; line-height: 1.4; color: var(--uc-accent-text);
}
.uc-questions .uc-q-add:hover { background-color: var(--uc-band); }
.uc-questions { display: flex; flex-direction: column; }
/* .uc-check and the buttons set display, which beats the user agent's [hidden]. */
.uc-questions [data-uc-q-inperson][hidden],
.uc-questions [data-uc-q-add][hidden] { display: none; }

/* THE TOTALS STRIP, above the registrations list: one line per question, body
   type, the question in the same ink as the counts line above it. */
.uc-q-totals { list-style: none; margin: -8px 0 16px; padding: 0; font-size: 14px; font-weight: 400; line-height: 1.5; color: var(--sfaf-darkgray); }
.uc-q-totals li + li { margin-top: 2px; }

/* DETAILS: a quiet action in the row's last cell, and the answers under it. */
.uc-table [data-uc-rsvp-details] {
    background: none; border: 0; padding: 0; margin-left: 12px;
    font-size: 13px; font-weight: 600; color: var(--uc-accent-text); cursor: pointer;
}
.uc-table [data-uc-rsvp-details]:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: 2px; }
.uc-table .uc-rsvp-details[hidden] { display: none; }
.uc-table .uc-rsvp-details td { background: var(--p-bg); }
.uc-rsvp-answers { margin: 0; font-size: 14px; font-weight: 400; line-height: 1.5; color: var(--sfaf-darkgray); }
.uc-rsvp-answers dt { font-size: 13px; font-weight: 600; margin-top: 8px; }
.uc-rsvp-answers dt:first-child { margin-top: 0; }
.uc-rsvp-answers dd { margin: 0; }
.uc-rsvp-answer-more { display: block; font-size: 12px; color: var(--p-muted); }

/* ---------------------------------------------------------------------------
   THE EVENT EDITOR'S TOUR (3.108.0)

   "Take the tour" is a text link in the accent, 14px/600, beside Back. The
   tour itself is a shield, a ring and a panel appended to <body>: the ring is
   the focus ring's colour, 3px, 6px outside the card, and its box-shadow is
   the dim. The panel is the standard card on --p-panel with the confirm
   dialog's shadow, 320px wide or the window less 24px.

   EVERY SELECTOR HERE IS TWO CLASSES, because `.uc-portal h2` and
   `.uc-portal p` are a class and a type and outrank one class.
   ------------------------------------------------------------------------ */
.uc-page-head .uc-tour-link {
    margin: 0 8px 0 0; padding: 4px 0; border: 0; background-color: transparent; cursor: pointer;
    font-family: inherit; font-size: 14px; font-weight: 600; line-height: 1.4; color: var(--uc-accent-text);
    text-decoration: underline; text-underline-offset: 3px;
}
.uc-page-head .uc-tour-link:hover { text-decoration-thickness: 2px; }
.uc-page-head .uc-tour-link:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: 2px; border-radius: 4px; }

.uc-tour .uc-tour-shield { position: fixed; inset: 0; z-index: 100000; }
.uc-tour .uc-tour-ring {
    position: fixed; z-index: 100001; box-sizing: border-box; pointer-events: none;
    border: 3px solid var(--uc-accent-text); border-radius: 16px;
    box-shadow: 0 0 0 9999px var(--p-scrim);
}
.uc-tour .uc-tour-panel {
    position: fixed; z-index: 100002; box-sizing: border-box; width: min(320px, calc(100vw - 24px));
    padding: 16px; border: 1px solid var(--p-border); border-radius: 12px;
    background: var(--p-panel); color: var(--p-text); box-shadow: var(--p-shadow-raised);
}
.uc-tour .uc-tour-panel:focus { outline: none; }
.uc-tour .uc-tour-count { margin: 0 0 4px; font-size: 12px; font-weight: 400; line-height: 1.4; color: var(--p-muted); }
.uc-tour .uc-tour-name { margin: 0 0 8px; font-size: 16px; font-weight: 600; line-height: 1.3; color: var(--p-text); }
.uc-tour .uc-tour-text { margin: 0 0 16px; font-size: 14px; font-weight: 400; line-height: 1.5; color: var(--p-text); }
.uc-tour .uc-tour-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.uc-tour .uc-tour-done { margin-left: auto; }
.uc-tour .uc-btn[disabled] { cursor: default; }

/* ---------------------------------------------------------------------------
   THE FEATURED IMAGE BLOCK, EVENT EDITOR (3.108.1)

   The preview on top, at most 280px and 16:9, with two things on it: the pill
   in its top-left corner saying where the picture comes from, and Remove in
   its top-right corner while the picture is the event's own. "Choose a
   picture" under it names the picture and draws no second thumbnail, because
   the preview above is that picture. With no picture at all the preview is an
   empty 16:9 tile on --p-bg.

   The pill is the Helper step, 12px/400 --p-text on --p-panel (11.80:1);
   Remove is a small control, 13px/600 --p-text on --p-panel with the control
   boundary --p-border-strong (3.33:1) and the accent focus ring.
   ------------------------------------------------------------------------ */
.uc-image-block .uc-image-preview { position: relative; max-width: 280px; margin: 0 0 10px; }
.uc-image-block .uc-image-preview img { max-width: 100%; }
.uc-image-block .uc-image-preview-empty {
    aspect-ratio: 16 / 9; box-sizing: border-box;
    background: var(--p-bg); border: 1px solid var(--p-border); border-radius: 10px;
}
.uc-image-block .uc-image-pill {
    position: absolute; top: 8px; left: 8px; padding: 2px 8px;
    border: 1px solid var(--p-border); border-radius: 99px; background: var(--p-panel);
    font-size: 12px; font-weight: 400; line-height: 1.4; color: var(--p-text);
}
.uc-image-block .uc-image-remove {
    position: absolute; top: 8px; right: 8px; padding: 3px 10px;
    border: 1px solid var(--p-border-strong); border-radius: 8px; background: var(--p-panel);
    font-family: inherit; font-size: 13px; font-weight: 600; line-height: 1.4; color: var(--p-text); cursor: pointer;
}
.uc-image-block .uc-image-remove:hover { background: var(--p-bg); }
.uc-image-block .uc-image-remove:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: 2px; }
.uc-image-block .uc-image-picker { margin: 0; }
.uc-image-block .uc-image-current-thumb { display: none; }

/* ---------------------------------------------------------------------------
   THE EDITORS' FAQs, FOLDED (3.108.1)

   A folded row keeps the FAQ row's ground (--p-bg, --p-border, 10px radius)
   with tighter padding: the head is the question in Body type, 14px/400
   --p-text ("New question" in --p-muted), then Edit, a text button in the
   accent at 13px/600, then the remove icon, the 32px icon button the
   registration questions use. Open, the question and answer sit under the
   head 10px apart.
   ------------------------------------------------------------------------ */
.uc-faq-row.uc-faq-fold { gap: 0; padding: 6px 6px 6px 14px; }
.uc-faq-row.uc-faq-fold.is-open { padding-bottom: 14px; padding-right: 14px; }
.uc-faq-fold .uc-faq-head { display: flex; align-items: center; gap: 8px; min-height: 32px; }
.uc-faq-fold .uc-faq-head-q {
    flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-size: 14px; font-weight: 400; line-height: 1.4; color: var(--p-text);
}
.uc-faq-fold .uc-faq-head-q.uc-faq-head-new { color: var(--p-muted); }
.uc-faq-fold .uc-faq-toggle {
    flex: 0 0 auto; padding: 6px 4px; border: 0; background-color: transparent; cursor: pointer;
    font-family: inherit; font-size: 13px; font-weight: 600; line-height: 1.4; color: var(--uc-accent-text);
}
.uc-faq-fold .uc-faq-toggle:hover { text-decoration: underline; }
.uc-faq-fold .uc-faq-toggle:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: 2px; border-radius: 4px; }
.uc-faq-fold .uc-faq-x {
    flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; padding: 0; border: 0; border-radius: 8px;
    background-color: transparent; color: var(--p-muted); cursor: pointer;
}
.uc-faq-fold .uc-faq-x:hover { background-color: var(--p-border); color: var(--p-text); border-color: transparent; }
.uc-faq-fold .uc-faq-x:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: 2px; }
.uc-faq-fold .uc-faq-body { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; }
.uc-faq-fold .uc-faq-body[hidden] { display: none; }

/* ---------------------------------------------------------------------------
   ONE INLINE NOTICE ON THE EDITORS (3.108.1)

   What a button just did, said under it: the series prefill's "Filled in 7
   things...", the FAQ set's "Added 4 questions...", and the description's
   "Added to the description." One component: --p-ok-ink on --p-ok-tint
   (6.08:1), 10px 14px, 8px radius, 10px above, Field label type 13px/600.
   A failure in the same place takes the Red family's pair instead.
   ------------------------------------------------------------------------ */
.uc-notice {
    margin: 10px 0 0; padding: 10px 14px; border-radius: 8px;
    background: var(--p-ok-tint); color: var(--p-ok-ink);
    font-size: 13px; font-weight: 600; line-height: 1.45;
}
.uc-notice.uc-notice-error { background: var(--p-error-tint); color: var(--p-error-ink); }
.uc-notice[hidden] { display: none; }

/* ---------------------------------------------------------------------------
   WHO CAN FIND THIS EVENT (3.110.0)

   Its own card under Display. Once the event is saved and private, its link
   sits in a read-only box with Copy beside it: the box takes the row, the
   button keeps its width, and below 420px of card the button takes its own
   line under the box. The box is the standard text field, read-only, on the
   page tint so it reads as a value rather than something to type in.
   ------------------------------------------------------------------------ */
.uc-private-field .uc-private-link-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 4px; }
.uc-private-field .uc-private-link-box { flex: 1 1 200px; min-width: 0; background-color: var(--p-bg); color: var(--p-text); }
.uc-private-field .uc-private-link-row .uc-btn { flex: 0 0 auto; }

/* ---------------------------------------------------------------------------
   THE REGISTRATION AGREEMENT IN THE EDITOR (3.110.0)

   A section of the Registration card, as the questions are: the 16px subhead
   with one --p-border hairline above it, the tick, and the text box under it
   while the tick is on.
   ------------------------------------------------------------------------ */
.uc-registration-card .uc-agreement { display: flex; flex-direction: column; gap: 10px; margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--p-border); }
.uc-registration-card .uc-agreement-title { margin: 0; font-size: 16px; font-weight: 600; line-height: 1.3; color: var(--p-text); }
.uc-registration-card .uc-agreement-text[hidden] { display: none; }

/* ---------------------------------------------------------------------------
   ONE EVENT'S RSVP LIST: COUNTS, CHECK-IN, FIND, EMAIL (3.110.0)

   The counts are one strip, Body type, the figures bold. Under it the check-in
   choice, the segmented control drawn with buttons because each press saves
   it; "Enter a count" adds its one number box and Save. Then Find by name,
   then Email registrants, the same full-width row as the Notifications card's.
   A row's Check in is the standard small button; checked in, it wears the
   accent: --uc-accent-text edge and ink on --uc-band. "Texts" is a small
   neutral mark after the phone number.
   ------------------------------------------------------------------------ */
.uc-rsvp-counts { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; }
.uc-checkin-bar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px 20px; margin: 0 0 16px; }
.uc-checkin-bar .uc-checkin-mode { margin: 0; }
.uc-checkin-bar .uc-seg-opt-btn {
    display: block; margin: 0; padding: 8px 16px; border: 0; border-left: 1px solid var(--p-border); border-radius: 0;
    background: var(--p-control-face); color: var(--p-text); font-family: inherit; font-size: 13px; font-weight: 600; line-height: 1.4; cursor: pointer;
}
.uc-checkin-bar .uc-seg-opt-btn:first-child { border-left: 0; }
.uc-checkin-bar .uc-seg-opt-btn:hover { background: var(--uc-band); }
.uc-checkin-bar .uc-seg-opt-btn[aria-pressed="true"] { background: var(--uc-accent-text); color: var(--p-panel); }
.uc-checkin-bar .uc-seg-opt-btn:focus-visible { outline: 2px solid var(--uc-accent-text); outline-offset: -2px; }
.uc-checkin-bar .uc-attendance-form { display: flex; align-items: flex-end; gap: 8px; margin: 0; }
.uc-checkin-bar .uc-attendance-field { margin: 0; }
.uc-checkin-bar .uc-attendance-field input { width: 120px; }
/* The Search button is the no-script half of the one search box; with a script
   the box filters as you type and the button is hidden (3.110.1). .uc-btn sets
   display, which would otherwise beat [hidden]. */
.uc-filters-bar .uc-btn[hidden] { display: none; }
.uc-registrant-mail { margin: 0 0 16px; }
.uc-registrant-mail .uc-registrant-mail-form { display: flex; flex-direction: column; gap: 12px; }
.uc-registrant-mail .uc-rm-preview-frame { display: block; width: 100%; height: 640px; border: 1px solid var(--p-border); border-radius: 8px; background: var(--p-panel); }
.uc-registrant-mail .uc-rm-preview-subject { margin: 0; }
.uc-registrant-mail .uc-rm-preview[hidden] { display: none; }
/* Email registrants (3.110.2): the two ticks side by side; Send in the
   Publish green, its envelope sliding in from the label's left on hover and
   focus, and appearing without moving when motion is reduced. */
.uc-registrant-mail .uc-rm-ticks { display: flex; flex-wrap: wrap; gap: 0 20px; }
.uc-portal .uc-rm-send { display: inline-flex; align-items: center; justify-content: center; }
.uc-rm-send .uc-rm-send-icon { display: inline-flex; width: 0; margin-right: 0; overflow: hidden; opacity: 0; transform: translateX(-8px);
    transition: width 150ms ease, margin-right 150ms ease, opacity 150ms ease, transform 150ms ease; }
.uc-rm-send:hover .uc-rm-send-icon,
.uc-rm-send:focus-visible .uc-rm-send-icon { width: 16px; margin-right: 8px; opacity: 1; transform: translateX(0); }
@media (prefers-reduced-motion: reduce) {
    .uc-rm-send .uc-rm-send-icon { transition: none; transform: none; }
}
.uc-registrant-mail .uc-rm-format { min-width: 40px; }
.uc-rsvp-table .uc-checkin-form { display: inline; margin: 0; }
.uc-rsvp-table .uc-checkin-btn[aria-pressed="true"] { border-color: var(--uc-accent-text); color: var(--uc-accent-text); background: var(--uc-band); }
.uc-texts-mark {
    display: inline-block; margin-left: 6px; padding: 0 6px; border: 1px solid var(--p-border); border-radius: 99px;
    font-size: 12px; font-weight: 400; line-height: 1.5; color: var(--p-muted); background: var(--p-bg);
}
.uc-rsvp-table tr[hidden] { display: none; }

/* ---------------------------------------------------------------------------
   THE RSVP LIST ON A PHONE (3.110.0)

   One column. A row is the name and its buttons on one line, the name taking
   what the buttons leave, then email, phone and status on a small line under
   it. Every button is at least 44px tall. The header row goes; Updates and
   Registered go, being the desk's columns.
   ------------------------------------------------------------------------ */
@media (max-width: 600px) {
    .uc-rsvp-table thead { display: none; }
    .uc-rsvp-table, .uc-rsvp-table tbody { display: block; width: 100%; }
    .uc-rsvp-table tr[data-uc-rsvp-row] {
        display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px;
        padding: 12px 0; border-bottom: 1px solid var(--p-border);
    }
    .uc-rsvp-table tr[data-uc-rsvp-row] > td { display: block; padding: 0; border: 0; min-width: 0; }
    .uc-rsvp-table tr[data-uc-rsvp-row] > td:nth-child(1) { order: 1; font-size: 16px; }
    .uc-rsvp-table tr[data-uc-rsvp-row] > td:nth-child(2) { order: 2; flex: 1 1 0; font-size: 16px; font-weight: 600; }
    /* The actions cell lets go of its three: Check in stays on the name's line,
       Details and Remove go to a line of their own at the bottom. */
    .uc-rsvp-table tr[data-uc-rsvp-row] > td:nth-child(8) { display: contents; }
    .uc-rsvp-table tr[data-uc-rsvp-row] .uc-rsvp-actions > form,
    .uc-rsvp-table tr[data-uc-rsvp-row] .uc-rsvp-actions > button { order: 5; margin: 0; }
    .uc-rsvp-table tr[data-uc-rsvp-row] .uc-rsvp-actions > .uc-checkin-form { order: 3; display: block; }
    .uc-rsvp-table tr[data-uc-rsvp-row] > td:nth-child(2) { overflow-wrap: anywhere; }
    .uc-rsvp-table tr[data-uc-rsvp-row] > td:nth-child(3),
    .uc-rsvp-table tr[data-uc-rsvp-row] > td:nth-child(4),
    .uc-rsvp-table tr[data-uc-rsvp-row] > td:nth-child(6) { order: 4; font-size: 13px; color: var(--p-muted); overflow-wrap: anywhere; }
    .uc-rsvp-table tr[data-uc-rsvp-row] > td:nth-child(3) { flex: 1 1 100%; }
    .uc-rsvp-table tr[data-uc-rsvp-row] > td:nth-child(5),
    .uc-rsvp-table tr[data-uc-rsvp-row] > td:nth-child(7) { display: none; }
    .uc-rsvp-table td:nth-child(2) .uc-muted { display: none; }
    /* The line under the name breaks before the buttons at the bottom. */
    .uc-rsvp-table tr[data-uc-rsvp-row] > td:nth-child(6) { flex: 1 1 100%; }
    /* The waitlist, the same way: position and name, then email and status,
       then Confirm and Remove. Joined goes. */
    .uc-waitlist .uc-table thead { display: none; }
    .uc-waitlist .uc-table, .uc-waitlist .uc-table tbody { display: block; width: 100%; }
    .uc-waitlist .uc-table tr {
        display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px;
        padding: 12px 0; border-bottom: 1px solid var(--p-border);
    }
    .uc-waitlist .uc-table tr > td { display: block; padding: 0; border: 0; min-width: 0; }
    .uc-waitlist .uc-table tr > td:nth-child(1) { font-size: 16px; }
    .uc-waitlist .uc-table tr > td:nth-child(2) { flex: 1 1 0; font-size: 16px; overflow-wrap: anywhere; }
    .uc-waitlist .uc-table tr > td:nth-child(3) { flex: 1 1 100%; font-size: 13px; color: var(--p-muted); overflow-wrap: anywhere; }
    .uc-waitlist .uc-table tr > td:nth-child(4) { display: none; }
    .uc-waitlist .uc-table tr > td:nth-child(6) { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; flex: 1 1 100%; }
    .uc-waitlist .uc-table .uc-rsvp-actions form { margin: 0; }
    .uc-waitlist .uc-table .uc-rsvp-actions button { min-height: 44px; }
    .uc-rsvp-table .uc-rsvp-actions .uc-btn,
    .uc-rsvp-table .uc-rsvp-actions button { min-height: 44px; display: inline-flex; align-items: center; }
    .uc-rsvp-table tr.uc-rsvp-details { display: block; }
    .uc-rsvp-table tr.uc-rsvp-details[hidden] { display: none; }
    .uc-rsvp-table tr.uc-rsvp-details > td { display: block; padding: 8px 0 12px; }
    .uc-checkin-bar .uc-seg-opt-btn { min-height: 44px; }
    .uc-checkin-bar .uc-attendance-form .uc-btn { min-height: 44px; }
}

/* ---------------------------------------------------------------------------
   A FINGER'S WORTH OF TARGET (3.110.0)

   Everything a thumb presses in caladmin is at least 44px tall on a phone,
   and on any screen driven by touch: `pointer: coarse` for the finger, as the
   calendar decides it, and 600px for a narrow window, which is what the
   phone pass measures. Fields, selects, buttons, tick-box rows and the
   summary that opens the image picker take min-height, which wins over any
   height they declare. The 16px "?" keeps its look and gains a 44px hit
   area round it, drawn by ::after. A tick's label grows by padding, not by
   centring, so its box stays on the first line. Two classes or more throughout, so the
   button rules above, at one class plus one, cannot take it back.
   ------------------------------------------------------------------------ */
@media (pointer: coarse), (max-width: 600px) {
    .uc-portal input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="file"]):not([type="range"]):not([type="color"]),
    .uc-portal select { min-height: 44px; }
    .uc-portal .uc-btn, .uc-portal .uc-picker-tab, .uc-portal .uc-tpl-token,
    .uc-portal .uc-link-danger, .uc-portal .uc-link-btn, .uc-portal .uc-outline-btn,
    .uc-page-head .uc-tour-link,
    .uc-questions .uc-icon-btn, .uc-questions .uc-o-add, .uc-questions .uc-q-add { min-height: 44px; }
    .uc-questions .uc-icon-btn { min-width: 44px; }
    /* + Add option lines up with the option boxes, which the 44px handle moved 12px right. */
    .uc-questions .uc-o-add { margin-left: 52px; }
    /* Required, In person only and the 44px remove stay on one line in 390px. */
    .uc-questions .uc-q-ticks { gap: 0 8px; }
    .uc-portal summary.uc-outline-btn { display: inline-flex; align-items: center; }
    /* The box stays on the label's first line (checkbox-align-test); 11px above
       and below a 22px line make the 44px, and a longer label just grows. */
    .uc-portal .uc-check, .uc-portal .uc-radio-row { box-sizing: border-box; min-height: 44px; padding-top: 11px; padding-bottom: 11px; margin-bottom: 0; }
    .uc-portal .uc-seg-opt span { display: flex; align-items: center; min-height: 44px; }
    .uc-portal .uc-help-btn { position: relative; }
    .uc-portal .uc-help-btn::after { content: ""; position: absolute; top: -14px; right: -14px; bottom: -14px; left: -14px; }
}

/* ---------------------------------------------------------------------------
   THE USERS TABLE (3.110.2)

   One row a person. The search box above it is the field's width; the team
   pills are the standard pill at Helper size. Contributor categories opens as
   a row under its person. Below 600px a row is two lines: who they are, then
   the controls, wrapping rather than cutting anything off.
   ------------------------------------------------------------------------ */
.uc-users-search { display: block; max-width: 420px; margin: 0 0 16px; }
.uc-users-search input { width: 100%; }
.uc-users-table td { vertical-align: middle; }
/* The cells stay table cells: their contents stack, not the cells. */
.uc-users-table .uc-user-id > * { display: block; }
.uc-users-table .uc-user-id > [hidden] { display: none; }
.uc-users-table .uc-user-id .uc-muted { font-size: 12px; overflow-wrap: anywhere; }
.uc-users-table .uc-user-cats-toggle { margin-top: 4px; font-size: 12px; text-align: left; }
.uc-users-table .uc-user-teams .uc-team-pill { display: inline-block; margin: 2px 4px 2px 0; }
.uc-users-table .uc-team-pill { font-size: 12px; font-weight: 400; color: var(--p-text); background: var(--p-bg); border: 1px solid var(--p-border); }
/* A table cell, not the old row's flex box (3.110.2). */
.uc-users-table td.uc-user-actions { display: table-cell; white-space: nowrap; text-align: right; }
.uc-users-table td.uc-user-actions > * + * { margin-left: 12px; }
.uc-users-table .uc-user-actions .uc-btn[disabled] { opacity: .5; cursor: default; }
.uc-users-table .uc-user-cats-row > td { background: var(--p-bg); }
.uc-users-table tr[hidden] { display: none; }
@media (max-width: 600px) {
    .uc-users-table thead { display: none; }
    .uc-users-table, .uc-users-table tbody { display: block; width: 100%; }
    .uc-users-table tr.uc-user-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding: 12px 0; border-bottom: 1px solid var(--p-border); }
    .uc-users-table tr.uc-user-row > td { display: block; padding: 0; border: 0; min-width: 0; }
    .uc-users-table tr.uc-user-row > td.uc-user-id { flex: 1 1 100%; }
    .uc-users-table tr.uc-user-row > td.uc-user-teams { flex: 1 1 100%; }
    .uc-users-table tr.uc-user-row > td.uc-user-actions { margin-left: auto; }
    .uc-users-table tr.uc-user-cats-row, .uc-users-table tr.uc-user-reassign-row { display: block; }
    .uc-users-table tr.uc-user-cats-row[hidden] { display: none; }
    .uc-users-table tr.uc-user-cats-row > td, .uc-users-table tr.uc-user-reassign-row > td { display: block; padding: 8px 0 12px; }
    .uc-users-search { max-width: none; }
}
/* ---------------------------------------------------------------------------
   THE REST OF CALADMIN ON A PHONE (3.110.2)

   Tables marked .uc-table-cards are one card a row below 600px: no heading
   row, each value under its column's name (data-label, from portal.js), the
   first cell as the card's title. Every summary, the events list's row
   icons, the pending queue's text actions, the template picker and the
   sign-in tick reach 44px, as the 3.110.0 block does for the rest.
   ------------------------------------------------------------------------ */
@media (max-width: 600px) {
    .uc-portal .uc-table-cards thead { display: none; }
    .uc-portal .uc-table-cards, .uc-portal .uc-table-cards tbody { display: block; width: 100%; }
    .uc-portal .uc-table-cards tr { display: block; padding: 12px 0; border-bottom: 1px solid var(--p-border); }
    .uc-portal .uc-table-cards tr > td { display: flex; gap: 8px; align-items: baseline; padding: 2px 0; border: 0; min-width: 0; overflow-wrap: anywhere; text-align: left; }
    .uc-portal .uc-table-cards tr > td[data-label]::before { content: attr(data-label); flex: 0 0 96px; font-size: 12px; font-weight: 400; color: var(--p-muted); }
    .uc-portal .uc-table-cards tr > td:first-child { font-size: 16px; }
    .uc-portal .uc-table-cards tr > td:first-child::before { content: none; }
    .uc-portal .uc-table-cards tr > td:empty { display: none; }
}
@media (pointer: coarse), (max-width: 600px) {
    .uc-portal summary { min-height: 44px; box-sizing: border-box; }
    .uc-portal .uc-icon-action { min-width: 44px; min-height: 44px; }
    .uc-portal .uc-link-ok, .uc-portal .uc-action-link, .uc-portal .uc-tpl-pick { min-height: 44px; }
    .uc-portal .uc-tick-all, .uc-portal .uc-login-remember { min-height: 44px; display: inline-flex; }
}
/* ---------------------------------------------------------------------------
   PICTURES IN THREE PLACES, THE UPLOAD, THE APPROVAL QUESTION, SET TEAM (3.110.3)
   --------------------------------------------------------------------------- */
/* The editor's picker tools: search and the active-only tick on one row, there
   only once the script that drives them is (the search box's own rule). */
.uc-image-tools { display: none; }
.uc-image-picker-live .uc-image-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; margin-bottom: 8px; }
.uc-image-tools .uc-picker-filter { flex: 1 1 220px; margin: 0; }
.uc-image-picker-live .uc-image-tools .uc-image-search { display: block; }
.uc-portal .uc-image-active-only { margin: 0; font-size: 13px; line-height: 1.4; }
/* A group's name inside the list: the Field label step, 13/600, in --p-muted,
   a hairline above, so the two groups read as two without a box each. */
.uc-image-group-head { margin: 8px 0 2px; padding: 10px 0 0; border-top: 1px solid var(--p-border);
    font-size: 13px; font-weight: 600; line-height: 1.45; color: var(--p-muted); }
.uc-image-group-none { margin: 2px 0 6px; font-size: 13px; line-height: 1.45; }
.uc-image-group-none[hidden] { display: none; }

/* "+ Upload a picture for this event": the outlined control, its file input
   inside it and hidden, the focus ring on the label while the input has it. */
.uc-portal .uc-image-upload { position: relative; margin-top: 10px; }
.uc-portal .uc-image-upload:focus-within { outline: 2px solid var(--uc-accent-text); outline-offset: 2px; }
.uc-portal .uc-image-upload-error[hidden] { display: none; }

/* The approval dialog's picture question, a section of the panel under a
   hairline: the picture at 160px, two choices, the series list under its own. */
.uc-approve-picture { margin: 12px 0 0; padding: 12px 0 0; border: 0; border-top: 1px solid var(--p-border); min-width: 0; }
.uc-approve-picture > legend { float: left; width: 100%; padding: 0; margin: 0 0 8px; }
.uc-approve-picture-thumb { display: block; clear: both; width: 160px; max-width: 100%; height: auto; aspect-ratio: 16 / 9;
    object-fit: cover; border-radius: 6px; border: 1px solid var(--p-border); margin: 0 0 10px; }
.uc-approve-picture-choices { clear: both; }
.uc-portal .uc-approve-picture-series { margin: 0 0 8px 24px; max-width: 280px; }

/* The Images screen: search and the active tick join the filter row; a card
   names its place in a pill, and "Active" in the success pair (6.08:1). */
.uc-media-filters { align-items: center; }
.uc-portal .uc-media-search { flex: 1 1 220px; max-width: 320px; margin: 0; }
.uc-portal .uc-media-active { margin: 0; }
.uc-media-place { display: flex; flex-wrap: wrap; gap: 5px; margin: 0; }
.uc-media-pill { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 999px;
    border: 1px solid var(--p-border); background: var(--p-bg); font-size: 12px; line-height: 1.4; color: var(--p-text); }
.uc-media-pill-active { border-color: var(--p-ok-tint); background: var(--p-ok-tint); color: var(--p-ok-ink); }
.uc-media-with { margin: 0; font-size: 13px; line-height: 1.45; }
.uc-media-item[hidden] { display: none; }

/* Set team on the events list: a row of its own under the other two, its
   choices on the page tint when open. */
.uc-bulk-team { flex: 1 1 100%; }
.uc-bulk-team-body { margin-top: 10px; padding: 12px 14px; border-radius: 10px; background: var(--p-bg); }
.uc-bulk-team-body .uc-access-people { display: flex; flex-wrap: wrap; gap: 6px 16px; }

@media (pointer: coarse), (max-width: 600px) {
    .uc-portal .uc-image-upload { min-height: 44px; }
    .uc-portal .uc-image-active-only, .uc-portal .uc-media-active { min-height: 44px; display: inline-flex; }
    /* An Images card's tick (24px) and a tag's x (18px) reach 44px with the
       hit area the "?" buttons use, so the card does not change size. */
    .uc-portal .uc-media-tick::after { content: ""; position: absolute; top: -10px; right: -10px; bottom: -10px; left: -10px; }
    .uc-portal .uc-media-tag-off { position: relative; }
    .uc-portal .uc-media-tag-off::after { content: ""; position: absolute; top: -13px; right: -13px; bottom: -13px; left: -13px; }
    /* The picture's Remove (26px) and a chip's x (16px) on the editor, the same way. */
    .uc-portal .uc-image-block .uc-image-remove::after { content: ""; position: absolute; top: -9px; right: -9px; bottom: -9px; left: -9px; }
    .uc-portal .uc-chip-remove { position: relative; }
    .uc-portal .uc-chip-remove::after { content: ""; position: absolute; top: -14px; right: -6px; bottom: -14px; left: -6px; }
}

/* ---------------------------------------------------------------------------
   RESTORE WHAT YOU WERE TYPING (3.110.5)

   caladmin-session.js puts one line at the top of a screen that has a draft
   in this browser: the .uc-flash-attention banner, its words, then Restore
   and Discard together at the right, wrapping under the words when they do
   not fit. After a restore, the plain .uc-flash says it is back. Nothing new
   in colour: both are the page-level banners caladmin already has.
   ------------------------------------------------------------------------ */
.uc-draft-prompt { justify-content: space-between; }
.uc-draft-prompt-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* Registrations taken elsewhere (3.111.0): the Notifications card is one line,
   and its fields wait hidden until registrations come back here. */
.uc-portal .uc-notify-away[hidden],
.uc-portal .uc-notify-fields[hidden] { display: none; }
