/* Seahorse Admin - Main Stylesheet */

/* Keep first paint independent of a third-party font stylesheet/connection.
   The same files are already embedded for PDF export, so the UI and exported
   artifacts continue to use identical Quicksand metrics. */
@font-face {
    font-family: 'Quicksand';
    src: url('/fonts/Quicksand-Regular.woff2?v=1') format('woff2');
    font-style: normal;
    font-weight: 400 500;
    font-display: swap;
}

@font-face {
    font-family: 'Quicksand';
    src: url('/fonts/Quicksand-Bold.woff2?v=1') format('woff2');
    font-style: normal;
    font-weight: 600 700;
    font-display: swap;
}

/* ═══════════════════════════════════════════════════════════════════════════
   Typography scale — ~1.2 ratio modular scale anchored to existing usage.
   Tokens below are the source of truth; bare h1..h6 and body pick them up,
   but existing module-specific overrides (e.g. children h4=23px, educators
   h2=18px) keep winning by CSS specificity. That means this scale fills
   gaps without disrupting what modules already style locally — safe to
   merge upstream, easy to revert from this one file if rejected.
   ═══════════════════════════════════════════════════════════════════════════ */
:root {
    --text-xs:   11px;  /* meta, timestamps, badges */
    --text-sm:   13px;  /* secondary body, table cells */
    --text-base: 15px;  /* default body text */
    --text-lg:   17px;  /* lead paragraphs */
    --text-xl:   20px;  /* h4, small section headers */
    --text-2xl:  24px;  /* h3, module headers */
    --text-3xl:  28px;  /* h2, page titles */
    --text-4xl:  32px;  /* h1, hero titles */
}

/* Global heading defaults. Module-specific rules (e.g. .children-module h4)
   have higher specificity and will override these. */
h1 { font-size: var(--text-4xl); }
h2 { font-size: var(--text-3xl); }
h3 { font-size: var(--text-2xl); }
h4 { font-size: var(--text-xl);  }
h5 { font-size: var(--text-lg);  }
h6 { font-size: var(--text-base); }

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: 'Quicksand', sans-serif;
    font-size: var(--text-base); /* was unset — now 15px by default */
    background: #e0e0e0;
    margin: 0;
    padding: 0;
    height: 100vh;
    color: #444;
    overflow: hidden;
}

.container {
    width: 100vw;
    height: 100vh;
    padding: 15px;
    display: flex;
    flex-direction: column;
    background: #e0e0e0;
    box-sizing: border-box;
}

/* Header Styles */
.header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15px;
    background: rgba(255, 255, 255, 0.3);
    padding: 12px 20px;
    border-radius: 25px;
    box-shadow:
        0 4px 20px rgba(0, 0, 0, 0.12),
        0 1px 4px rgba(0, 0, 0, 0.06),
        inset 1.5px 1.5px 1px 0 rgba(255, 255, 255, 0.45),
        inset -1px -1px 1px 0.5px rgba(255, 255, 255, 0.35);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid rgba(255, 255, 255, 0.3);
    height: 70px;
    position: relative;
    /* Sits above all modal scrims (photos modal-overlay 9999,
       docs-modal-overlay 2000, lightbox 3000) so the flex bar +
       module name + notification icons stay clear/visible while
       the rest of the page (incl. side nav) gets frosted. */
    z-index: 10002;
    overflow: visible;
}

.educator-profile {
    display: flex;
    align-items: center;
    gap: 15px;
}

/* Name badge (not a letter-circle): color matches the dropdown's
   getEducatorColor(id) swatch. Sized for first name + last name stack. */
.profile-avatar {
    position: relative;
    cursor: pointer;
    min-width: 64px;
    max-width: 148px;
    min-height: 48px;
    padding: 7px 12px;
    background: #95a5a6; /* Admin gray until Alpine binds real color */
    border-radius: 14px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    color: white;
    line-height: 1.15;
    text-align: center;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
    box-sizing: border-box;
}
.profile-avatar .avatar-first {
    font-size: 14px;
    font-weight: 700;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.profile-avatar .avatar-last {
    font-size: 11px;
    font-weight: 500;
    opacity: 0.92;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    margin-top: 1px;
}

/* App-shell educator picker: illustrated face instead of the name pill.
   Outer trigger stays overflow:visible so the dropdown is not clipped. */
.profile-avatar--face {
    width: 48px;
    height: 48px;
    min-width: 48px;
    max-width: 48px;
    padding: 0;
    background: transparent;
    border-radius: 50%;
    box-shadow: none;
}
.profile-avatar-face {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    overflow: hidden;
    background: #95a5a6;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
}
.profile-avatar-face .child-face {
    width: 100%;
    height: 100%;
}

.profile-info h2 {
    color: #21304d;
    font-size: 16px;
    margin-bottom: 3px;
}

.profile-info p {
    color: #7f8c8d;
    font-size: 13px;
}

/* ── Flex Bar ──────────────────────────────────────────────────────────────── */
/* Sizing rule: the bar grows to fit its content (module label, step
   title, or notification + buttons) but never exceeds 2/3 of the
   header width. That way long confirmation prompts like "Are you
   sure? Stay / Log Out" don't get clamped to "Ar...", but the bar
   also never eats the profile / notification slots on either side. */
.flex-bar-container {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    justify-content: center;
    padding: 0 20px;
    min-width: 0;
    /* Absolutely positioned + centered on .header's midpoint, so it does
       NOT participate in the profile/notifications flex layout — it has
       no idea how much space either sibling needs. A flat 66.67% cap is
       not enough on its own: because it's CENTERED (not flexed), and the
       two siblings are unequal widths (profile ~186px, notification
       cluster ~285px), the box can drift into the wider (right) sibling
       even when its total width looks "reserved" for both combined.
       For a box centered at the midpoint to clear BOTH sides, its width
       must leave room for the WIDER sibling on both sides (the box only
       "sees" half its own width on each side) — i.e. reserve
       2 × max(profile, notifications), not their sum. Notifications is
       the larger at ~285px; 2×285=570, +80px safety margin = 650px. */
    max-width: min(66.67%, calc(100% - 650px));
    width: clamp(320px, 45vw, 720px);
}

/* Dashboard Operate mode carries the title, three top-level tabs, and the
   Drop-off / Pick-up switch in one row. Give that control-heavy state a
   wider desktop budget so "Attendance Logging" stays readable instead of
   ellipsizing. The existing max-width reservation still keeps the bar clear
   of the profile and header-action clusters; tablet mode overrides this
   later with its device-specific 46vw sizing. */
.flex-bar-container:has(.flex-bar-mode-toggle) {
    width: clamp(720px, 50vw, 840px);
}

/* Belt-and-suspenders for the reservation above: at moderate header
   widths the box can still end up wide enough to visually reach the
   notification icon cluster (nested flex-basis:100% percentages 3
   levels down don't reliably propagate a hard pixel constraint to the
   actual button content, so the reservation above narrows the box but
   doesn't guarantee its content never overflows it). .notifications is
   a later DOM sibling with no z-index, so on overlap it paints ON TOP
   by default — exactly backwards for a state whose entire purpose is
   "click this button". Force the controls above the icons whenever
   they've taken over the bar, so Send/Cancel are ALWAYS the clickable,
   visible layer regardless of how the width math resolves. */
.flex-bar-container:has(.topbar-controls--centered) {
    z-index: 1;
}

/* Spacer not needed — label uses flex:1 to fill all space left of controls */
.flex-bar-spacer-left {
    display: none;
}

/* Label fills all space left of controls; text-align:center centers text within that space */
.label-centered {
    flex: 1;
    text-align: center;
    font-size: 20px;
    font-weight: 700;
    color: white;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

/* Teleported controls fill their container and right-align content */
.children-top-bar-content,
.curriculum-top-bar-content,
.educators-top-bar-controls {
    width: 100%;
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 10px;
}

/* Controls take their natural width — do NOT grow into label's space.
   flex-start (not flex-end): flex-end + an oversized controls cluster
   overflows LEFT and paints over the module title ("Childre|" bug). */
#topBarControls {
    flex: 0 1 auto;
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 10px;
    min-width: 0;
}

/* Anonymous teleported wrappers (children/planner) and classed ones
   (docs/photos) must be allowed to shrink; otherwise they overflow
   leftward over .flex-bar-content. */
#topBarControls > div {
    min-width: 0;
}

/* Photos/docs used to teleport into #flexBar with flex:1 / width:100%.
   Inside #topBarControls those claims crush the title — size to content. */
#topBarControls .gallery-topbar-filters,
#topBarControls .docs-top-bar-content {
    flex: 0 1 auto;
    width: auto;
    max-width: 100%;
    padding: 0;
    justify-content: flex-start;
    gap: 10px;
}

/* When empty, collapse entirely.

   `:empty` alone is not enough: a module that teleports a control and then
   hides it with x-show leaves a real (but `display: none`) child behind, so
   the container stops being `:empty` while still rendering nothing. It then
   contributes a 14px `gap` to the bar's flex row with no visible content —
   an unbalanced trailing slot that pushes the centred title left. Messaging
   sat 14px off centre for exactly this reason. Collapse on VISIBLE children
   instead, matching the predicate used by the .flex-bar-content rules. */
#topBarControls:empty,
#topBarControls:not(:has(> *:not(template):not([style*="display: none"]))) {
    display: none;
}

/* When label is hidden (ASQ modal flow), controls take full width and center.
   flex-wrap is a best-effort safety net for long content; the reliable
   guarantee that these controls stay clickable is the z-index rule on
   .flex-bar-container below (this element sits 3 levels of nested flex
   deep, and that chain does not reliably propagate a width constraint
   down to here — see the .flex-bar-container comment for why the fix
   is paint-order, not width). */
#topBarControls.topbar-controls--centered {
    flex: 1 1 100%;
    justify-content: center;
    flex-wrap: wrap;
}

/* ASQ nav fills full bar and centers the version picker */
.asq-topbar-nav {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
}

/* Top bar select styling (Children, Activity Planner) */
.topbar-select {
    font-size: 13px !important;
    font-family: 'Quicksand', sans-serif !important;
    font-weight: 500 !important;
    color: #444 !important;
    border-radius: 16px !important;
    border: 1px solid rgba(255, 255, 255, 0.4) !important;
    background: rgba(255, 255, 255, 0.85) !important;
    padding: 0 10px !important;
    height: 100% !important;
    outline: none !important;
    cursor: pointer !important;
    text-align: left !important;
    min-width: 80px !important;
}
.topbar-select:hover {
    background: rgba(255, 255, 255, 0.95) !important;
}


.flex-bar-container.curriculum-mode {
    /* width handled by flex */
}

.flex-bar {
    padding: 10px 28px;
    border-radius: 20px;
    font-weight: 700;
    font-size: 20px;
    cursor: default;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    /* Fixed height so the bar is consistent across every module regardless of
       its controls (was content-driven min-height, ranging 47–60px per module).
       Content is centred; tallest control measured is ~38px, well under 56px. */
    box-sizing: border-box;
    height: 56px;
    width: 100%;
    min-width: 350px;
    white-space: nowrap;
    background: linear-gradient(-45deg,
        #4a6b8a, #5583a0, #4f9aa0, #579c94, #6e9280, #a08070,
        #b07a78, #b08465, #a89060, #8fa060, #6ea070, #5fa085,
        #4a9a98, #429aa8, #3ea0a0, #50a090, #6ca085, #8a9c7a,
        #a09480, #b07e85, #b07080, #a56a78, #9c5f6e, #8f5f6a,
        #8a5f78, #7a608a, #60709a, #5082a0, #4a6b8a);
    background-size: 600% 600%;
    animation: gradientFlow 180s ease infinite;
    backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px);
    border: 1px solid rgba(255, 255, 255, 0.35);
    color: white;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
    overflow: visible;
    position: relative;
    isolation: isolate;

    transition: background 0.4s ease, border-color 0.3s ease;
    box-shadow:
        0 4px 10px rgba(0, 0, 0, 0.2),
        inset 0 1px 1px rgba(255, 255, 255, 0.35);
}

.flex-bar::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: linear-gradient(180deg, rgba(0, 0, 0, 0.08) 0%, rgba(0, 0, 0, 0.18) 100%);
    pointer-events: none;
    z-index: 0;
}

/* Left-side back-button slot. Absolutely pinned to the LEFT edge of
   the flex bar so Back never sits flush against the centred title —
   the title stays truly centred; Back is a separate leftmost control.
   Hidden when empty so the bar's padding / layout doesn't shift. */
.flex-bar-back-controls {
    display: inline-flex;
    align-items: center;
    z-index: 2;
    /* NOT absolute, despite how this rule used to read. `.flex-bar > *`
       below sets `position: relative` on every direct child and has the
       same specificity (0,1,0), so it wins on source order — the
       `absolute` never took effect. The `top: 50%` + `translateY(-50%)`
       centring idiom that came with it DID still apply, but relative
       offsets are measured from the in-flow position the bar has already
       centred via `align-items: center`, so together they pushed Back
       1.75px below centre (top 17px, translate −15.25px). Dropping both
       lets the flex container do the centring it was already doing.
       `left` is kept: under `relative` it is the nudge that insets Back
       from the bar's padding edge. */
    position: relative;
    left: 14px;
    margin-right: 0;
    pointer-events: auto;
}
.flex-bar-back-controls:empty {
    display: none;
}

/* Right-side counterpart: forward/next actions pinned to the far end of the
   bar. margin-left:auto is what pins it — it eats the slack the bar's other
   children leave, so Next sits hard right whatever the context content is.
   Contributes nothing when empty, same as the back slot. */
.flex-bar-next-controls {
    display: inline-flex;
    align-items: center;
    z-index: 1;
    position: relative;
    margin-left: auto;
}
.flex-bar-next-controls:empty {
    margin-left: 0;
}
/* :empty above means "no child NODES", which is not the same as "nothing
   drawn": a teleported control hidden by x-show is still a node, so the slot
   went on claiming the bar's free space with nothing visible in it and
   left-shifted its own module's title by 46px while every other module sat
   at 7. The owning template sets data-slot-vacant whenever its x-show is
   false (Alpine drops a bound attribute when the expression is falsy), so
   this reads the author's own intent rather than sniffing a serialised
   inline style. */
.flex-bar-next-controls:has(> [data-slot-vacant]) {
    margin-left: 0;
}

/* ── Children-module billing-detail context bar ─────────────────────
   Hosted in the global flex bar via shared store state
   (see app.js childrenBillingContext + children.js syncBilling-
   Context). Replaces the in-module billing-detail-head actions row
   so the per-child detail view doesn't have a competing horizontal
   strip. Buttons here dispatch CustomEvents back to children.js. */
.flex-bar-billing-context {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    z-index: 1;
    position: relative;
    /* Allow the action group to shrink and the label to truncate
       on narrow viewports rather than overflowing the flex bar. */
    min-width: 0;
    max-width: 100%;
}
.flex-bar-billing-label {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: white;
    font-weight: 700;
    font-size: 16px;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
}
.flex-bar-billing-sep {
    opacity: 0.55;
    font-weight: 400;
}
.flex-bar-billing-actions {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

/* Daily-care context: the inherited module title leads at the left, the
   actions ride the right edge. The child itself is named by the log surface's
   own identity strip below, so the title here is the module.
   Right-aligning also pins Delete: the auto-save pill on its left comes and
   goes with every write, and a left-packed row would have slid the button
   sideways under the educator's finger each time. Anchored to the right edge,
   the pill grows leftward into the gap instead. */
.flex-bar-care-context {
    display: flex;
    width: 100%;
    align-items: center;
    justify-content: space-between;
    /* Roomier than the 8px .flex-bar-content default: this bar packs Back,
       title, Delete and Next Child into one strip, and at tablet tap sizes
       they read as one run-on cluster without it. padding-left holds the title
       off the teleported Back button, which sits outside this box. No
       padding-right: Delete is meant to land beside Next Child, and the bar's
       own 14px gaps either side of the empty #topBarControls already put ~28px
       between them. */
    gap: 18px;
    padding-left: 8px;
}
.flex-bar-care-title {
    /* Match every other flex-bar title (20px, inherited from .flex-bar) —
       .flex-bar-billing-label, which this shares for colour/weight/shadow,
       drops to 16px for the billing bar's longer child-name label. */
    font-size: inherit;
    /* Truncate rather than push the actions off the bar on a narrow tablet. */
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* space-between already pins this group to the right edge; flex-shrink:0 keeps
   Delete at full size when a long title competes for the row. */
.flex-bar-care-context .flex-bar-billing-actions {
    flex-shrink: 0;
    gap: 10px;
}
/* space-between only reaches the right edge if the container actually spans
   the row, and two rules shrink-wrap .flex-bar-content out from under it:
   the `:has(#topBarControls > *)` rule below (the children module teleports
   an inert <template> into that slot even in detail view, so it matches and
   its id makes it win) and the tablet width:auto override. Out-specify both
   by carrying an id in the :has() — the same trick, one level up. Safe to
   span here: in care mode #topBarControls holds nothing visible, which is
   the collision that rule exists to prevent. Offline-queue mode is excluded:
   it collapses the content deliberately to make room for the queue UI. */
.flex-bar:not(.flex-bar--offline-queue):has(#topBarControls) .flex-bar-content:has(.flex-bar-care-context) {
    width: 100%;
    flex: 1 1 auto;
    min-width: 0;
    justify-content: flex-start;
}
/* Dead 14px-gap item between the care actions and Next Child — the centred
   label it spaces is display:none whenever .flex-bar-content renders. */
.flex-bar:has(.flex-bar-care-context) .top-bar-spacer-left {
    display: none;
}

/* Same 8px hold-off for every OTHER detail bar (child read view, child
   billing, educator detail). #topBarBackControls is absolutely positioned,
   so it contributes no width and the title lands flush against the Back
   button — the daily-care bar was the only one holding itself off, which
   made the two read as differently padded when you toggle between them.
   Excludes the care bar so its own padding-left isn't doubled, and matches
   the slot on a VISIBLE child: the children module keeps its Back button
   teleported (x-show'd off) while the grid is up, so `> *` alone would
   shift the grid title too. */
.flex-bar:has(#topBarBackControls > *:not([style*="display: none"]))
    .flex-bar-content:not(:has(.flex-bar-care-context)) {
    padding-left: 8px;
}

/* Payer picker — child-name label as a clickable dropdown trigger
   when the billing surface has >1 contributor on the plan. Slice C
   of the 2026-05-19 consolidation. */
.flex-bar-payer-picker {
    position: relative;
}
.flex-bar-billing-label--clickable {
    font-family: inherit;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: transparent;
    border: none;
    color: white;
    cursor: pointer;
    /* Vertical padding only — horizontal stays 0 so the highlight
       doesn't bleed into the parent .flex-bar-billing-context's gap
       and crowd the Send button on the right. */
    padding: 4px 0;
    border-radius: 10px;
    transition: background 0.15s ease;
    text-shadow: inherit;
    line-height: inherit;
}
.flex-bar-billing-label--clickable:hover,
.flex-bar-billing-label--clickable.is-open {
    /* Background only paints within the button bounds (no negative
       margin); breathing room comes from the parent gap. */
    background: rgba(255, 255, 255, 0.18);
    padding-left: 8px;
    padding-right: 8px;
    margin-left: -4px;
    margin-right: -4px;
}
.flex-bar-billing-label-caret {
    opacity: 0.75;
    transition: transform 0.15s ease;
    margin-left: 2px;
    margin-right: 2px;
}
.flex-bar-billing-label--clickable.is-open .flex-bar-billing-label-caret {
    transform: rotate(180deg);
}
.flex-bar-billing-payer-pill {
    margin-left: 10px;
    padding: 3px 10px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.22);
    border: 1px solid rgba(255, 255, 255, 0.45);
    font-size: 12px;
    font-weight: 600;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.flex-bar-payer-menu {
    position: absolute;
    top: calc(100% + 10px);
    left: -8px;
    z-index: 100;
    min-width: 220px;
    padding: 4px;
    background: rgba(255, 255, 255, 0.97);
    border: 1px solid rgba(33, 48, 77, 0.08);
    border-radius: 14px;
    box-shadow:
        2px 5px 4px rgba(33, 48, 77, 0.08),
        3px 14px 22px rgba(33, 48, 77, 0.14);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
}
.flex-bar-payer-item {
    font-family: inherit;
    width: 100%;
    padding: 8px 12px;
    border-radius: 10px;
    border: none;
    cursor: pointer;
    color: #21304d;
    background: transparent;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    transition: background 0.12s ease;
    text-shadow: none;
}
.flex-bar-payer-item:hover {
    background: rgba(116, 185, 255, 0.14);
}
.flex-bar-payer-item.is-active {
    background: rgba(116, 185, 255, 0.22);
    color: #1e3a5f;
    font-weight: 600;
}
.flex-bar-payer-item-name {
    font-size: 13px;
    text-align: left;
}
.flex-bar-payer-item-share {
    font-size: 11px;
    color: #64748b;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}
.flex-bar-payer-item.is-active .flex-bar-payer-item-share {
    color: #2c5282;
}
.flex-bar-billing-btn {
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    padding: 6px 10px;
    border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, 0.45);
    cursor: pointer;
    color: white;
    background: rgba(255, 255, 255, 0.18);
    display: inline-flex;
    align-items: center;
    gap: 6px;
    backdrop-filter: blur(10px) saturate(1.1);
    -webkit-backdrop-filter: blur(10px) saturate(1.1);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
    transition: background 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}
.flex-bar-billing-btn:hover {
    background: rgba(255, 255, 255, 0.32);
    border-color: rgba(255, 255, 255, 0.65);
    transform: translateY(-1px);
}
.flex-bar-billing-btn--accent {
    /* Tax statement primary slot during the surge window. Filled
       accent so it pops against the muted Edit Plan + overflow. */
    background: rgba(116, 185, 255, 0.45);
    border-color: rgba(186, 215, 244, 0.75);
}
.flex-bar-billing-btn--accent:hover {
    background: rgba(116, 185, 255, 0.6);
    border-color: rgba(186, 215, 244, 0.85);
}
.flex-bar-billing-btn--icon {
    padding: 6px 8px;
}

.flex-bar-billing-overflow {
    position: relative;
}
.flex-bar-billing-btn--icon.is-open {
    background: rgba(255, 255, 255, 0.42);
    border-color: rgba(255, 255, 255, 0.75);
}
.flex-bar-billing-menu {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 10;
    min-width: 180px;
    padding: 4px;
    background: rgba(255, 255, 255, 0.96);
    border: 1px solid rgba(33, 48, 77, 0.08);
    border-radius: 12px;
    box-shadow:
        2px 5px 4px rgba(33, 48, 77, 0.10),
        3px 14px 22px rgba(33, 48, 77, 0.16);
    display: flex;
    flex-direction: column;
    gap: 2px;
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
}
.flex-bar-billing-menu-item {
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    padding: 8px 12px;
    border-radius: 8px;
    border: none;
    cursor: pointer;
    color: #21304d;
    background: transparent;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    text-align: left;
    width: 100%;
    transition: background 0.12s ease;
    text-shadow: none;
}
.flex-bar-billing-menu-item:hover {
    background: rgba(116, 185, 255, 0.14);
}
.flex-bar-billing-menu-item iconify-icon {
    color: #4a5670;
}

.flex-bar > * { position: relative; z-index: 1; }

/* White text treatment for controls teleported into the flex bar */
.flex-bar .asq-nav-label,
.flex-bar .asq-nav-caret { color: white; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); }
.flex-bar .asq-nav-arrow { color: white !important; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); }
.flex-bar input[type="text"] {
    color: white !important;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.flex-bar input[type="text"]::placeholder { color: rgba(255, 255, 255, 0.75); }

/* ═══════════════════════════════════════════════════════════════════════════
   Flex-bar search — gold standard (liquid glass)
   Use the `.docs-search` + `.docs-search-input` pattern for ANY search
   control hoisted into the flex bar, across all modules.
   ═══════════════════════════════════════════════════════════════════════════ */
.flex-bar .docs-search {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 14px;
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.2);
    border: 1px solid rgba(255, 255, 255, 0.35);
    box-shadow:
        inset 1px 1px 0.5px 0 rgba(255, 255, 255, 0.35),
        inset -0.5px -0.5px 0.5px 0.5px rgba(255, 255, 255, 0.15);
    backdrop-filter: blur(8px) saturate(1.2);
    -webkit-backdrop-filter: blur(8px) saturate(1.2);
    transition: background 0.15s ease, border-color 0.15s ease;
}

.flex-bar .docs-search:focus-within {
    background: rgba(255, 255, 255, 0.3);
    border-color: rgba(255, 255, 255, 0.55);
}

.flex-bar .docs-search iconify-icon {
    color: rgba(255, 255, 255, 0.85) !important;
    flex-shrink: 0;
}

.flex-bar .docs-search-input {
    border: none;
    outline: none;
    background: none;
    font-family: 'Quicksand', sans-serif;
    font-size: 14px;
    font-weight: 500;
    width: 100%;
    color: white !important;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
    /* ellipsize instead of clipping mid-glyph when the box is capped
       (tablet caps the search width on control-heavy bars) */
    text-overflow: ellipsis;
}
.flex-bar .docs-search-input::placeholder { color: rgba(255, 255, 255, 0.75); }

@keyframes gradientFlow {
    0% {
        background-position: 0% 50%;
    }
    50% {
        background-position: 100% 50%;
    }
    100% {
        background-position: 0% 50%;
    }
}

/* Onboarding Child/Educator toggle inside the flex bar — compact pill
   pair styled to match the gradient header. Replaces the page-level
   "Select one of the following entities" prompt + tabs. */
.flex-bar-entity-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0;
    padding: 4px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.18);
    border: 1px solid rgba(255, 255, 255, 0.25);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.15);
    margin-left: 14px;
    flex-shrink: 0;
}
.flex-bar-entity-btn {
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: none;
    color: rgba(255, 255, 255, 0.85);
    font-size: 13px;
    font-weight: 700;
    padding: 6px 16px;
    border-radius: 999px;
    cursor: pointer;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
    transition: background 0.18s ease, color 0.18s ease;
}
.flex-bar-entity-btn:hover {
    background: rgba(255, 255, 255, 0.12);
}

/* Leave-without-saving control, left slot. Mirrors .flex-bar-entity-btn's
   sizing so the bar stays balanced around the centred label, but is
   deliberately lower-contrast: exiting is the recoverable action and must not
   compete with the commit button on the opposite side. */
.flex-bar-back-btn {
    appearance: none;
    -webkit-appearance: none;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: transparent;
    border: none;
    color: rgba(255, 255, 255, 0.7);
    font-size: 13px;
    font-weight: 600;
    padding: 6px 14px;
    border-radius: 999px;
    cursor: pointer;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
    transition: background 0.18s ease, color 0.18s ease;
}
.flex-bar-back-btn:hover {
    background: rgba(255, 255, 255, 0.12);
    color: rgba(255, 255, 255, 0.95);
}
.flex-bar-entity-btn.is-active {
    background: rgba(255, 255, 255, 0.95);
    color: #21304d;
    text-shadow: none;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
}

/* Action button in flex bar (Add Child, Save and Exit) - matches gallery Send button style */
.flex-bar-entity-btn.action-btn {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    background: #10b981;
    color: white;
    border: none;
    border-radius: 8px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s ease;
    white-space: nowrap;
    text-shadow: none;
    margin-left: 10px;
}

.flex-bar-entity-btn.action-btn:hover {
    background: #059669;
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);
}

.flex-bar-entity-btn.action-btn.btn-outline {
    background: transparent;
    border: 2px solid rgba(255, 255, 255, 0.6);
    color: rgba(255, 255, 255, 0.85);
}

.flex-bar-entity-btn.action-btn.btn-outline:hover {
    background: rgba(255, 255, 255, 0.12);
    transform: none;
    box-shadow: none;
}

.flex-bar-entity-btn.action-btn.btn-disabled {
    cursor: not-allowed;
    background: rgba(255, 255, 255, 0.15) !important;
    border: 2px solid rgba(255, 255, 255, 0.4) !important;
    color: rgba(255, 255, 255, 0.65) !important;
    box-shadow: none !important;
}

.flex-bar-entity-btn.action-btn.btn-disabled:hover {
    transform: none !important;
    box-shadow: none !important;
    background: rgba(255, 255, 255, 0.15) !important;
}

.flex-bar-entity-btn.action-btn.btn-disabled iconify-icon {
    opacity: 0.65;
}

/* ── Flex Bar – module content wrapper ──────────────────────────────────── */
.flex-bar-content {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    animation: flexBarFadeIn 0.3s ease both;
    min-width: 0;
}
/* When teleported controls sit beside the title (room/week, filters),
   don't force the title wrapper to width:100% — that collides with
   #topBarControls and paints the title under the pickers. Keep a
   readable ellipsis floor so long titles yield space to controls.

   The predicate must mean "a control is VISIBLE beside the title", not
   "an element exists". A bare `> *` also matched Alpine's inert `<template>`
   hosts, which never render: at one click into Children the only child of
   #topBarControls is such a template, so the title wrapper collapsed from
   100% to its intrinsic width and the spacer vanished, leaving the bar
   `justify-content: center` with nothing to fill it — Back and the title
   clustered in the middle of the bar. Excluding templates and x-show'd
   (`style="display: none"`) children matches what the tablet rules below
   already do with `> div:not([style*="display: none"])`. */
.flex-bar:has(#topBarControls > *:not(template):not([style*="display: none"])) .flex-bar-content {
    width: auto;
    flex: 0 1 auto;
    min-width: 0;
    justify-content: flex-start;
}
.flex-bar:has(#topBarControls > *:not(template):not([style*="display: none"])) .flex-bar-content > span {
    min-width: 72px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Empty spacer between title and controls must not steal gap budget. */
.flex-bar:has(#topBarControls > *:not(template):not([style*="display: none"])) .top-bar-spacer-left {
    display: none;
}
/* The spacer is the LEFT action slot, and its job is to BALANCE a leading
   item so the centred title stays centred: Back on the left contributes one
   14px gap, the spacer contributes the matching one on the right, and they
   cancel. With no Back rendered there is nothing to balance, so the spacer
   becomes a one-sided 14px trailing gap that drags the title left — the
   other half of Messaging's off-centre label. Only carry the counterweight
   when there is a weight. */
.flex-bar:not(:has(.flex-bar-back-controls:not(:empty))) .top-bar-spacer-left {
    display: none;
}

@keyframes flexBarFadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* ── Flex Bar – notification ─────────────────────────────────────────────── */
/* Notification used to be `position: absolute; inset: 0` so it
   overlaid the bar perfectly. Side effect: it didn't contribute to
   the bar's intrinsic size, so "Are you sure? Stay / Log Out" got
   crushed into the inherited 350px min-width. Now in-flow so the
   bar grows to fit its own content (and gets clamped only by
   .flex-bar-container's 2/3 max-width). */
.flex-bar-notif {
    /* Flow naturally so the parent flex-bar grows vertically with
       wrapped multi-line warnings. Siblings (spacers / nav controls)
       are pulled out of flow below so they don't reserve height. */
    position: relative;
    display: flex;
    align-items: center;
    gap: 15px;
    padding: 10px 25px;
    animation: flexBarSlideIn 0.25s ease;
    justify-content: center;
    /* Same radius as the outer .flex-bar (set below when a notif is
       showing). Stretch to full bar height so we never leave a shorter
       inner pill floating inside a taller outer shell — that double
       radius was the corner overflow/rim users saw on error toasts. */
    border-radius: inherit;
    align-self: stretch;
    width: 100%;
    box-sizing: border-box;
    white-space: nowrap;
    /* Parent already paints the type gradient; keep this layer clear so
       only one rounded surface is visible. */
    background: transparent !important;
}

.flex-bar:has(.flex-bar-notif) {
    /* Bar collapses to the notification's natural width — the parent
       container caps it at ~92vw of the header when a notif is up
       (see .flex-bar-container:has(.flex-bar-notif) below). Floor stays
       at the regular .flex-bar min-width so a one-word toast still
       looks like a bar, not a button. */
    width: max-content;
    min-width: 350px;
    max-width: 100%;
    padding: 0;
    /* Drop the fixed 56px height so multi-line errors aren't clipped,
       and use a rounder radius (matches header/side-nav 25px language)
       shared with the inner notif via border-radius: inherit. */
    height: auto;
    min-height: 56px;
    border-radius: 25px;
    overflow: hidden;
    box-shadow: none;
    border-color: transparent;
}

/* When a notification is showing, widen the container cap so the bar
   grows HORIZONTALLY first — prose like "Email invoice X to Y (no email
   on file — Stripe will use the address from their associate record)
   via Stripe?" fits on one or two lines instead of three. Plain
   navigation labels are still bounded by the original 720 px clamp
   defined on the base .flex-bar-container rule.

   Cap: header width minus ~640 px reserved for the left logo/profile
   cluster and the right notifications + AI bubble. Container is
   centered (left:50% + translateX(-50%)) so the symmetric reserve is
   what keeps wide confirms from sliding under the side icons. The
   right cluster (context-add + AI bubble + chat + 2-3 notification
   icons + container padding) needs ~310 px clearance; mirroring that
   on the left keeps the centered bar symmetric. */
.flex-bar-container:has(.flex-bar-notif) {
    width: max-content;
    max-width: calc(100% - 640px);
}

/* Offline queue chip + module controls (e.g. Activity Planner room/week)
   need more horizontal room than the default 45vw/720px clamp. Grow to
   content so nothing clips; keep the same side clearance as notifications
   so the bar never slides under profile / header icons. */
.flex-bar-container--offline-queue {
    width: max-content;
    max-width: min(92%, calc(100% - 480px));
}
.flex-bar--offline-queue {
    width: max-content;
    max-width: 100%;
    min-width: 350px;
    gap: 12px;
    padding-left: 14px;
    padding-right: 18px;
    height: auto;
    min-height: 56px;
    /* Single row: chip | title | controls — no full-width children
       stacking/overlapping each other. */
    justify-content: center;
    flex-wrap: nowrap;
    overflow: visible;
}
/* .flex-bar-content defaults to width:100%, which forces the title
   strip to eat the whole bar and paint over room/week controls once
   we switch to content-sized width. Collapse to intrinsic width. */
.flex-bar--offline-queue .flex-bar-content {
    width: auto;
    flex: 0 0 auto;
    justify-content: flex-start;
    min-width: 0;
}
/* label-centered duplicates the title already rendered inside
   .flex-bar-content for non-dashboard modules (tablet already hid
   this; desktop only blew up once offline expanded the bar). */
.flex-bar:has(.flex-bar-content) .label-centered {
    display: none !important;
}
.flex-bar--offline-queue #topBarControls,
.flex-bar--offline-queue .flex-bar-mode-toggle,
.flex-bar--offline-queue .flex-bar-back-controls,
.flex-bar--offline-queue .flex-bar-next-controls,
.flex-bar--offline-queue .offline-queue-wrap {
    flex: 0 0 auto;
    min-width: 0;
}
.flex-bar--offline-queue .offline-queue-wrap {
    margin-right: 0;
}
/* Empty left spacer must not steal space in the content-sized row. */
.flex-bar--offline-queue .top-bar-spacer-left {
    display: none;
}

/* Hide the regular bar children outright when a notification is
   present — `visibility: hidden` preserved their layout space, which
   prevented the notif from sizing the bar. `display: none` lets the
   notif drive the width. */
/* The notification markup moved into a <seahorse-flex-bar-notif> custom
   element (js/shell-chrome.js) so the shells stop duplicating it. That added a
   wrapper the selector below did not know about: `:has()` matches DESCENDANTS
   so the rule still fired, but `>` matches DIRECT CHILDREN, and the direct
   child is now the wrapper — which is not `.flex-bar-notif`. So this rule was
   hiding the notification's own container along with the siblings, and the bar
   went completely blank on every notify()/confirm(). `flexBarSlideIn` then
   froze at its `from` state, which is why the element also measured opacity 0.

   Cost while it was broken: flexBar.confirm() renders the Confirm/Cancel
   buttons, so any flow gated on one was unreachable — deleting a child avatar
   among them, which read as "there is no way to delete a photo".

   `display: contents` puts .flex-bar-notif back in the bar's own flex layout,
   as it was before the wrapper existed. It does NOT affect selector matching,
   so the :not() exclusion is still required. */
seahorse-flex-bar-notif {
    display: contents;
}

.flex-bar:has(.flex-bar-notif) > *:not(.flex-bar-notif):not(seahorse-flex-bar-notif) {
    display: none !important;
}

@keyframes flexBarSlideIn {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0);    }
}

.flex-bar-notif__icon {
    font-size: 16px;
    font-weight: 800;
    flex-shrink: 0;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255,255,255,0.25);
}

.flex-bar-notif__msg {
    /*
      Use flex:1 with min-width:0 so the message is allowed to shrink
      inside the (centered, width-capped) flex-bar. Wrap on long copy so
      the full warning is readable — bar grows vertically instead of
      truncating with "…".
    */
    flex: 1 1 auto;
    min-width: 0;
    max-width: 100%;
    font-size: 16px;
    font-weight: 700;
    text-shadow: 0 1px 2px rgba(0,0,0,0.15);
    line-height: 1.3;
    /* pre-line: honour explicit \n as a visual break while still
       wrapping long copy. Lets callers control sentence splits. */
    white-space: pre-line;
    text-align: center;
}

/* When a notification is active, relax the parent flex-bar's nowrap so
   the inner message can lay out within the bar rather than forcing the
   whole bar to its intrinsic width. */
.flex-bar:has(.flex-bar-notif) {
    white-space: normal;
}

.flex-bar-notif__actions {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-shrink: 0;
}

/* Notification type — paint the OUTER flex-bar only. Inner .flex-bar-notif
   stays transparent so outer and inner share one radius (no double pill). */
.flex-bar-notif--success,
.flex-bar-notif--error,
.flex-bar-notif--warning,
.flex-bar-notif--info,
.flex-bar-notif--confirm {
    background: transparent !important;
    animation: flexBarSlideIn 0.25s ease;
}

.flex-bar:has(.flex-bar-notif--success) { background: linear-gradient(135deg, #00b894, #00cec9) !important; animation: none; border-color: rgba(0,184,148,0.5); }
.flex-bar:has(.flex-bar-notif--error)   { background: linear-gradient(135deg, #d63031, #e17055) !important; animation: none; border-color: rgba(214,48,49,0.5); }
.flex-bar:has(.flex-bar-notif--warning) { background: linear-gradient(135deg, #e17055, #fdcb6e) !important; animation: none; border-color: rgba(253,203,110,0.5); }
.flex-bar:has(.flex-bar-notif--info)    { background: linear-gradient(135deg, #74b9ff, #a29bfe) !important; animation: none; border-color: rgba(116,185,255,0.5); }
.flex-bar:has(.flex-bar-notif--confirm) { background: linear-gradient(135deg, #6c5ce7, #a29bfe) !important; animation: none; border-color: rgba(108,92,231,0.5); }

/* Notification buttons */
.flex-bar-notif__btn {
    padding: 8px 18px;
    border-radius: 12px;
    border: 1px solid rgba(255, 255, 255, 0.3);
    font-size: 14px;
    font-weight: 700;
    font-family: 'Quicksand', sans-serif;
    cursor: pointer;
    transition: all 0.25s cubic-bezier(0.175, 0.885, 0.32, 1.4);
    white-space: nowrap;
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
    box-shadow:
        inset 1px 1px 0.5px 0 rgba(255, 255, 255, 0.3),
        inset -0.5px -0.5px 0.5px 0.5px rgba(255, 255, 255, 0.2);
}
.flex-bar-notif__btn:hover { transform: scale(1.05); }

.flex-bar-notif__btn--primary   { background: rgba(255, 255, 255, 0.85); color: #6c5ce7; }
.flex-bar-notif__btn--secondary { background: rgba(255,255,255,0.2); color: white; border: 1px solid rgba(255,255,255,0.4); }
.flex-bar-notif__btn--danger    { background: rgba(214, 48, 49, 0.85); color: white; }

.flex-bar-notif__close {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: none;
    background: rgba(255,255,255,0.2);
    color: white;
    font-size: 11px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s ease;
    flex-shrink: 0;
    font-family: 'Quicksand', sans-serif;
}
.flex-bar-notif__close:hover { background: rgba(255,255,255,0.35); }

.message-notification-dot {
    width: 8px;
    height: 8px;
    background-color: #f1c40f;
    border-radius: 50%;
}

.messages-dropdown {
    display: none;
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    background: rgba(255, 255, 255, 0.75);
    border-radius: 16px;
    box-shadow:
        0 8px 28px rgba(0, 0, 0, 0.12),
        0 2px 8px rgba(0, 0, 0, 0.06),
        inset 1.5px 1.5px 1px 0 rgba(255, 255, 255, 0.5),
        inset -1px -1px 1px 0.5px rgba(255, 255, 255, 0.4);
    padding: 20px;
    z-index: 110;
    margin-top: 10px;
    width: 450px;
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border: 1px solid rgba(255, 255, 255, 0.4);
}

.messages-dropdown.show {
    display: block;
}

.message {
    padding-bottom: 10px;
    margin-bottom: 10px;
    border-bottom: 1px solid #ecf0f1;
}

.message:last-child {
    border-bottom: none;
    margin-bottom: 0;
}

.message p {
    font-size: 14px;
    color: #34495e;
    margin-bottom: 5px;
}

.message span {
    font-size: 11px;
    color: #7f8c8d;
}

/* Notifications */
.notifications {
    /* Read back by .header-icon-collapsible to cancel its own gap share
       when it collapses — keep the two in step by changing only this. */
    --header-icon-gap: 15px;
    display: flex;
    align-items: center;
    gap: var(--header-icon-gap);
}

.notification-item {
    position: relative;
    cursor: pointer;
}

.notification-icon {
    width: 45px;
    height: 45px;
    background: rgba(255, 255, 255, 0.25);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.3);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #21304d;
    font-size: 18px;
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15),
                inset 0 1px 1px rgba(255, 255, 255, 0.5),
                inset 0 -1px 1px rgba(0, 0, 0, 0.1);
    transition: all 0.3s ease;
}

.notification-icon:hover {
    transform: scale(1.1);
    box-shadow: 0 12px 25px rgba(0, 0, 0, 0.2),
                inset 0 1px 1px rgba(255, 255, 255, 0.6),
                inset 0 -1px 1px rgba(0, 0, 0, 0.15);
}

/* .context-add-btn--filled removed 2026-08-05 — it only ever marked the
   child daily-care log as "engaged", and (+) is now hidden on that
   surface rather than highlighted. */

/* Contextual header icons — (+) and Edit — come and go as you move between
   the child grid, the read view and the daily-care log. They used x-show,
   which flips `display`, so the icons to their right jumped sideways the
   instant the state changed; the fade x-transition added never touched that
   reflow, and the reflow is the part that read as abrupt. These stay in
   flow and collapse their own box instead, so the row closes over the gap
   in the same beat as the fade. .notification-icon's `transition: all 0.3s
   ease` already carries width / margin / opacity / transform, so there is
   no separate transition declaration to keep in sync here.

   Deliberately NO `overflow: hidden`: it would clip the .has-tip ::after
   tooltip, which renders above the disc. The glyph rides the shrinking
   box's centre instead and is fully faded well before the box is small
   enough for it to spill. */
.header-icon-collapsible.is-collapsed {
    width: 0;
    /* A zero-width flex item still earns its share of the .notifications
       gap — cancel it so the row really does close up. Tablet slims that
       gap to 4px, hence the variable rather than a literal. */
    margin-left: calc(-1 * var(--header-icon-gap, 15px));
    padding: 0;
    border-width: 0;
    box-shadow: none;
    opacity: 0;
    transform: scale(0.55);
    pointer-events: none;
}

/* ── View-mode toggle (Operate / Analyze) ───────────────────────
   Single iconify glyph (pencil for Operate, telescope for Analyze)
   on a standard .notification-icon disc. Active state (.is-analyze)
   shifts the background to teal so the toggle's current mode is
   visible at a glance without reading the icon. 2026-05-26 —
   simpler than the earlier crescent-SVG approach; icons are bigger
   and more legible. Modules opt in via `supportsModes: true`. */
.header-mode-toggle.is-analyze {
    background: rgba(70, 207, 192, 0.45);
    border-color: rgba(70, 207, 192, 0.7);
    box-shadow: 0 8px 20px rgba(70, 207, 192, 0.25),
                inset 0 1px 1px rgba(255, 255, 255, 0.5),
                inset 0 -1px 1px rgba(0, 0, 0, 0.08);
}
.header-mode-toggle.is-analyze:hover {
    box-shadow: 0 12px 25px rgba(70, 207, 192, 0.32),
                inset 0 1px 1px rgba(255, 255, 255, 0.6),
                inset 0 -1px 1px rgba(0, 0, 0, 0.12);
}

/* Header print button — context-aware dropdown. Drops DOWN from the
   button. Reads $store.shared.printContext to populate items. */
.header-print {
    position: relative;
}
.header-print.is-open {
    background: rgba(255, 255, 255, 0.7);
    color: #21304d;
}
.header-print-menu {
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    z-index: 1000;
    min-width: 240px;
    padding: 6px;
    background: rgba(255, 255, 255, 0.97);
    border: 1px solid rgba(33, 48, 77, 0.08);
    border-radius: 14px;
    box-shadow:
        2px 5px 4px rgba(33, 48, 77, 0.08),
        3px 14px 22px rgba(33, 48, 77, 0.14);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    text-align: left;
    cursor: default;
}
.header-print-item {
    font-family: inherit;
    width: 100%;
    padding: 8px 10px;
    border-radius: 10px;
    border: none;
    cursor: pointer;
    color: #21304d;
    background: transparent;
    display: flex;
    align-items: center;
    gap: 10px;
    transition: background 0.12s ease;
}
.header-print-item:hover {
    background: rgba(116, 185, 255, 0.14);
}
.header-print-item iconify-icon {
    color: #4a5670;
    flex-shrink: 0;
}
.header-print-item-label {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 1px;
    line-height: 1.3;
}
.header-print-item-title {
    font-size: 13px;
    font-weight: 600;
}
.header-print-item-sub {
    font-size: 11px;
    color: #64748b;
    font-weight: 500;
}
.header-print-empty {
    padding: 12px;
    color: #94a3b8;
    font-size: 12px;
    text-align: center;
}

/* ── Priority Tasks panel (header bell dropdown) ────────────────────
   Same glass treatment as .header-print-menu, but a taller, scrollable
   list of open items. Each row jumps to the record; a footer CTA starts
   the guided walkthrough. */
.priority-panel {
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    z-index: 1000;
    width: 320px;
    padding: 6px;
    background: rgba(255, 255, 255, 0.97);
    border: 1px solid rgba(33, 48, 77, 0.08);
    border-radius: 14px;
    box-shadow:
        2px 5px 4px rgba(33, 48, 77, 0.08),
        3px 14px 22px rgba(33, 48, 77, 0.14);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    text-align: left;
    cursor: default;
}
.priority-panel-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    padding: 6px 8px 8px;
    border-bottom: 1px solid rgba(33, 48, 77, 0.07);
    margin-bottom: 4px;
}
.priority-panel-title {
    font-size: 13px;
    font-weight: 700;
    color: #21304d;
}
.priority-panel-count {
    font-size: 11px;
    font-weight: 600;
    color: #e17055;
}
.priority-panel-body {
    max-height: 320px;
    overflow-y: auto;
}
.priority-item {
    display: flex;
    align-items: center;
}
/* Main clickable area — jumps to the record. */
.priority-item-go {
    font-family: inherit;
    flex: 1;
    min-width: 0;
    padding: 8px 10px;
    border-radius: 10px;
    border: none;
    cursor: pointer;
    color: #21304d;
    background: transparent;
    display: flex;
    align-items: center;
    gap: 10px;
    text-align: left;
    transition: background 0.12s ease;
}
.priority-item-go:hover {
    background: rgba(116, 185, 255, 0.14);
}
/* ✨ Radar → Co-pilot action — pre-fills the AI on this task. */
.priority-item-spark {
    flex-shrink: 0;
    margin-left: 2px;
    padding: 6px;
    border: none;
    border-radius: 8px;
    background: transparent;
    color: #b8c0cf;
    cursor: pointer;
    display: flex;
    align-items: center;
    transition: background 0.12s ease, color 0.12s ease;
}
.priority-item-spark:hover {
    background: rgba(9, 132, 227, 0.12);
    color: #0984e3;
}
.priority-item-dot {
    flex-shrink: 0;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #94a3b8;
}
.priority-item-dot.is-late {
    background: #e17055;
}
.priority-item-dot.is-due {
    background: #f39c12;
}
.priority-item-label {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 1px;
    line-height: 1.3;
    flex: 1;
    min-width: 0;
}
.priority-item-title {
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}
.priority-item-sub {
    font-size: 11px;
    color: #64748b;
    font-weight: 500;
}
.priority-item-chev {
    color: #b8c0cf;
    flex-shrink: 0;
    font-size: 18px;
}
.priority-panel-empty {
    padding: 22px 12px;
    color: #94a3b8;
    font-size: 12px;
    text-align: center;
}
.priority-panel-cta {
    font-family: inherit;
    width: 100%;
    margin-top: 4px;
    padding: 9px 10px;
    border-radius: 10px;
    border: none;
    cursor: pointer;
    color: #fff;
    background: linear-gradient(135deg, #0984e3, #74b9ff);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    font-size: 12.5px;
    font-weight: 600;
    transition: filter 0.12s ease;
}
.priority-panel-cta:hover {
    filter: brightness(1.06);
}
.notification-icon--active {
    background: rgba(99, 102, 241, 0.15);
    border-color: rgba(99, 102, 241, 0.35);
    color: #6366f1;
}

/* Ambient pending-task indicators */
.nav-pending-dot {
    position: absolute;
    top: 2px;
    right: 2px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: #e17055;
    border: 2px solid rgba(255, 255, 255, 0.7);
    pointer-events: none;
}


.notification-badge {
    position: absolute;
    top: -3px;
    right: -3px;
    background: #e74c3c;
    color: white;
    border-radius: 50%;
    width: 18px;
    height: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    font-weight: bold;
}

/* Main Content */
.main-content {
    display: flex;
    flex: 1;
    position: relative;
}

/* Logs Sidebar */
.logs-sidebar {
    background: rgba(255, 255, 255, 0.4);
    border-radius: 25px;
    padding: 10px;
    margin-right: 15px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
    backdrop-filter: blur(15px);
    -webkit-backdrop-filter: blur(15px);
    border: 1px solid rgba(255, 255, 255, 0.2);
    display: flex;
    flex-direction: column;
    gap: 10px;
    width: 110px;
    transition: all 0.4s ease;
    position: relative;
    overflow: visible;
    z-index: 100;
}

.expand-toggle {
    position: absolute;
    bottom: 10px;
    left: 50%;
    transform: translateX(-50%);
    width: 40px;
    height: 25px;
    border: none;
    border-radius: 50%;
    background: linear-gradient(135deg, #74b9ff 0%, #0984e3 100%);
    color: white;
    cursor: pointer;
    font-size: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.3s ease;
    z-index: 101;
}

.expand-toggle:hover {
    transform: translateX(-50%) scale(1.1);
}

/* Collapsed View */
.logs-collapsed {
    display: flex;
    flex-direction: column;
    gap: 5px;
    align-items: center;
}

.logs-sidebar.expanded .logs-collapsed {
    display: none;
}

.log-icon-small {
    width: 80px;
    height: 70px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 30px;
    color: white;
    cursor: pointer;
    transition: all 0.3s ease;
}

.log-icon-small.attendance { background: linear-gradient(135deg, #a095e8 0%, #c3bdf2 100%); }
.log-icon-small.bathroom { background: linear-gradient(135deg, #89c4ff 0%, #b9d9ff 100%); }
.log-icon-small.observations { background: linear-gradient(135deg, #50c9b3 0%, #8ee0d1 100%); }
.log-icon-small.snacks { background: linear-gradient(135deg, #ffd58a 0%, #ffb396 100%); }
.log-icon-small.nap { background: linear-gradient(135deg, #ffb3c1 0%, #ffd5a1 100%); }
.log-icon-small.incident { background: linear-gradient(135deg, #ff6b6b 0%, #ff8e8e 100%); }
.log-icon-small.health { background: linear-gradient(135deg, #48dbfb 0%, #7ed6df 100%); }

.log-icon-small:hover {
    transform: scale(1.05);
}

/* Expanded Grid View */
.logs-expanded {
    display: none;
    width: 100%;
    height: 100%;
}

.logs-sidebar.expanded .logs-expanded {
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    width: 1125px;
    height: 100%;
    background: rgba(255, 255, 255, 0.4);
    backdrop-filter: blur(15px);
    -webkit-backdrop-filter: blur(15px);
    border: 1px solid rgba(255, 255, 255, 0.2);
    padding: 10px;
    border-radius: 12px;
    box-shadow: 0 4px 15px rgba(0,0,0,0.1);
    z-index: 100;
}

.grid-main {
    display: grid;
    grid-template-columns: 90px 1fr;
    gap: 15px;
    flex: 1;
}

.grid-logs {
    display: flex;
    flex-direction: column;
    width: 90px;
    align-items: center;
}

.log-icon {
    width: 80px;
    height: 70px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 30px;
    color: white;
    margin-bottom: 5px;
    cursor: pointer;
    transition: all 0.3s ease;
}

.log-icon.attendance { background: linear-gradient(135deg, #a095e8 0%, #c3bdf2 100%); }
.log-icon.bathroom { background: linear-gradient(135deg, #89c4ff 0%, #b9d9ff 100%); }
.log-icon.observations { background: linear-gradient(135deg, #50c9b3 0%, #8ee0d1 100%); }
.log-icon.snacks { background: linear-gradient(135deg, #ffd58a 0%, #ffb396 100%); }
.log-icon.nap { background: linear-gradient(135deg, #ffb3c1 0%, #ffd5a1 100%); }
.log-icon.incident { background: linear-gradient(135deg, #ff6b6b 0%, #ff8e8e 100%); }
.log-icon.health { background: linear-gradient(135deg, #48dbfb 0%, #7ed6df 100%); }

.log-icon:hover {
    transform: scale(1.05);
}

.grid-cells {
    flex: 1;
    display: flex;
    flex-direction: column;
}

.grid-row {
    display: flex;
    margin-bottom: 5px;
    height: 70px;
    align-items: center;
    gap: 10px;
}

.grid-cell {
    width: 80px;
    height: 70px;
    border: 2px solid #ecf0f1;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.3s ease;
    background: white;
    font-size: 12px;
    font-weight: bold;
    text-align: center;
    padding: 2px;
}

.grid-cell.logged {
    background: linear-gradient(135deg, #00b894 0%, #55efc4 100%);
    color: white;
    border-color: #00b894;
}

.grid-cell.away-cell {
    background: #f8f9fa;
    color: #bbb;
    border-style: dashed;
}

.grid-cell:hover:not(.away-cell) {
    transform: scale(1.05);
    border-color: #74b9ff;
}

.grid-cell.no-nap-cell {
    background: linear-gradient(135deg, #e17055 0%, #fab1a0 100%);
    color: white;
    border-color: #e17055;
    font-size: 20px;
}

/* Center Activity Area */
.center-area {
    flex: 1;
    display: flex;
    align-items: stretch;
    justify-content: center;
    transition: opacity 0.4s ease 0.2s;
    margin-right: 15px;
}

.logs-sidebar.expanded + .center-area {
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
}

.activity-display {
    position: relative;
    z-index: 1;
    border-radius: 25px;
    padding: 40px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
    text-align: center;
    width: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    transition: all 0.4s ease;
    background: rgba(255, 255, 255, 0.25);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid rgba(255, 255, 255, 0.2);
}

.activity-display::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: var(--activity-background, linear-gradient(135deg, #a8edea 0%, #fed6e3 100%));
    opacity: 0.25;
    border-radius: 15px;
    z-index: -1;
}

.activity-icon {
    font-size: 60px;
    margin-bottom: 20px;
}

.activity-name {
    font-size: 28px;
    color: #21304d;
    font-weight: bold;
    margin-bottom: 10px;
}

.activity-time {
    font-size: 18px;
    color: #7f8c8d;
    margin-bottom: 15px;
}

.activity-description {
    font-size: 16px;
    color: #34495e;
    line-height: 1.5;
}

/* Log Entry Display */
.log-entry-display {
    display: none;
    background: white;
    border-radius: 15px;
    padding: 20px;
    box-shadow: 0 4px 15px rgba(0,0,0,0.1);
    width: 100%;
    height: 100%;
    flex-direction: column;
}

.log-entry-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15px;
}

.log-entry-header h3 {
    font-size: 22px;
    color: #21304d;
}

.close-btn {
    font-size: 24px;
    cursor: pointer;
    color: #7f8c8d;
}

.selected-children-container {
    margin-bottom: 20px;
    padding: 10px;
    background: #f8f9fa;
    border-radius: 8px;
    min-height: 50px;
}

.selected-children-list {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: center;
    justify-content: center;
}

.selected-children-placeholder {
    color: #7f8c8d;
    font-style: italic;
    font-size: 14px;
}

.selected-child-tag {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: #74b9ff;
    color: white;
    padding: 5px 10px;
    border-radius: 15px;
    font-size: 14px;
    cursor: pointer;
}

.log-entry-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 8px;
    overflow-y: auto;
}

.log-form-group {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.log-form-group label {
    font-weight: bold;
    color: #34495e;
}

.log-form-group input,
.log-form-group textarea,
.log-form-group select {
    width: 100%;
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 8px;
    font-size: 14px;
    font-family: 'Quicksand', sans-serif;
}

.log-form-group textarea {
    resize: vertical;
    min-height: 100px;
}

.log-button-group {
    display: flex;
    gap: 10px;
}

.log-button {
    flex: 1;
    padding: 12px;
    border: none;
    border-radius: 8px;
    background: #ecf0f1;
    color: #21304d;
    cursor: pointer;
    font-size: 14px;
    transition: background 0.3s;
    font-family: 'Quicksand', sans-serif;
}

.log-button.active {
    background: #74b9ff;
    color: white;
}

.log-submit-btn {
    padding: 15px;
    border: none;
    border-radius: 8px;
    background: #0984e3;
    color: white;
    font-size: 16px;
    cursor: pointer;
    margin-top: auto;
    transition: background-color 0.3s ease;
    font-family: 'Quicksand', sans-serif;
    font-weight: 500;
}

.log-submit-btn.saved {
    background-color: #27ae60;
}

.log-submit-btn:disabled {
    background-color: #a4b0be;
    opacity: 0.6;
    cursor: not-allowed;
}

/* Child Profile Display */
.child-profile-display {
    display: none;
    flex-direction: column;
    gap: 20px;
    width: 100%;
    height: 100%;
    padding: 25px;
    background: rgba(255, 255, 255, 0.4);
    border-radius: 25px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
    backdrop-filter: blur(15px);
    -webkit-backdrop-filter: blur(15px);
    border: 1px solid rgba(255, 255, 255, 0.2);
}

.profile-header {
    display: flex;
    align-items: center;
    gap: 20px;
}

.profile-photo {
    width: 100px;
    height: 100px;
    border-radius: 50%;
    background-color: #ccc;
    background-size: cover;
    background-position: center;
    border: 3px solid white;
    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}

.profile-details {
    flex: 1;
}

.profile-details h2 {
    font-size: 24px;
    color: #21304d;
    margin-bottom: 5px;
}

.profile-details p {
    font-size: 14px;
    color: #7f8c8d;
}

.profile-status {
    font-size: 14px;
    font-weight: 500;
    padding: 4px 10px;
    border-radius: 12px;
    display: inline-block;
    margin-top: 8px;
}

.profile-status.absent {
    color: #7f8c8d;
    background-color: #dfe6e9;
}

.profile-status.present {
    color: #00b894;
    background-color: #e8f5e8;
}

.profile-status.picked-up {
    color: #2d3436;
    background-color: #b2bec3;
}

.profile-actions {
    display: flex;
    gap: 10px;
    flex-direction: column;
}

.profile-actions button {
    padding: 10px 15px;
    border-radius: 20px;
    border: 1px solid #bdc3c7;
    background: white;
    cursor: pointer;
    font-size: 14px;
    font-weight: 500;
    transition: all 0.3s ease;
    font-family: 'Quicksand', sans-serif;
}

.profile-actions button:hover {
    background: #f0f0f0;
    border-color: #7f8c8d;
}

.profile-actions button.check-in-btn {
    background-color: #0984e3;
    color: white;
    border-color: #0984e3;
}

.profile-actions button.check-out-btn {
    background-color: #d63031;
    color: white;
    border-color: #d63031;
}

.profile-summary {
    background: rgba(255, 255, 255, 0.5);
    border-radius: 15px;
    padding: 20px;
}

.profile-summary h3 {
    margin-bottom: 10px;
    color: #34495e;
}

.profile-cards {
    display: flex;
    gap: 20px;
    flex: 1;
}

.profile-card {
    flex: 1;
    background: rgba(255, 255, 255, 0.5);
    border-radius: 15px;
    padding: 20px;
    display: flex;
    flex-direction: column;
}

.profile-card h3 {
    margin-bottom: 15px;
    color: #34495e;
}

.profile-card ul {
    list-style-type: none;
    padding-left: 5px;
}

.profile-card ul li {
    margin-bottom: 10px;
    padding-left: 20px;
    position: relative;
}

.profile-card ul li::before {
    content: '✓';
    position: absolute;
    left: 0;
    color: #27ae60;
}

/* Right Panel - Timeline */
.right-panel {
    width: 110px;
    background: rgba(255, 255, 255, 0.4);
    border-radius: 25px;
    padding: 20px 10px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
    backdrop-filter: blur(15px);
    -webkit-backdrop-filter: blur(15px);
    border: 1px solid rgba(255, 255, 255, 0.2);
    display: flex;
    justify-content: center;
    user-select: none;
    position: relative;
    z-index: 2001;
}

.timeline {
    position: relative;
    height: 100%;
    width: 2px;
    background-color: #ccc;
}

.timeline-progress {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    background-color: #888;
    z-index: 1;
}

.timeline-marker {
    position: absolute;
    left: 10px;
    transform: translateY(-50%) rotate(45deg);
    width: 40px;
    height: 40px;
    border-radius: 50% 50% 50% 0;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    background-color: #f0f0f0;
    border: 1px solid #ccc;
    z-index: 2;
    transition: all 0.3s ease;
}

.current-time-marker {
    position: absolute;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 90px;
    height: 35px;
    background: rgba(255, 255, 255, 0.65);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-radius: 25px;
    border: 1px solid rgba(255, 255, 255, 0.4);
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15),
                inset 0 1px 1px rgba(255, 255, 255, 0.7);
    cursor: grab;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #21304d;
    font-size: 12px;
    font-weight: bold;
    z-index: 3;
    text-shadow: 0 1px 1px rgba(0,0,0,0.1);
    transition: background-color 0.1s ease;
}

.timeline-time {
    position: absolute;
    right: 10px;
    transform: translateY(-50%);
    font-size: 12px;
    color: #888;
    transition: all 0.3s ease;
}

/* Children Status Row */
.children-row {
    display: flex;
    background: rgba(255, 255, 255, 0.4);
    border-radius: 25px;
    padding: 15px 20px 25px 20px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
    backdrop-filter: blur(15px);
    -webkit-backdrop-filter: blur(15px);
    border: 1px solid rgba(255, 255, 255, 0.2);
    margin-top: 15px;
    position: relative;
}

.children-spacer {
    width: 105px;
    flex-shrink: 0;
    transition: all 0.4s ease;
}

/* Attendance tray only — do not use bare .children-grid (collides with
   the Children module card grid in children-module.css). */
.attendance-modal .children-grid,
.children-row .children-grid {
    flex: 1;
    display: flex;
    gap: 10px;
}

.child-status {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: bold;
    font-size: 14px;
    cursor: pointer;
    transition: all 0.3s ease;
    position: relative;
    backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px);
    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2),
                inset 0 2px 2px rgba(255, 255, 255, 0.6),
                inset 0 -2px 2px rgba(0, 0, 0, 0.1);
    text-shadow: 0 1px 1px rgba(0,0,0,0.2);
}

.child-status.present {
    background: linear-gradient(135deg, #55efc4 0%, #00b894 100%);
    border: 1px solid #00b894;
    color: white;
    box-shadow: 0 10px 20px rgba(0, 184, 148, 0.25),
                inset 0 2px 2px rgba(255, 255, 255, 0.5),
                inset 0 -2px 2px rgba(0, 0, 0, 0.15);
}

.child-status.picked-up {
    background: #b2bec3;
    border: 1px solid #95a5a6;
    color: #2d3436;
    box-shadow: 0 5px 10px rgba(0, 0, 0, 0.15),
                inset 0 2px 2px rgba(255, 255, 255, 0.5),
                inset 0 -2px 2px rgba(0, 0, 0, 0.05);
}

.child-status.away {
    background: transparent;
    border: 3px dashed #b2bec3;
    color: #a4b0be;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: none;
    text-shadow: none;
}

.child-status.neutral {
    background: radial-gradient(circle at 50% 0%, rgba(255, 255, 255, 0.5) 0%, rgba(224, 224, 224, 0.5) 100%);
    border: 1px solid rgba(255, 255, 255, 0.6);
    color: #7f8c8d;
}

.child-status:hover {
    transform: scale(1.1);
}

.child-status.disabled,
.child-status.inactive-for-log {
    opacity: 0.4;
}

.child-status.disabled {
    cursor: not-allowed;
}

.child-status.selected {
    transform: scale(1.1);
    box-shadow: 0 0 15px rgba(9, 132, 227, 0.7);
    border-color: #74b9ff;
}

.tooltip {
    position: absolute;
    bottom: -30px;
    left: 50%;
    transform: translateX(-50%);
    background: #21304d;
    color: white;
    padding: 4px 8px;
    border-radius: 4px;
    font-size: 10px;
    white-space: nowrap;
    opacity: 0;
    transition: opacity 0.3s ease;
    z-index: 1000;
}

.child-status:hover .tooltip {
    opacity: 1;
}

/* Legend */
.legend {
    display: flex;
    gap: 20px;
    justify-content: center;
    font-size: 12px;
    margin-top: 10px;
    position: absolute;
    bottom: 8px;
    left: 50%;
    transform: translateX(-50%);
}

.legend-item {
    display: flex;
    align-items: center;
    gap: 5px;
    color: #7f8c8d;
}

.legend-dot {
    width: 14px;
    height: 14px;
    border-radius: 50%;
}

.legend-dot.present { background: linear-gradient(135deg, #00b894 0%, #55efc4 100%); }
.legend-dot.picked-up { background: #bdc3c7; }
.legend-dot.away { border: 2px dashed #bdc3c7; background: transparent; }

/* Modals — heavy frosted scrim that matches .lightbox-overlay so
   modals everywhere (Send Photos, Send Document, asset picker, etc.)
   read like the photo lightbox: one element clear and in focus, the
   rest washed into a uniform slate-blue blur. The .header
   (z-index: 10002) sits above this scrim so the flex bar and module
   pill stay sharp. */
.modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(208, 212, 222, 0.78);
    backdrop-filter: blur(28px) saturate(1.3);
    -webkit-backdrop-filter: blur(28px) saturate(1.3);
    display: flex;
    justify-content: center;
    align-items: flex-start;
    padding: 5vh 0;
    overflow-y: auto;
    z-index: 2000;
    border: none;
}

.modal-content {
    background: rgba(255, 255, 255, 0.35);
    padding: 25px;
    border-radius: 20px;
    box-shadow:
        0 20px 60px rgba(0, 0, 0, 0.1),
        0 4px 16px rgba(0, 0, 0, 0.05),
        inset 2px 2px 1px 0 rgba(255, 255, 255, 0.7),
        inset -1px -1px 1px 1px rgba(255, 255, 255, 0.5);
    width: 80%;
    max-width: 900px;
    height: 80%;
    display: flex;
    flex-direction: column;
    border: 1px solid rgba(255, 255, 255, 0.5);
    backdrop-filter: blur(10px) saturate(1.1);
    -webkit-backdrop-filter: blur(10px) saturate(1.1);
}

.modal-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-bottom: 1px solid rgba(0, 0, 0, 0.06);
    padding-bottom: 15px;
    margin-bottom: 15px;
}

.modal-header h2 {
    color: #21304d;
}

.close-modal {
    font-size: 28px;
    cursor: pointer;
    color: #7f8c8d;
}

.close-modal:hover {
    color: #34495e;
}

.modal-body {
    flex: 1;
    overflow-y: auto;
}

.record-item {
    background: #f8f9fa;
    border: 1px solid #ecf0f1;
    border-radius: 8px;
    padding: 15px;
    margin-bottom: 10px;
}

.record-item h4 {
    color: #34495e;
    margin-bottom: 10px;
}

.record-item pre {
    background: #e9ecef;
    padding: 10px;
    border-radius: 5px;
    white-space: pre-wrap;
    word-wrap: break-word;
    font-size: 13px;
    font-family: monospace;
}

/* Confetti Canvas */
#confetti-canvas {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 9999;
    display: none;
}

/* Attendance Log Specific Styles */
.attendance-log-container {
    display: flex;
    flex-direction: column;
    gap: 15px;
    height: 100%;
    flex: 1;
}

.attendance-box {
    flex: 1;
    border: 3px dashed #dfe6e9;
    border-radius: 12px;
    padding: 15px;
    display: flex;
    flex-direction: column;
    transition: all 0.3s ease;
    cursor: pointer;
}

.attendance-box.active {
    border-color: #74b9ff;
    border-style: solid;
    background-color: #f0f7ff;
}

/* Educators Attendance: smoother drag */
.attendance-chip-draggable {
    will-change: transform;
}
.attendance-chip-draggable:active {
    cursor: grabbing;
}
.attendance-chip-draggable.attendance-chip-dragging {
    opacity: 0.5;
    transform: scale(0.9);
}
.attendance-chips .attendance-chip-wrap {
    transition: transform 0.2s ease-out, opacity 0.2s ease-out;
}

/* Educators Attendance: drag-over feedback for Present/Home zones */
.attendance-zone.attendance-zone-dragover {
    border-color: #0984e3 !important;
    background: rgba(9, 132, 227, 0.12) !important;
    box-shadow: inset 0 0 0 3px rgba(9, 132, 227, 0.3);
}

.attendance-box h4 {
    font-size: 16px;
    color: #21304d;
    margin-bottom: 15px;
    font-weight: 600;
}

.attendance-children-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
    gap: 10px;
    flex: 1;
}

.attendance-child-slot {
    width: 80px;
    height: 80px;
    position: relative;
}

.attendance-child-icon {
    width: 70px;
    height: 70px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    font-weight: bold;
    font-size: 16px;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    cursor: pointer;
}

.attendance-child-icon.present {
    background: linear-gradient(135deg, #00b894 0%, #55efc4 100%);
    border: 3px solid #00b894;
}

.attendance-child-icon.picked-up {
    background: #bdc3c7;
    border: 3px solid #95a5a6;
}

.attendance-child-icon.present.completed {
    background: #bdc3c7;
    border-color: #95a5a6;
    opacity: 0.4;
}

.attendance-child-icon .timestamp {
    position: absolute;
    bottom: -18px;
    font-size: 11px;
    color: #7f8c8d;
    font-weight: 500;
    background: #f0f0f0;
    padding: 1px 4px;
    border-radius: 4px;
}

.line-connector {
    position: absolute;
    top: -100%;
    left: 50%;
    transform: translateX(-50%);
    width: 2px;
    height: calc(100% + 15px);
    background-color: #bdc3c7;
    z-index: -1;
}

/* Observation Styles */
.observation-item {
    padding-bottom: 15px;
    margin-bottom: 0;
    border-bottom: 1px solid #ecf0f1;
}

.observation-item:last-of-type {
    border-bottom: none;
    margin-bottom: 0;
}

.observation-question {
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
}

.observation-question-details {
    display: flex;
    align-items: center;
    gap: 10px;
}

.developmental-area-tag {
    font-size: 11px;
    font-weight: normal;
    background-color: #e8f5e8;
    color: #006400;
    padding: 3px 8px;
    border-radius: 10px;
    flex-shrink: 0;
}

.observation-actions {
    display: flex;
    align-items: center;
    gap: 10px;
}

.comment-btn {
    background: #ecf0f1;
    border: none;
    cursor: pointer;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.3s;
    width: 44px;
    height: 44px;
    padding: 0;
}

.comment-btn:hover {
    background-color: #e0e0e0;
}

.comment-btn.active,
.comment-btn.has-comment {
    background-color: #74b9ff;
    border: none;
}

.comment-btn svg {
    width: 24px;
    height: 24px;
    fill: #888;
    transition: fill 0.3s;
}

.comment-btn.active svg,
.comment-btn.has-comment svg {
    fill: white;
}

.comment-box-container {
    display: none;
    margin-top: 15px;
    padding: 15px;
    border: 2px solid #0984e3;
    border-radius: 12px;
    background-color: #f8f9fa;
}

.comment-box-container textarea {
    width: 100%;
    min-height: 80px;
    border: 1px solid #ccc;
    border-radius: 8px;
    padding: 10px;
    resize: vertical;
    font-size: 14px;
    font-family: 'Quicksand', sans-serif;
}

/* Snack/Food Items */
.food-item-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 10px;
}

.food-item-tag {
    background: #e0e0e0;
    padding: 5px 10px;
    border-radius: 15px;
    cursor: pointer;
    transition: background 0.3s;
}

.food-item-tag:hover {
    background: #c7c7c7;
}

.snack-items-container {
    display: flex;
    flex-direction: column;
    gap: 15px;
    margin-top: 15px;
    max-height: 280px;
    overflow-y: auto;
    padding-right: 10px;
}

.snack-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 15px;
    background: #f8f9fa;
    border-radius: 8px;
    border: 1px solid #ecf0f1;
}

.snack-item span {
    font-weight: 500;
    color: #34495e;
    flex: 1;
}

.snack-item .progress-bar-container {
    width: 220px;
    flex-shrink: 0;
    margin-left: 15px;
}

.progress-bar-container {
    display: flex;
    gap: 5px;
    cursor: pointer;
}

.progress-bar-block {
    flex: 1;
    height: 20px;
    background-color: #e0e0e0;
    border-radius: 4px;
    transition: background-color 0.3s ease;
}

.progress-bar-block.active {
    background-color: darksalmon;
}

/* Nap Slider */
.nap-log-container {
    display: flex;
    flex-direction: column;
    gap: 20px;
    height: 100%;
    flex: 1;
    justify-content: space-between;
}

#napVisualizer {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    flex: 1;
    gap: 20px;
    width: 80%;
    margin: 0 auto;
}

.nap-timeline-container {
    width: 100%;
}

.nap-timeline-labels {
    display: flex;
    justify-content: space-between;
    font-size: 12px;
    color: #7f8c8d;
    margin-bottom: 5px;
    padding: 0 10px;
}

.nap-timeline {
    width: 100%;
    height: 20px;
    background-color: #ecf0f1;
    border-radius: 10px;
    position: relative;
}

.nap-duration-bar {
    position: absolute;
    height: 100%;
    background: linear-gradient(135deg, #74b9ff 0%, #0984e3 100%);
    border-radius: 10px;
    cursor: grab;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.nap-duration-bar:active {
    cursor: grabbing;
}

.handle {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background-color: white;
    border: 2px solid #0984e3;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    cursor: ew-resize;
    z-index: 10;
}

.handle.left-handle {
    left: -12px;
}

.handle.right-handle {
    right: -12px;
}

.nap-time-display {
    display: flex;
    gap: 40px;
    font-size: 16px;
    font-weight: 500;
    color: #21304d;
}

/* Health Log Styles */
.symptom-icons {
    display: flex;
    flex-wrap: wrap;
    gap: 15px;
    justify-content: center;
    padding: 10px 0;
}

.symptom-icon {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    cursor: pointer;
    padding: 10px;
    border-radius: 8px;
    transition: background 0.3s;
    width: 80px;
    text-align: center;
}

.symptom-icon:hover {
    background: #f0f0f0;
}

.symptom-icon.selected {
    background: #74b9ff;
    color: white;
}

.symptom-icon .icon {
    font-size: 30px;
}

.symptom-icon .label {
    font-size: 12px;
}

/* Profile Messages View */
.profile-messages-view {
    display: none;
    flex-direction: column;
    gap: 20px;
    flex: 1;
}

.message-history-card {
    background: rgba(255, 255, 255, 0.5);
    border-radius: 15px;
    padding: 20px;
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 10px;
    max-height: 350px;
    overflow-y: auto;
}

.message-item {
    border: 1px solid #dfe6e9;
    border-radius: 12px;
    padding: 15px;
    background: white;
    display: flex;
    align-items: center;
    gap: 15px;
    transition: all 0.3s ease;
    cursor: pointer;
}

.message-item:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0,0,0,0.08);
    border-color: #74b9ff;
}

.message-item.urgent {
    border-left: 4px solid #d63031;
}

.message-icon {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.message-icon.urgent-icon {
    background-color: #ffe8e8;
}

.message-icon.normal-icon {
    background-color: #eef6ff;
}

.message-icon svg {
    width: 20px;
    height: 20px;
}

.message-content {
    flex-grow: 1;
}

.message-sender {
    font-weight: 600;
    color: #21304d;
    font-size: 14px;
    margin-bottom: 3px;
}

.message-sender .relationship {
    font-weight: 400;
    color: #7f8c8d;
    font-size: 12px;
}

.message-date {
    font-size: 12px;
    color: #7f8c8d;
}

.message-text {
    font-size: 13px;
    color: #34495e;
    margin-top: 4px;
}

.message-indicator {
    width: 24px;
    height: 24px;
    flex-shrink: 0;
}

/* Observation View */
.observation-view {
    display: none;
    flex-direction: column;
    gap: 15px;
    padding: 20px;
    background: rgba(255, 255, 255, 0.5);
    border-radius: 15px;
    flex: 1;
    overflow-y: auto;
}

.observation-question-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-bottom: 15px;
    border-bottom: 1px solid #ecf0f1;
}

.observation-question-row:last-child {
    border-bottom: none;
}

.observation-question-row .log-button-group {
    width: auto;
}

.observation-question-row .log-button {
    padding: 8px 18px;
}

.observation-question-row .comment-btn {
    width: 38px;
    height: 38px;
}

.observation-question-row .comment-btn svg {
    width: 20px;
    height: 20px;
}

/* Print-specific styles */
@media print {
    * {
        -webkit-print-color-adjust: exact !important;
        color-adjust: exact !important;
    }

    body.printing {
        overflow: visible !important;
    }

    .print-container {
        page-break-inside: avoid;
    }

    .curriculum-box {
        page-break-inside: avoid;
        margin-bottom: 10px !important;
    }

    .add-note-btn,
    .tag-input-wrapper,
    .tag-add-btn,
    input,
    button:not(.print-button),
    .close-note-modal {
        display: none !important;
    }
}

/* Print button hover effect */
.notification-icon[title="Export PDF"]:hover {
    background: rgba(116, 185, 255, 0.2) !important;
}

/* Photo Gallery Modal Styles */
.photo-gallery-overlay {
    background: rgba(255, 255, 255, 0.8);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    padding-top: 100px;
    align-items: flex-start;
    z-index: 3000;
}

.photo-gallery-modal {
    max-width: 800px !important;
    min-width: 700px !important;
    width: 800px !important;
    height: 80vh !important;
    max-height: 700px !important;
    display: flex;
    flex-direction: column;
    padding: 30px !important;
    position: relative;
}

.gallery-close-btn {
    position: absolute;
    top: 20px;
    right: 20px;
    z-index: 10;
    font-size: 32px;
    background: rgba(255, 255, 255, 0.6);
    width: 40px;
    height: 40px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s ease;
}

.gallery-close-btn:hover {
    background: rgba(255, 255, 255, 0.9);
    transform: scale(1.1);
}

/* Top Bar Filter Styles */
.gallery-topbar-filters {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 0 20px;
    flex: 1;
    justify-content: center;
}

.gallery-title {
    font-size: 18px;
    font-weight: 700;
    margin-right: 15px;
    color: white;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}

.gallery-date-filter,
.gallery-select-filter {
    padding: 8px 14px;
    border: 1px solid rgba(255, 255, 255, 0.5);
    border-radius: 20px;
    font-size: 14px;
    font-family: 'Quicksand', sans-serif;
    font-weight: 600;
    background: rgba(255, 255, 255, 0.25);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    color: white;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
    transition: all 0.2s ease;
    cursor: pointer;
}

.gallery-date-filter {
    min-width: 150px;
}

/* "+" button in the gallery top bar for quick photo upload */
.gallery-add-photo-btn {
    height: 34px;
    width: 34px;
    min-width: 34px;
    padding: 0;
    border-radius: 10px;
    border: 1px solid rgba(255, 255, 255, 0.3);
    background: rgba(255, 255, 255, 0.25);
    color: #ffffff;
    font-size: 22px;
    font-weight: 600;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: 'Quicksand', sans-serif;
    flex-shrink: 0;
    transition: background 0.15s ease, transform 0.1s ease;
}

.gallery-add-photo-btn:hover {
    background: rgba(255, 255, 255, 0.4);
    transform: translateY(-1px);
}

.gallery-add-photo-btn:active {
    transform: translateY(0);
}

.gallery-add-photo-btn span {
    display: block;
    margin-top: -2px;
}

/* Upload progress banner shown above the grid while files are uploading */
.gallery-upload-progress {
    padding: 12px 16px;
    margin: 0 0 16px 0;
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.6);
    border: 1px solid rgba(0, 0, 0, 0.05);
    font-size: 13px;
    color: #34495e;
}

.gallery-upload-progress .upload-progress-text {
    margin-bottom: 8px;
    font-weight: 600;
}

.gallery-select-filter {
    min-width: 140px;
}

.gallery-date-filter::-webkit-calendar-picker-indicator {
    filter: brightness(0) invert(1);
    cursor: pointer;
}

.gallery-date-filter::placeholder,
.gallery-select-filter option {
    color: rgba(255, 255, 255, 0.8);
}

.gallery-select-filter option {
    background: #21304d;
    color: white;
}

.gallery-date-filter:hover,
.gallery-select-filter:hover {
    background: rgba(255, 255, 255, 0.35);
    border-color: rgba(255, 255, 255, 0.7);
    transform: translateY(-1px);
}

.gallery-date-filter:focus,
.gallery-select-filter:focus {
    outline: none;
    background: rgba(255, 255, 255, 0.4);
    border-color: rgba(255, 255, 255, 0.8);
    box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.2);
}

.photo-gallery-body {
    flex: 1;
    overflow: hidden;
}

.photo-grid-container {
    height: 100%;
    overflow-y: auto;
    padding-right: 10px;
}

.photo-grid-container::-webkit-scrollbar {
    width: 8px;
}

.photo-grid-container::-webkit-scrollbar-track {
    background: #f1f3f4;
    border-radius: 4px;
}

.photo-grid-container::-webkit-scrollbar-thumb {
    background: #c1c8cd;
    border-radius: 4px;
}

.photo-grid-container::-webkit-scrollbar-thumb:hover {
    background: #a4acb3;
}

.photos-module .photo-grid, .photo-gallery-modal .photo-grid {
    display: grid;
    grid-template-columns: repeat(5, 1fr) !important;
    gap: 16px !important;
    transition: gap 0.3s ease;
}
@media (max-width: 1280px) {
    .photos-module .photo-grid, .photo-gallery-modal .photo-grid {
        grid-template-columns: repeat(4, 1fr) !important;
    }
}
@media (max-width: 980px) {
    .photos-module .photo-grid, .photo-gallery-modal .photo-grid {
        grid-template-columns: repeat(3, 1fr) !important;
    }
}
@media (max-width: 720px) {
    .photos-module .photo-grid, .photo-gallery-modal .photo-grid {
        grid-template-columns: repeat(2, 1fr) !important;
    }
}

.photos-module .photo-grid.selection-mode, .photo-gallery-modal .photo-grid.selection-mode {
    gap: 10px !important;
}

.photo-tile {
    position: relative;
    aspect-ratio: 1;
    cursor: pointer;
    overflow: hidden;

    /* Hairline frame — drop the padding entirely; the image sits
       edge-to-edge with a 1px border. Inset glass halos previously
       added another ~2px of visible white frame, removed. */
    padding: 0;
    background: rgba(255, 255, 255, 0.35);
    border-radius: 12px;
    border: 1px solid rgba(255, 255, 255, 0.5);
    box-shadow: 0 4px 14px 0 rgba(31, 38, 135, 0.08);

    transition: all 0.3s ease;
}

.photo-tile:hover {
    transform: translateY(-4px) scale(1.02);
    box-shadow:
        0 12px 40px 0 rgba(31, 38, 135, 0.2),
        inset 0 0 0 1px rgba(255, 255, 255, 0.7),
        inset 0 0 20px rgba(255, 255, 255, 0.4);
}

.photo-tile-image {
    width: 100%;
    height: 100%;
    background-size: cover;
    background-position: center;
    background-color: #e0e0e0;
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.photo-tile-caption {
    position: absolute;
    bottom: 12px;
    left: 12px;
    right: 12px;
    padding: 8px 12px;
    background: rgba(33, 48, 77, 0.85);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    color: white;
    font-size: 12px;
    border-radius: 8px;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Photo Selection Styles */
.photo-tile.selected {
    border: 3px solid #46cfc0;
    box-shadow:
        0 0 0 2px rgba(70, 207, 192, 0.2),
        0 12px 40px 0 rgba(31, 38, 135, 0.2),
        inset 0 0 0 1px rgba(255, 255, 255, 0.7),
        inset 0 0 20px rgba(255, 255, 255, 0.4);
}

.photo-tile.selected:hover {
    transform: translateY(-2px) scale(1.01);
}

/* Per-tile tag chip — bottom-left overlay on photo grid tiles.
   Shows tagged children's first names ("Carter, Lucas +2"). Compact +
   semi-transparent so it floats over the photo content without
   competing. Hover-only on idle tiles to keep the grid quiet; always
   visible in selection mode so admin can scan tags fast while
   choosing recipients. Empty when photo has no child tags — chip is
   hidden in markup via x-if so the rule below only paints when the
   chip exists. */
.photo-tile-tag-chip {
    position: absolute;
    bottom: 8px;
    left: 8px;
    max-width: calc(100% - 56px);
    padding: 3px 9px;
    border-radius: 999px;
    /* Translucent frosted-glass — drop alpha further (0.32 → 0.18)
       so the photo content reads clearly through the chip. Stronger
       blur + saturate compensates so text remains legible against
       busy photo backgrounds; heavier text-shadow as a safety net. */
    background: rgba(15, 23, 42, 0.18);
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    line-height: 1.4;
    letter-spacing: 0.01em;
    backdrop-filter: blur(14px) saturate(1.5);
    -webkit-backdrop-filter: blur(14px) saturate(1.5);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6), 0 0 4px rgba(0, 0, 0, 0.4);
    pointer-events: none;
    z-index: 5;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    opacity: 0;
    transition: opacity 0.18s ease;
}
.photo-tile:hover .photo-tile-tag-chip,
.photos-module .photo-grid.selection-mode .photo-tile-tag-chip, .photo-gallery-modal .photo-grid.selection-mode .photo-tile-tag-chip,
.photo-tile.selected .photo-tile-tag-chip {
    opacity: 1;
}

/* Photo Tile Checkbox */
.photo-tile-checkbox {
    position: absolute;
    top: 16px;
    left: 16px;
    z-index: 10;
    opacity: 0;
    transition: opacity 0.2s ease;
    background: white;
    border-radius: 50%;
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}

/* Only show checkbox in selection mode or when actually selected */
.photos-module .photo-grid.selection-mode .photo-tile-checkbox, .photo-gallery-modal .photo-grid.selection-mode .photo-tile-checkbox,
.photo-tile-checkbox.visible {
    opacity: 1;
}

/* Photo Tile Select Icon */
.photo-tile-select-icon {
    position: absolute;
    top: 16px;
    right: 16px;
    z-index: 10;
    opacity: 0;
    transition: all 0.2s ease;
    background: rgba(150, 150, 150, 0.6);
    backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px);
    border-radius: 50%;
    width: 34px;
    height: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}
/* Reveal-on-hover, mirrors .docs-card-select-icon. Selected tiles
   keep the chip visible regardless of hover so the selection state
   is always legible. */
.photo-tile:hover .photo-tile-select-icon,
.photo-tile.selected .photo-tile-select-icon {
    opacity: 1;
}
/* Invisible hit-area extension — keeps the visible bubble at 34×34
   but expands the clickable region to ~62×62 so taps near the
   corner don't slip past the bubble and trigger the lightbox. */
.photo-tile-select-icon::before {
    content: '';
    position: absolute;
    inset: -14px;
    border-radius: 50%;
}

.photo-tile-select-icon iconify-icon {
    color: white;
    opacity: 0.8;
}

.photo-tile-select-icon:hover {
    background: rgba(150, 150, 150, 0.8);
    transform: scale(1.1);
}

/* Selected photo icon - bright turquoise */
.photo-tile.selected .photo-tile-select-icon {
    opacity: 1;
    background: rgba(70, 207, 192, 1);
}

.photo-tile.selected .photo-tile-select-icon iconify-icon {
    opacity: 1;
}

.photo-tile.selected .photo-tile-select-icon:hover {
    background: rgba(70, 207, 192, 1);
    transform: scale(1.1);
}

/* Gallery Selection Controls */
.gallery-selection-controls,
.gallery-filter-controls {
    display: flex;
    align-items: center;
    gap: 12px;
}

/* Tablet: the 5-button selection toolbar (Back / Select All / Send / Delete /
   Clear) teleports into the fixed-width tablet flex-bar (~471px clamp, which
   does NOT grow to content). Even with the module label hidden the last button
   overflowed the pill by ~24px. Tighten inter-button gap + horizontal padding
   so all five sit inside the bar (audit 2026-07-16). The flex-bar is outside
   the module zoom — this is chrome tuning, not a double-shrink. */
html[data-ui-mode="tablet"] .gallery-selection-controls {
    gap: 8px;
}
html[data-ui-mode="tablet"] .gallery-selection-controls > button {
    padding-left: 14px;
    padding-right: 14px;
}

.gallery-back-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 16px;
    border: 1px solid rgba(255, 255, 255, 0.5);
    border-radius: 20px;
    font-size: 14px;
    font-family: 'Quicksand', sans-serif;
    font-weight: 600;
    background: rgba(255, 255, 255, 0.25);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    color: white;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
    transition: all 0.2s ease;
    cursor: pointer;
}

.gallery-back-btn:hover {
    background: rgba(255, 255, 255, 0.35);
    border-color: rgba(255, 255, 255, 0.7);
    transform: translateY(-1px);
}

.gallery-select-all-btn {
    padding: 8px 16px;
    border: 1px solid rgba(255, 255, 255, 0.5);
    border-radius: 20px;
    font-size: 14px;
    font-family: 'Quicksand', sans-serif;
    font-weight: 600;
    background: rgba(255, 255, 255, 0.25);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    color: white;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
    transition: all 0.2s ease;
    cursor: pointer;
}

.gallery-select-all-btn:hover:not(:disabled) {
    background: rgba(255, 255, 255, 0.35);
    border-color: rgba(255, 255, 255, 0.7);
    transform: translateY(-1px);
}

.gallery-select-all-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.gallery-selected-count {
    padding: 8px 16px;
    border-radius: 20px;
    font-size: 14px;
    font-weight: 600;
    background: rgba(70, 207, 192, 0.9);
    color: white;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
}

.gallery-actions-dropdown-wrapper {
    position: relative;
}

.gallery-actions-btn {
    padding: 8px 16px;
    border: 1px solid rgba(255, 255, 255, 0.5);
    border-radius: 20px;
    font-size: 14px;
    font-family: 'Quicksand', sans-serif;
    font-weight: 600;
    background: rgba(255, 255, 255, 0.25);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    color: white;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
    transition: all 0.2s ease;
    cursor: pointer;
}

.gallery-actions-btn:hover {
    background: rgba(255, 255, 255, 0.35);
    border-color: rgba(255, 255, 255, 0.7);
    transform: translateY(-1px);
}

.gallery-actions-dropdown {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    background: white;
    border-radius: 12px;
    box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
    padding: 8px;
    z-index: 1001;
    min-width: 160px;
    border: 1px solid rgba(0, 0, 0, 0.05);
}

.gallery-action-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    border-radius: 8px;
    cursor: pointer;
    transition: all 0.2s ease;
    color: #21304d;
    font-size: 14px;
    font-weight: 500;
    background: transparent;
    border: none;
    width: 100%;
    text-align: left;
    font-family: 'Quicksand', sans-serif;
}

.gallery-action-item:hover {
    background: #f8f9fa;
}

.gallery-action-item.delete:hover {
    background: #ffe8e8;
    color: #d63031;
}

.gallery-action-item.delete:hover iconify-icon {
    color: #d63031;
}

.gallery-clear-selection-btn {
    padding: 8px 16px;
    border: 1px solid rgba(255, 255, 255, 0.5);
    border-radius: 20px;
    font-size: 14px;
    font-family: 'Quicksand', sans-serif;
    font-weight: 600;
    background: rgba(255, 255, 255, 0.25);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    color: white;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
    transition: all 0.2s ease;
    cursor: pointer;
}

.gallery-clear-selection-btn:hover {
    background: rgba(255, 255, 255, 0.35);
    border-color: rgba(255, 255, 255, 0.7);
    transform: translateY(-1px);
}

/* Gallery States */
.gallery-loading-state,
.gallery-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    color: #7f8c8d;
}

.gallery-empty-state h3 {
    margin: 15px 0 10px 0;
    color: #21304d;
    font-size: 20px;
}

.gallery-empty-state p {
    color: #7f8c8d;
    font-size: 14px;
    max-width: 400px;
    text-align: center;
    line-height: 1.6;
}

.loading-spinner {
    width: 50px;
    height: 50px;
    border: 4px solid #f3f3f3;
    border-top: 4px solid #0984e3;
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

.gallery-loading-more {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 20px;
    color: #7f8c8d;
    font-size: 14px;
}

.loading-spinner-small {
    width: 20px;
    height: 20px;
    border: 3px solid #f3f3f3;
    border-top: 3px solid #0984e3;
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
}

.gallery-end-message {
    text-align: center;
    padding: 20px;
    color: #7f8c8d;
    font-size: 14px;
    font-style: italic;
}

/* ── Generic CSS-managed tooltip (.has-tip + data-tip="...") ───────────
   Replaces native `title=""` everywhere we want a predictable show-
   on-hover / hide-on-leave bubble. Native tooltips can stick when an
   element repaints or hides under a modal mid-hover — this :hover-
   driven recipe vanishes the moment the cursor leaves the host.
   Was scoped to messaging.css; moved here so it's available on every
   page, not just after the messaging module first mounts. */
.has-tip {
    cursor: default;
    /* Anchor for the ::after tooltip — without this, the absolute-
       positioned tooltip resolves up to the nearest positioned
       ancestor, which on header icons is the body and renders
       wherever the cursor last was. */
    position: relative;
}
.has-tip::after {
    content: attr(data-tip);
    position: absolute;
    bottom: calc(100% + 8px);
    right: 0;
    transform: translateY(2px);
    background: #1e293b;
    color: #fff;
    font-size: 12px;
    font-weight: 500;
    line-height: 1.3;
    padding: 6px 10px;
    border-radius: 6px;
    white-space: nowrap;
    max-width: 320px;
    overflow: hidden;
    text-overflow: ellipsis;
    pointer-events: none;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.12s ease, transform 0.12s ease;
    z-index: 100;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
}
.has-tip:hover::after {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

/* Tooltip position-below modifier — for hosts where above-the-anchor
   would clip against the viewport top (notification icons in the
   header sit ~12px from the top edge; the default upward tooltip
   gets cut off by the browser chrome). Apply via:
       <div class="has-tip has-tip--below" data-tip="...">
   or scope by parent (see `.notifications .has-tip` below). */
.has-tip.has-tip--below::after,
.notifications .has-tip::after {
    bottom: auto;
    top: calc(100% + 8px);
    transform: translateY(-2px);
}

/* Wide / multi-line tooltip modifier — for explanatory tips longer
   than the ~30-char default fits on one line. Lets text wrap, bumps
   max-width so the popover has room to read. Apply via:
       <div class="has-tip has-tip--wide" data-tip="long explanation…"> */
.has-tip.has-tip--wide::after {
    white-space: normal;
    max-width: 360px;
    width: max-content;
    text-overflow: clip;
    overflow: visible;
    line-height: 1.4;
    padding: 8px 12px;
}
.has-tip.has-tip--below:hover::after,
.notifications .has-tip:hover::after {
    transform: translateY(0);
}

/* Left-anchored variant — tooltip extends rightward from the anchor.
   Use when the host sits near the left edge of an overflow:hidden container
   and the default right-anchored tooltip would be clipped. */
.has-tip.has-tip--start::after {
    right: auto;
    left: 0;
}
.has-tip.has-tip--below.has-tip--start::after {
    right: auto;
    left: 0;
}

/* Photo Lightbox / editor workspace
   Full-viewport: photo canvas on the left, tagging rail docked flush
   to the right edge. Stage shrink-wraps the image so face circles share
   the same coordinate origin as the painted photo. */
.lightbox-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(208, 212, 222, 0.78);
    backdrop-filter: blur(28px) saturate(1.3);
    -webkit-backdrop-filter: blur(28px) saturate(1.3);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 3000;
    padding: 50px 40px 30px 40px;
}

.lightbox-overlay--editor {
    align-items: stretch;
    justify-content: stretch;
    /* Clear the fixed header (container pad + header row) so the
       filmstrip / photo / tagging rail start on the same upper line
       as normal module content below the flex bar — not under it. */
    padding: 96px 20px 20px 16px;
    background: rgba(45, 55, 72, 0.55);
    backdrop-filter: blur(22px) saturate(1.2);
    -webkit-backdrop-filter: blur(22px) saturate(1.2);
    box-sizing: border-box;
}

.lightbox-workspace {
    display: flex;
    flex: 1 1 auto;
    width: 100%;
    height: 100%;
    min-height: 0;
    min-width: 0;
    gap: 14px;
}

/* Left markup panel — mirrors right tagging rail (~300px) so the
   photo stays centered. Tools: text / arrow / box / pen. */
.lightbox-markup-panel {
    flex: 0 0 300px;
    width: 300px;
    height: 100%;
    max-height: 100%;
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 18px 16px 14px;
    background: rgba(255, 255, 255, 0.94);
    backdrop-filter: blur(18px) saturate(1.15);
    -webkit-backdrop-filter: blur(18px) saturate(1.15);
    border: 1px solid rgba(255, 255, 255, 0.55);
    border-radius: 16px;
    box-shadow: 0 10px 32px rgba(0, 0, 0, 0.14);
    color: #2c3e50;
    box-sizing: border-box;
    min-height: 0;
    overflow-y: auto;
}
.lightbox-markup-panel__title {
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #4a5568;
}
.lightbox-markup-panel__hint {
    margin: 0;
    font-size: 12.5px;
    line-height: 1.4;
    color: #5b6b7b;
}
.lightbox-markup-panel__section {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #718096;
    margin-top: 4px;
}
.lightbox-markup-tools {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
}
.lightbox-markup-tool {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 10px 6px;
    border: 1.5px solid #cbd5e0;
    border-radius: 10px;
    background: #fff;
    color: #2d3748;
    font-size: 11px;
    font-weight: 700;
    font-family: inherit;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.lightbox-markup-tool:hover {
    border-color: #2d9cdb;
    background: rgba(45, 156, 219, 0.08);
}
.lightbox-markup-tool.active {
    border-color: #1a365d;
    background: #1a365d;
    color: #fff;
}
.lightbox-markup-swatches {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.lightbox-markup-swatch {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 2px solid rgba(0, 0, 0, 0.15);
    cursor: pointer;
    padding: 0;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.35);
}
.lightbox-markup-swatch.active {
    border-color: #1a365d;
    box-shadow: 0 0 0 2px rgba(26, 54, 93, 0.35);
}
.lightbox-markup-stroke {
    display: flex;
    border: 1.5px solid #2d3748;
    border-radius: 8px;
    overflow: hidden;
}
.lightbox-markup-stroke-btn {
    flex: 1;
    border: none;
    background: #f7fafc;
    padding: 7px 4px;
    font-size: 12px;
    font-weight: 700;
    font-family: inherit;
    color: #1a202c;
    cursor: pointer;
}
.lightbox-markup-stroke-btn + .lightbox-markup-stroke-btn {
    border-left: 1.5px solid #2d3748;
}
.lightbox-markup-stroke-btn.active {
    background: #1a365d;
    color: #fff;
}
.lightbox-markup-panel__actions {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: auto;
    padding-top: 8px;
}
.lightbox-markup-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8px 10px;
    border: 1px solid #cbd5e0;
    border-radius: 8px;
    background: #fff;
    color: #2d3748;
    font-size: 13px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
}
.lightbox-markup-action:hover:not(:disabled) {
    border-color: #c0392b;
    color: #c0392b;
}
.lightbox-markup-action:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}
.lightbox-markup-panel__count {
    margin: 0;
    font-size: 12px;
    color: #718096;
    text-align: center;
}

/* Flex bar undo/redo while the photo editor is open */
.flex-bar-markup-history {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    margin-left: 8px;
}
/* Lightbox editor: drop the date filter (not an editor action) so
   Send / Undo stay inside the current pill. Do not replace the bar. */
.flex-bar--photo-editor .gallery-filter-controls {
    display: none;
}
.flex-bar-markup-history-btn {
    font-family: inherit;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 6px 10px;
    border-radius: 10px;
    border: 1px solid rgba(255, 255, 255, 0.45);
    background: rgba(255, 255, 255, 0.14);
    color: #fff;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s ease, opacity 0.15s ease;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
}
.flex-bar-markup-history-btn:hover:not(:disabled) {
    background: rgba(255, 255, 255, 0.24);
}
.flex-bar-markup-history-btn:disabled {
    opacity: 0.42;
    cursor: not-allowed;
}

/* Text label popover — reuses .center-dropdown glass from app-modules.css */
.markup-text-popover {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px !important;
}
.markup-text-popover__label {
    font-size: 12px;
    font-weight: 700;
    color: #4a5568;
    letter-spacing: 0.02em;
    text-transform: uppercase;
}
.markup-text-popover__input {
    width: 100%;
    box-sizing: border-box;
    padding: 9px 11px;
    border: 1px solid rgba(33, 48, 77, 0.12);
    border-radius: 12px;
    font-size: 14px;
    font-family: inherit;
    color: #21304d;
    background: rgba(255, 255, 255, 0.92);
}
.markup-text-popover__input:focus {
    outline: none;
    border-color: rgba(116, 185, 255, 0.85);
    box-shadow: 0 0 0 3px rgba(116, 185, 255, 0.18);
}
.markup-text-popover__actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 2px;
}
.markup-text-popover__btn {
    font-family: inherit;
    padding: 7px 12px;
    border-radius: 10px;
    border: none;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    background: rgba(255, 255, 255, 0.45);
    color: #4a5568;
    transition: background 0.15s ease;
}
.markup-text-popover__btn:hover {
    background: rgba(255, 255, 255, 0.7);
}
.markup-text-popover__btn--primary {
    background: linear-gradient(135deg, rgba(116, 185, 255, 0.92) 0%, rgba(9, 132, 227, 0.92) 100%);
    color: #fff;
    box-shadow: 0 2px 6px rgba(9, 132, 227, 0.25);
}
.markup-text-popover__btn--primary:hover {
    background: linear-gradient(135deg, rgba(116, 185, 255, 1) 0%, rgba(9, 132, 227, 1) 100%);
}

.photo-markup-layer {
    position: absolute;
    display: block;
    pointer-events: none; /* Tag mode: clicks pass through to face layer */
    z-index: 5;
    touch-action: none;
}
.photo-markup-layer.active {
    pointer-events: auto;
    cursor: crosshair;
}
.face-tag-layer--behind {
    z-index: 2;
    pointer-events: none !important; /* don't steal markup drags */
}
.lightbox-stage.markup-mode {
    cursor: crosshair;
}

.lightbox-main {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
    display: flex;
    align-items: stretch;
    justify-content: center;
    padding: 8px 4px;
    box-sizing: border-box;
}
/* Empty gutters beside the photo are clickable prev/next zones */
.lightbox-main--nav-prev,
.lightbox-main--nav-next {
    cursor: pointer;
}
.lightbox-main .lightbox-stage,
.lightbox-main .lightbox-close {
    cursor: default;
}
.lightbox-main .lightbox-stage.tag-mode {
    cursor: crosshair;
}
.lightbox-main .lightbox-caption-bar,
.lightbox-main .lightbox-caption-bar__input {
    cursor: text;
}

/* Full width of the center column so the caption bar doesn't shrink
   with portrait photos or grow with landscape ones. */
.lightbox-stage-wrap {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    width: 100%;
    max-width: 100%;
    height: 100%;
    max-height: 100%;
    min-width: 0;
    min-height: 0;
}
/* Centers the shrink-wrapped photo stage in the space above the caption. */
.lightbox-stage-center {
    flex: 1 1 auto;
    min-height: 0;
    min-width: 0;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}

.lightbox-caption-bar {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 100%;
    padding: 10px 12px;
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.82);
    border: 1px solid rgba(255, 255, 255, 0.5);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
    box-sizing: border-box;
}
.lightbox-caption-bar__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 14px;
    font-size: 12.5px;
    font-weight: 600;
    color: #4a5568;
}
.lightbox-caption-bar__input {
    width: 100%;
    box-sizing: border-box;
    resize: vertical;
    min-height: 88px;
    max-height: 192px;
    padding: 8px 10px;
    border: 1px solid #e2e8f0;
    border-radius: 8px;
    font-size: 13.5px;
    font-family: inherit;
    background: #fff;
    color: #2c3e50;
}
.lightbox-caption-bar__input:focus {
    outline: none;
    border-color: #74b9ff;
    box-shadow: 0 0 0 3px rgba(116, 185, 255, 0.12);
}

/* Legacy centred card (kept for any non-editor lightbox callers) */
.lightbox-content {
    position: relative;
    max-width: calc(90vw - 80px);
    max-height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 7.5px;
}

/* Tablet: stack rail under the photo; keep usable height budgets. */
html[data-ui-mode="tablet"] .lightbox-overlay:not(.lightbox-overlay--editor) {
    align-items: flex-start;
    overflow-y: auto;
    padding: 88px 24px 20px;
}
html[data-ui-mode="tablet"] .lightbox-overlay--editor {
    overflow-y: auto;
    align-items: flex-start;
    /* 10px container + 60px header + slack. 5vh is only ~38–40px on
       the 1024×768 / 1280×800 tablet-mode repros and let the bar
       sit on the workspace. */
    padding: 96px 14px 14px;
}
html[data-ui-mode="tablet"] .flex-bar--photo-editor {
    overflow: hidden;
}
html[data-ui-mode="tablet"] .flex-bar--photo-editor .flex-bar-markup-history {
    margin-left: 0;
    gap: 4px;
}
html[data-ui-mode="tablet"] .flex-bar--photo-editor .flex-bar-markup-history-btn {
    padding: 5px 8px;
}
html[data-ui-mode="tablet"] .lightbox-workspace {
    flex-direction: column;
    height: auto;
    min-height: calc(100vh - 110px);
}
html[data-ui-mode="tablet"] .lightbox-markup-panel {
    flex: 0 0 auto;
    width: 100%;
    max-width: none;
    height: auto;
    max-height: none;
}
html[data-ui-mode="tablet"] .lightbox-main {
    padding: 4px 0;
    min-height: 280px;
}
html[data-ui-mode="tablet"] .lightbox-image {
    max-height: 42vh;
}
html[data-ui-mode="tablet"] .lightbox-tag-rail {
    flex: 0 0 auto;
    width: 100%;
    max-width: none;
    height: auto;
    max-height: none;
}

.lightbox-close {
    position: absolute;
    top: 16px;
    right: 16px;
    width: 40px;
    height: 40px;
    background: rgba(255, 255, 255, 0.55);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(0, 0, 0, 0.12);
    border-radius: 50%;
    color: #2c3e50;
    font-size: 28px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s ease, transform 0.2s ease;
    line-height: 1;
    padding: 0;
    z-index: 2;
}

.lightbox-close:hover {
    background: rgba(255, 255, 255, 0.85);
    transform: scale(1.06);
}

.lightbox-image {
    display: block;
    max-width: 100%;
    /* Header clearance + overlay bottom pad + taller caption bar + gaps */
    max-height: calc(100vh - 340px);
    width: auto;
    height: auto;
    border-radius: 10px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.28);
    object-fit: contain;
    border: 1px solid rgba(255, 255, 255, 0.25);
    flex-shrink: 0;
    user-select: none;
}

/* Stage shrink-wraps the image — face-tag-layer must share this box so
   circle left/top map onto painted pixels (not a taller stretched parent). */
.lightbox-stage {
    position: relative;
    display: block;
    width: fit-content;
    max-width: 100%;
    max-height: 100%;
    margin: 0;
    line-height: 0;
    flex: 0 1 auto;
    min-height: 0;
}
.lightbox-stage.tag-mode { cursor: crosshair; }

.face-tag-layer {
    position: absolute;
    inset: 0;
    touch-action: none;   /* pointer drag draws, doesn't scroll/zoom */
}
.face-tag-layer--drop {
    /* HTML5 drop target — show the stage is ready for a child name */
    outline: 2px dashed rgba(45, 156, 219, 0.55);
    outline-offset: -4px;
    border-radius: 10px;
    background: rgba(45, 156, 219, 0.06);
}

.face-tag-circle {
    position: absolute;
    box-sizing: border-box;
    border: 2px solid rgba(45, 156, 219, 0.95);   /* confirmed/manual = solid blue */
    border-radius: 50%;
    background: rgba(45, 156, 219, 0.08);
    cursor: grab;
    transition: border-color 0.15s, background 0.15s;
}
/* Hard hide — :style geometry binding replaces the style attr and would
   otherwise defeat Alpine x-show's display:none. */
.face-tag-circle.face-tag-circle--hidden {
    display: none !important;
    visibility: hidden !important;
    pointer-events: none !important;
}
.face-tag-circle.suggested {                       /* AI-suggested = dashed amber */
    border-style: dashed;
    border-color: rgba(243, 156, 18, 0.95);
    background: rgba(243, 156, 18, 0.10);
}
.face-tag-circle.active {
    border-width: 3px;
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.7), 0 2px 10px rgba(0, 0, 0, 0.25);
    cursor: grabbing;
    z-index: 3;
}
.face-tag-circle.drop-target {
    border-color: rgba(39, 174, 96, 0.95);
    background: rgba(39, 174, 96, 0.18);
    box-shadow: 0 0 0 3px rgba(39, 174, 96, 0.35);
    z-index: 4;
}
/* Proximity-revealed circles fade in under a dragged name */
.face-tag-layer--drop .face-tag-circle {
    animation: face-tag-reveal 0.16s ease-out;
}
@keyframes face-tag-reveal {
    from { opacity: 0; transform: scale(0.85); }
    to { opacity: 1; transform: scale(1); }
}
.face-tag-circle.forced {                          /* force-blur = solid slate + hatch */
    border-color: rgba(71, 85, 105, 0.95);
    background: repeating-linear-gradient(
        45deg,
        rgba(71, 85, 105, 0.18) 0 6px,
        rgba(71, 85, 105, 0.06) 6px 12px);
}

.face-tag-pin {
    position: absolute;
    left: 50%;
    bottom: -22px;
    transform: translateX(-50%);
    white-space: nowrap;
    font-size: 11px;
    font-weight: 600;
    color: #fff;
    background: rgba(45, 156, 219, 0.95);
    padding: 1px 7px;
    border-radius: 8px;
    pointer-events: none;
}
.face-tag-pin--suggested { background: rgba(243, 156, 18, 0.95); }

.face-tag-handle {
    position: absolute;
    right: -7px;
    bottom: -7px;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: #fff;
    border: 2px solid rgba(45, 156, 219, 0.95);
    cursor: nwse-resize;
}

/* Right tagging rail — inset card, mirrors the left filmstrip width balance */
.lightbox-tag-rail {
    flex: 0 0 300px;
    width: 300px;
    height: 100%;
    max-height: 100%;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 18px 16px 14px;
    background: rgba(255, 255, 255, 0.94);
    backdrop-filter: blur(18px) saturate(1.15);
    -webkit-backdrop-filter: blur(18px) saturate(1.15);
    border: 1px solid rgba(255, 255, 255, 0.55);
    border-radius: 16px;
    box-shadow: 0 10px 32px rgba(0, 0, 0, 0.14);
    color: #2c3e50;
    box-sizing: border-box;
    min-height: 0;
    z-index: 1;
}
.lightbox-tag-rail__section-label {
    font-size: 12px;
    font-weight: 700;
    color: #4a5568;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    flex-shrink: 0;
}
.lightbox-tag-rail__hint {
    margin: 0;
    font-size: 12.5px;
    line-height: 1.4;
    color: #5b6b7b;
    flex-shrink: 0;
}
.lightbox-tag-rail__list {
    flex: 1 1 auto;
    min-height: 120px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding: 2px;
    margin: 0 -4px;
    border-radius: 8px;
    background: rgba(247, 250, 252, 0.7);
}
.lightbox-tag-rail .tag-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 8px;
    border-radius: 8px;
    font-size: 13.5px;
    color: #2d3748;
    user-select: none;
}
.lightbox-tag-rail .tag-item:hover {
    background: rgba(116, 185, 255, 0.14);
}
.lightbox-tag-rail .tag-item--pending {
    background: rgba(45, 156, 219, 0.16);
    box-shadow: inset 0 0 0 1.5px rgba(45, 156, 219, 0.55);
}
.lightbox-tag-rail .tag-item--previewing {
    background: rgba(26, 54, 93, 0.08);
    box-shadow: inset 0 0 0 1.5px rgba(26, 54, 93, 0.45);
}
.lightbox-tag-rail__check {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1 1 auto;
    min-width: 0;
    cursor: pointer;
}
.lightbox-tag-rail .tag-item input[type="checkbox"] {
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    accent-color: #2d9cdb;
    cursor: pointer;
}
.lightbox-tag-rail__name {
    flex: 1;
    min-width: 0;
    cursor: grab;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.lightbox-tag-rail__name:active {
    cursor: grabbing;
}
.lightbox-tag-rail .tag-item--dragging {
    opacity: 0.45;
}
.lightbox-tag-rail .tag-item--opt-out {
    background: rgba(192, 57, 43, 0.06);
}
.lightbox-tag-rail .tag-item--opt-out.tag-item--pending {
    background: rgba(45, 156, 219, 0.16);
}

/* Per-child Family / Others preview (tagged + opted-out only) */
.lightbox-tag-rail__preview {
    flex-shrink: 0;
    display: inline-flex;
    border: 1.5px solid #2d3748;
    border-radius: 7px;
    overflow: hidden;
    background: #f7fafc;
}
.lightbox-tag-rail__preview-btn {
    border: none;
    background: #f7fafc;
    padding: 4px 7px;
    font-size: 11px;
    font-weight: 700;
    font-family: inherit;
    color: #1a202c;
    cursor: pointer;
    line-height: 1.2;
}
.lightbox-tag-rail__preview-btn + .lightbox-tag-rail__preview-btn {
    border-left: 1.5px solid #2d3748;
}
.lightbox-tag-rail__preview-btn:hover:not(:disabled):not(.active) {
    background: #edf2f7;
}
.lightbox-tag-rail__preview-btn.active {
    background: #1a365d;
    color: #ffffff;
}
.lightbox-tag-rail__preview-btn:disabled {
    cursor: wait;
}
.lightbox-image--preview {
    box-shadow: 0 0 0 3px rgba(26, 54, 93, 0.5), 0 12px 40px rgba(0, 0, 0, 0.28);
}
.lightbox-tag-rail__active {
    flex-shrink: 0;
    padding-top: 10px;
    border-top: 1px solid rgba(0, 0, 0, 0.08);
}
/* "Who sees what" — the per-child sharing summary rendered by app.js
   photoSharing(), sitting at the foot of the tag rail.

   Colour carries EMPHASIS ONLY. Every state is also spelled out in words,
   because the distinction is a consent fact rather than a severity, and
   colour alone survives neither a colour-blind reader nor a screenshot
   pasted into a compliance thread.

   Sizing: the rail is a fixed-height flex column whose __list is
   `flex: 1 1 auto; min-height: 120px`. Left unbounded this panel would
   push the list to that 120px floor and then overflow the rail, so it is
   capped and scrolls internally instead. min-height:0 is required or a
   flex child refuses to shrink below its content. */
.lightbox-sharing {
    /* 0 0 auto, NOT 0 1 auto. The sibling __list is `flex: 1 1 auto`, so if
       this panel is allowed to shrink the list wins every time: with a full
       roster above it (85 children on the verification org) it collapsed to
       43px, which still measures as "inside the viewport" because the BOX
       fits -- the content was clipped inside the overflow. Let the list
       shrink toward its 120px floor instead; it already scrolls. */
    flex: 0 0 auto;
    min-height: 0;
    max-height: 38%;
    overflow-y: auto;
    padding-top: 10px;
    margin-bottom: 2px;
    border-top: 1px solid rgba(0, 0, 0, 0.06);
}

.lightbox-sharing-title {
    font-weight: 600;
    margin-bottom: 4px;
}

.lightbox-sharing-row {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
    font-size: 14px;
    line-height: 1.5;
}

.lightbox-sharing-name {
    font-weight: 500;
}

.lightbox-sharing-state--shared {
    color: #4a7c59;
}

.lightbox-sharing-state--others,
.lightbox-sharing-state--everyone {
    color: #a05a2c;
}

.lightbox-sharing-summary {
    margin-top: 6px;
    font-size: 13px;
    line-height: 1.5;
    opacity: 0.75;
}

.lightbox-tag-rail__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    flex-shrink: 0;
    padding-top: 10px;
    border-top: 1px solid rgba(0, 0, 0, 0.06);
    background: transparent;
}
.lightbox-tag-rail__actions .lightbox-edit-btn {
    flex: 1 1 auto;
    justify-content: center;
}

.lightbox-tag-assign__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
}
.lightbox-tag-assign__label { font-weight: 600; font-size: 13px; }
.lightbox-tag-del {
    background: none; border: none; color: #c0392b;
    cursor: pointer; padding: 4px; border-radius: 6px;
}
.lightbox-tag-del:hover { background: rgba(192, 57, 43, 0.1); }
.lightbox-tag-clear {
    margin-top: 8px;
    background: none; border: none;
    color: #5b6b7b; font-size: 13px;
    cursor: pointer; text-decoration: underline;
}
.lightbox-tag-consent-hint {
    margin: 6px 0 8px;
    font-size: 12.5px;
    line-height: 1.35;
    color: #8a6d1a;
}
.lightbox-tag-consent-hint--ok {
    color: #1e8449;
}
.lightbox-tag-forceblur {
    display: block;
    width: 100%;
    margin-top: 10px;
    padding: 7px 10px;
    border: 1px solid rgba(71, 85, 105, 0.4);
    border-radius: 8px;
    background: rgba(71, 85, 105, 0.06);
    color: #334155;
    font-size: 13px;
    cursor: pointer;
}
.lightbox-tag-forceblur.active {
    background: rgba(71, 85, 105, 0.85);
    border-color: rgba(71, 85, 105, 0.85);
    color: #ffffff;
}
.lightbox-edit-btn--done {
    background: rgba(39, 174, 96, 0.12);
    border-color: rgba(39, 174, 96, 0.5);
    color: #1e8449;
}
.lightbox-edit-btn--done:hover {
    background: rgba(39, 174, 96, 0.2);
    border-color: rgba(39, 174, 96, 0.7);
}

.lightbox-info {
    margin-top: 20px;
    padding: 20px 30px;
    background: rgba(255, 255, 255, 0.35);
    backdrop-filter: blur(12px) saturate(1.2);
    -webkit-backdrop-filter: blur(12px) saturate(1.2);
    border: 1px solid rgba(255, 255, 255, 0.5);
    border-radius: 12px;
    color: #2c3e50;
    width: 100%;
    max-width: 600px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
    
    /* Add scrolling instead of clipping */
    max-height: 250px;
    overflow-y: auto;
    flex-shrink: 1;
}

/* Custom scrollbar styling for lightbox info */
.lightbox-info::-webkit-scrollbar {
    width: 6px;
}

.lightbox-info::-webkit-scrollbar-track {
    background: rgba(0, 0, 0, 0.05);
    border-radius: 3px;
}

.lightbox-info::-webkit-scrollbar-thumb {
    background: rgba(0, 0, 0, 0.2);
    border-radius: 3px;
}

.lightbox-info::-webkit-scrollbar-thumb:hover {
    background: rgba(0, 0, 0, 0.3);
}

.lightbox-info-row {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    margin-bottom: 12px;
    font-size: 15px;
    line-height: 1.6;
}

.lightbox-info-row:last-child {
    margin-bottom: 0;
}

/* Legacy lightbox action row (kept for any remaining callers). */
.lightbox-info-actions {
    margin-top: 4px;
    padding-top: 12px;
    border-top: 1px solid rgba(0, 0, 0, 0.08);
    display: flex;
    justify-content: center;
    gap: 10px;
}
.lightbox-edit-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 14px;
    border-radius: 16px;
    border: 1px solid rgba(99, 102, 241, 0.4);
    background: rgba(99, 102, 241, 0.06);
    color: #4f46e5;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.lightbox-edit-btn:hover {
    background: rgba(99, 102, 241, 0.14);
    border-color: rgba(99, 102, 241, 0.6);
}

.lightbox-info-icon {
    flex-shrink: 0;
    color: #7f8c8d;
    margin-top: 2px;
}

.lightbox-info-content {
    flex: 1;
    color: #2c3e50;
    word-wrap: break-word;
    word-break: break-word;
    overflow-wrap: break-word;
    min-width: 0;
}

.lightbox-date {
    font-weight: 600;
    color: #34495e;
}

.lightbox-caption {
    font-style: italic;
    color: #555;
    word-wrap: break-word;
    word-break: break-word;
    overflow-wrap: break-word;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
    cursor: pointer;
    transition: all 0.2s ease;
}

.lightbox-caption.expanded {
    -webkit-line-clamp: unset;
    overflow: visible;
}

.lightbox-caption:hover {
    color: #2c3e50;
}

/* Photo Tagging Modal */
.photo-tagging-overlay {
    z-index: 3100;
}

.photo-tagging-modal {
    max-width: 500px !important;
    width: 500px !important;
    height: auto !important;
    max-height: 80vh !important;
    padding: 0 !important;
}

.tagging-modal-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 20px 25px;
    border-bottom: 1px solid #ecf0f1;
}

.tagging-modal-header h3 {
    font-size: 18px;
    font-weight: 700;
    color: #21304d;
    margin: 0;
}

.tagging-modal-body {
    padding: 20px 25px;
    max-height: calc(80vh - 140px);
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.tag-section {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.tag-section-header {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 5px;
}

.tag-section-header h4 {
    font-size: 16px;
    font-weight: 600;
    color: #21304d;
    margin: 0;
}

.tag-search-input {
    width: 100%;
    padding: 10px 14px;
    border: 1px solid #dfe6e9;
    border-radius: 8px;
    font-size: 14px;
    font-family: 'Quicksand', sans-serif;
    transition: all 0.2s ease;
}

.tag-search-input:focus {
    outline: none;
    border-color: #46cfc0;
    box-shadow: 0 0 0 3px rgba(70, 207, 192, 0.1);
}

.tag-items-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-height: 200px;
    overflow-y: auto;
    padding: 5px;
    border: 1px solid #ecf0f1;
    border-radius: 8px;
    background: #f8f9fa;
}

.tag-items-list::-webkit-scrollbar {
    width: 6px;
}

.tag-items-list::-webkit-scrollbar-track {
    background: #f1f3f4;
    border-radius: 3px;
}

.tag-items-list::-webkit-scrollbar-thumb {
    background: #c1c8cd;
    border-radius: 3px;
}

.tag-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    background: white;
    border-radius: 6px;
    cursor: pointer;
    transition: all 0.2s ease;
    font-size: 14px;
    color: #21304d;
}

.tag-item:hover {
    background: #e8f5f5;
}

.tag-item input[type="checkbox"] {
    width: 18px;
    height: 18px;
    cursor: pointer;
    accent-color: #46cfc0;
}

.tag-empty-message {
    text-align: center;
    padding: 20px;
    color: #7f8c8d;
    font-size: 14px;
    font-style: italic;
}

.tagging-modal-footer {
    display: flex;
    justify-content: flex-end;
    gap: 12px;
    padding: 20px 25px;
    border-top: 1px solid #ecf0f1;
}

.tagging-cancel-btn,
.tagging-save-btn {
    padding: 10px 24px;
    border-radius: 8px;
    font-size: 14px;
    font-family: 'Quicksand', sans-serif;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s ease;
    border: none;
}

.tagging-cancel-btn {
    background: #ecf0f1;
    color: #21304d;
}

.tagging-cancel-btn:hover {
    background: #dfe6e9;
}

.tagging-save-btn {
    background: #46cfc0;
    color: white;
}

.tagging-save-btn:hover {
    background: #3db8a8;
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(70, 207, 192, 0.3);
}

/* Lightbox Tags Display */
.lightbox-tags {
    display: flex;
    align-items: center;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid rgba(255, 255, 255, 0.2);
    font-size: 14px;
    opacity: 0.9;
}

/* Utility Classes */
.time-input-active {
    border-color: #0984e3 !important;
    box-shadow: 0 0 8px rgba(9, 132, 227, 0.5);
}

@keyframes shake {
    0%, 100% { transform: translateX(0); }
    25% { transform: translateX(-5px); }
    75% { transform: translateX(5px); }
}

/* ── Skeleton shimmer loading animation ────────────────────────── */
@keyframes shimmer {
    0%   { background-position: -400px 0; }
    100% { background-position: 400px 0; }
}

.skeleton {
    background: linear-gradient(90deg, #f0efee 25%, #e4e3e1 37%, #f0efee 63%);
    background-size: 800px 100%;
    animation: shimmer 1.6s ease-in-out infinite;
    border-radius: 12px;
}

.skeleton-line {
    background: linear-gradient(90deg, #f0efee 25%, #e4e3e1 37%, #f0efee 63%);
    background-size: 800px 100%;
    animation: shimmer 1.6s ease-in-out infinite;
    border-radius: 6px;
    height: 14px;
}

/* ── Card fade-in animation ────────────────────────────────────── */
/* 🔴 Animates the independent `translate` property, NOT `transform`.
   `.card-appear` runs with `animation-fill-mode: both`, which holds the
   end-state after the animation finishes — and a filled animation value
   outranks every normal author declaration in the cascade. While this
   animated `transform`, the held `translateY(0)` permanently defeated the
   `:hover` lift on every card that carried the class: `.child-card`,
   `.docs-card`, `.room-card` and `.att-room-donut-card` all had dead hover
   transforms. `translate` is a separate property that composes with
   `transform`, so the held entrance value leaves a hover `transform` free.
   Same fix, and the same reasoning, as `eduCascadeRise` in
   educators-unified.css — which sidestepped this trap deliberately. */
@keyframes cardFadeIn {
    from {
        opacity: 0;
        translate: 0 12px;
    }
    to {
        opacity: 1;
        translate: 0 0;
    }
}

.card-appear {
    animation: cardFadeIn 0.35s cubic-bezier(0.4, 0, 0.2, 1) both;
}

@media (prefers-reduced-motion: reduce) {
    .card-appear {
        animation: none;
    }
    .flex-bar {
        animation: none;
    }
}

/* Generated / photo child face — fills any circular avatar host.
   Absolute fill so a landscape file cannot shrink to a letterboxed
   strip (flex + intrinsic ratio) or stretch to the circle (width and
   height 100% without a definite box). Cover keeps the native ratio. */
.child-face-wrap,
.card-avatar-circle,
.child-avatar-large,
.care-child-avatar,
.large-avatar-circle,
.contact-avatar,
.parent-child-avatar,
.participant-avatar,
.attendance-child-icon,
.child-status-named,
.profile-avatar-face,
.educator-icon,
.edu-avatar,
.edu-avatar-large,
.floor-ed-avatar {
    position: relative;
    overflow: hidden;
}
.child-face {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    border-radius: inherit;
    overflow: hidden;
}
.child-face-img,
.child-face-svg {
    width: 100%;
    height: 100%;
    display: block;
    object-fit: cover;
    object-position: center;
    border-radius: inherit;
}
.attendance-child-icon .child-face,
.child-status-named .child-face {
    position: absolute;
    inset: 0;
}
.child-avatar-large.clickable-avatar,
.large-avatar-circle.clickable-avatar,
.edu-avatar-large.clickable-avatar {
    cursor: pointer;
}

/* Photo editor — crop / replace / remove a square profile photo.
   House modal chrome (.modal-content.glass-content). The vestibule cut
   stays (open on take / upload / tagged; frame only after pick).
   Crop-well contain-fit is from the later 1.3 ratio fix — keep it. */
.photo-editor-modal {
    max-width: 560px;
    width: 92%;
    height: auto;
    max-height: calc(100dvh - 128px);
}
.photo-editor-body {
    padding: 20px 24px 28px;
}
.photo-editor-error {
    margin-bottom: 12px;
    padding: 10px 14px;
    border-radius: 10px;
    background: rgba(255, 107, 107, 0.12);
    color: #a33;
    font-size: 14px;
}
.photo-editor-current {
    display: flex;
    justify-content: center;
    margin-bottom: 16px;
}
.photo-editor-current__img {
    width: 160px;
    height: 160px;
    border-radius: 50%;
    object-fit: cover;      /* the avatar surfaces are circular; preview must agree */
    box-shadow: 0 4px 18px rgba(0, 0, 0, 0.18);
}
.photo-editor-hint {
    margin: 0 0 14px;
    text-align: center;
    font-size: 13px;
    opacity: 0.7;
}
/* Cropper.js replaces this <img> with its own container and sizes to the
   element's box, so the height has to be explicit or the canvas collapses.
   Do not set the img to width+height 100% — that stretches the source
   before Cropper takes over. Contain + auto keeps the native ratio. */
.photo-editor-crop {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 340px;
    background: #1b1b1b;
    border-radius: 12px;
    overflow: hidden;
    margin-bottom: 12px;
}
.photo-editor-crop > img {
    display: block;
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}
/* Round the crop box so the framing matches where the photo actually lands. */
.photo-editor-crop .cropper-view-box,
.photo-editor-crop .cropper-face {
    border-radius: 50%;
}
.photo-editor-crop .cropper-line,
.photo-editor-crop .cropper-point {
    display: none;
}
.photo-editor-actions {
    display: flex;
    justify-content: center;
    gap: 12px;
    flex-wrap: wrap;
}
.photo-editor-actions--footer {
    justify-content: flex-end;
}

.media-picker-modal {
    max-width: 480px;
    width: 90%;
    height: auto;
    max-height: calc(100dvh - 128px);
}
.media-picker-modal--gallery {
    max-width: 720px;
    max-height: 85vh;
    display: flex;
    flex-direction: column;
}
.media-picker-body {
    padding: 20px 24px 28px;
}
.media-picker-modal--gallery .media-picker-body {
    overflow: hidden;
    display: flex;
    flex-direction: column;
    min-height: 0;
}
.media-picker-choices {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}
.media-picker-choice {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    min-height: 140px;
    padding: 18px 12px;
    border: 1px solid rgba(33, 48, 77, 0.12);
    border-radius: 16px;
    background: rgba(255, 255, 255, 0.72);
    color: #21304d;
    font-family: 'Quicksand', sans-serif;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.12s ease;
}
.media-picker-modal--gallery .media-picker-choice {
    min-height: 88px;
    padding: 14px 12px;
}
.media-picker-choice:hover {
    border-color: #74b9ff;
    box-shadow: 0 6px 16px rgba(9, 132, 227, 0.12);
    transform: translateY(-1px);
}
.media-picker-choice iconify-icon {
    font-size: 32px;
    color: #21304d;
}
.media-picker-gallery {
    margin-top: 16px;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
.media-picker-gallery-tabs {
    display: flex;
    gap: 8px;
    margin-bottom: 10px;
}
.media-picker-gallery-tab {
    border: 1px solid rgba(33, 48, 77, 0.12);
    background: rgba(255, 255, 255, 0.65);
    color: #21304d;
    font-family: 'Quicksand', sans-serif;
    font-size: 13px;
    font-weight: 600;
    border-radius: 999px;
    padding: 6px 12px;
    cursor: pointer;
}
.media-picker-gallery-tab.is-active {
    border-color: #74b9ff;
    background: rgba(116, 185, 255, 0.18);
}
.media-picker-gallery-status {
    margin: 8px 0 0;
    color: #7f8c8d;
    font-size: 13px;
}
.media-picker-gallery-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
    gap: 8px;
    overflow: auto;
    max-height: 360px;
    padding: 2px;
}
.media-picker-gallery-thumb {
    aspect-ratio: 1 / 1;
    border: 2px solid rgba(255, 255, 255, 0.5);
    border-radius: 10px;
    padding: 0;
    overflow: hidden;
    cursor: pointer;
    background: #eef2f7;
}
.media-picker-gallery-thumb:hover {
    border-color: rgba(59, 130, 246, 0.6);
}
.media-picker-gallery-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.media-picker-gallery-thumb.is-picking {
    opacity: 0.55;
}
.media-picker-video {
    width: 100%;
    border-radius: 14px;
    background: #000;
    max-height: 320px;
    object-fit: cover;
}
.media-picker-error {
    background: #ff7675;
    color: #fff;
    padding: 12px 14px;
    border-radius: 10px;
    margin-bottom: 12px;
    font-size: 14px;
}
.media-picker-loading {
    text-align: center;
    padding: 36px 12px;
    color: #7f8c8d;
}
.media-picker-camera-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: center;
    margin-top: 14px;
}

.photo-tile,
.child-card {
    content-visibility: auto;
    contain-intrinsic-size: 0 220px;
}

/* Responsive adjustments for smaller screens */
@media (max-width: 1366px) {
    .container {
        width: 95%;
        max-width: 1280px;
    }
}

/* ── Tablet UI mode (Galaxy Tab A 8.4 / tablet-class devices) ────────
   Gated on html[data-ui-mode="tablet"], set at boot by the inline
   detector in app.html/admin.html. Auto = touch + (Android|iPad) +
   tablet geometry (short≥500 & long≥900 CSS px); override with
   ?ui=tablet|desktop|auto, persisted in sessionStorage (per-tab only).
   Deliberately NOT pure-width-based: a half-snapped desktop Chrome
   window without a tablet-class device keeps the stock desktop UI.
   Tuned for the fleet Tab A ~1024×532 CSS. parent.html never sets the
   attribute, so the parent portal is untouched by design. */
html[data-ui-mode="tablet"] .container {
    width: 100vw;
    max-width: none;
    /* Vertical economy: the measured device gives Chrome only ~532px of
       height — desktop chrome (15px shell padding + 70px header + 15px
       margin) leaves ~417px for content. Trimmed paddings below buy
       back ~25px. */
    padding: 10px;
}
html[data-ui-mode="tablet"] .header {
    height: 60px;
    margin-bottom: 10px;
    padding: 8px 16px;
}
html[data-ui-mode="tablet"] .flex-bar {
    height: 48px;
}

/* Header: the flex-bar is centered on the header midpoint and doesn't
   see its siblings — a long org/centre name (admin.html especially)
   runs underneath it. Narrower bar + ellipsis cap keep both clear. */
html[data-ui-mode="tablet"] .flex-bar-container {
    /* 54vw at the fleet 1024 width ≈ 553px — the 46vw clamp (471px)
       could not hold "Activity Planner" + the room chip
       ("INF · EY1 Infants") + the week range at once. Same centred
       candy pill; reservation below still clears the icon cluster. */
    width: clamp(320px, 54vw, 720px);
    /* Cluster is ~206px (7x26 + 6x4 gaps) — 430 reservation keeps the
       centred bar clear of it on both sides. (NB: initial-scale 1.15 was
       reverted 2026-07-16 for option B — full 1024×532 density; at the
       fleet's 1024 width the 54vw clamp is the binding constraint, so
       this max-width only bites below ~935px.) */
    max-width: min(66.67%, calc(100% - 430px));
}
/* Control-heavy module bars (Children: search + two dropdowns) need the
   pill's side padding as content room; 5px vertical keeps the tallest
   control (~38px) inside the 48px bar (border-box). 18px sides: at 12px
   the title sat uncomfortably close to the pill edge on full bars (jj,
   round 17) — the shrink-first search absorbs the lost width. */
html[data-ui-mode="tablet"] .flex-bar {
    padding: 5px 18px;
}
/* Right icon cluster: 7 icons at 45px/15px-gap crush the bar to its
   350px floor on-device — same slimming treatment as the nav rail. */
html[data-ui-mode="tablet"] .notifications {
    --header-icon-gap: 4px;
}
html[data-ui-mode="tablet"] .notification-icon {
    width: 26px;
    height: 26px;
}
html[data-ui-mode="tablet"] .label-centered {
    font-size: 17px;
}
html[data-ui-mode="tablet"] .flex-bar .docs-search {
    /* Adaptive, not fixed: a hard 72px cap crushed the search to "Se…"
       while the bar sat on visible slack. Natural width comes from each
       module's authored size (children 170, ASQ 220); under pressure the
       high shrink factor makes the search yield toward its 72px floor
       BEFORE the module title starts ellipsizing. */
    min-width: 60px;
    max-width: 170px;
    flex-shrink: 3;
}
/* The input's intrinsic minimum (~170px) otherwise props up every
   ancestor's min-content, so the search box never actually shrinks —
   the wrapper's 60px floor above is the real minimum. */
html[data-ui-mode="tablet"] .flex-bar .docs-search .docs-search-input {
    min-width: 0;
}
/* Bars whose only control is the search box (Resources) have the whole
   pill to themselves — let the placeholder breathe instead of clipping
   at "Filter by I". */
html[data-ui-mode="tablet"] .flex-bar:not(:has(.asq-nav-label-wrap)) .docs-search {
    max-width: 230px;
}
html[data-ui-mode="tablet"] .profile-info h2,
html[data-ui-mode="tablet"] .profile-info p {
    max-width: 150px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* admin.html's centre-switcher h2 is inline-flex (inline style), so
   text-overflow on the h2 itself clips MID-GLYPH — the ellipsis has
   to live on the text span inside it. */
html[data-ui-mode="tablet"] .profile-info h2 > span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
/* Bars that carry teleported controls keep their module title (jj:
   hidden labels read as broken — the Messaging bar even rendered fully
   blank because its teleport mounts an invisible wrapper). The title
   shrinks and ellipsizes instead, controls keep their full labels. */
html[data-ui-mode="tablet"] .flex-bar .flex-bar-content,
html[data-ui-mode="tablet"] .flex-bar .label-centered {
    font-size: 14px;
}
/* flex-bar-content keeps its base flex layout (several modules put
   controls INSIDE it — photos' date picker, resources' search — and
   display:block scattered them). It may shrink; the ellipsis lives on
   the plain-text title span so composite content is untouched.
   min-content (NOT 0): with an explicit 0 the wrapper collapsed
   entirely under pressure and the title span spilled out of the bar
   leftward — the floor is its child's own minimum. */
html[data-ui-mode="tablet"] .flex-bar-content {
    flex: 0 1 auto;
    width: auto;
    min-width: min-content;
}
/* #topBarControls carries flex-shrink 0 at desktop — under tablet
   pressure that pushed the ENTIRE deficit onto the title wrapper.
   Let the controls cluster shrink; min-width 0 (NOT min-content —
   Chrome resolves min-content through this nested flex chain at the
   PREFERRED size, which blocks shrinking entirely). The real floors
   live on the leaves: the search stops at its 60px min-width and the
   fixed pills never shrink, so the cluster bottoms out at their sum. */
html[data-ui-mode="tablet"] .flex-bar #topBarControls {
    flex-shrink: 1;
    min-width: 0;
}
/* The teleported control wrappers are anonymous inline-styled divs
   whose automatic minimum resolves at the search's inline width:170
   basis (not its 60px floor) — the wrapper OVERFLOWED #topBarControls
   LEFTWARD, painting over the module title while every scrollWidth
   check read clean (leftward paint doesn't extend scrollWidth; jj's
   "Childre|" screenshot, round 15). */
html[data-ui-mode="tablet"] .flex-bar #topBarControls > div {
    min-width: 0;
}
html[data-ui-mode="tablet"] .flex-bar-content > span {
    flex: 0 1 auto;
    min-width: 64px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Centre the [title | controls] group in the pill instead of pinning
   the title left and the controls right with dead space between (the
   "off centre" look). label-centered is a crushed DUPLICATE of the
   title on every module except dashboard (which has no
   .flex-bar-content) — hide the duplicate, keep dashboard's. */
html[data-ui-mode="tablet"] .flex-bar {
    justify-content: center;
    gap: 6px;
    /* Uniform pill width across modules: the planner rides
       .curriculum-top-bar, whose width:auto (app-modules.css, loaded
       after this sheet) shrink-wrapped its pill narrower than every
       sibling bar. This selector out-specifies it, so all bars span
       the container. */
    width: 100%;
}
/* Module control wrappers that claim the full row on desktop
   (flex-basis 100% / width:100%, right-aligned) crush the title to its
   ellipsis floor no matter how much space the bar has. Content-sized
   and centred in tablet mode. NB children/curriculum/educators teleport
   ANONYMOUS inline-styled divs (no wrapper class exists for them) —
   only docs and photos ship a classed full-row wrapper. */
html[data-ui-mode="tablet"] .flex-bar .docs-top-bar-content,
html[data-ui-mode="tablet"] .flex-bar .gallery-topbar-filters {
    /* !important: docs' wrapper carries these as inline styles */
    flex: 0 1 auto !important;
    width: auto !important;
    justify-content: center !important;
}
/* Photos' wrapper also carries side padding that would offset the
   centred [title | date-picker] group. */
html[data-ui-mode="tablet"] .flex-bar .gallery-topbar-filters {
    padding: 0;
}
/* Back button pins to the pill's left edge on drill-in bars (it was
   getting swept into the centred group — jj: keep it consistently
   left, title centred). No :has() padding companion: the compliance
   drill-in's back teleport is PERMANENTLY mounted with x-show
   (display:none at rest), so any child-existence test fires on every
   bar — it stole 280px from dashboard/children/educators and crushed
   their titles. Visible backs only occur on title-only drill-in bars
   where the centred title never reaches the pill edge, so no reserve
   is needed. */
html[data-ui-mode="tablet"] .flex-bar #topBarBackControls {
    position: absolute;
    left: 10px;
    top: 50%;
    transform: translateY(-50%);
    /* Above .flex-bar > * siblings (z-index 1): long drill-in titles
       slide under the pinned button, and on a z tie the later sibling
       paints on top and STEALS ITS CLICKS (jj, round 22: back button
       overlapped and unclickable on Attendance·Compliance·Infants). */
    z-index: 3;
}
/* Cap the back label: the attendance-report back button renders the
   CENTRE NAME ("← Sunshine Valley Early Learning…") — unbounded, it
   blows past the 150px reserve below and shoves the centred title.
   Ellipsize inside a hard cap instead (audit 2026-07-16). */
html[data-ui-mode="tablet"] .flex-bar #topBarBackControls button {
    max-width: 140px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
html[data-ui-mode="tablet"] .flex-bar #topBarBackControls button span {
    display: inline-block;
    max-width: 110px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: bottom;
}
/* Reserve the back button's zone only when a back child is actually
   VISIBLE. The mount is permanent with x-show, so :has(> *) would fire
   on every bar (the round-11 trap) — but x-show hides via inline
   display:none, which IS selectable. The centred title then centres in
   the remaining space instead of sliding under the button. */
html[data-ui-mode="tablet"] .flex-bar:not(:has(.flex-bar-notif)):has(#topBarBackControls > *:not([style*="display: none"])) {
    /* 150px: the widest back label ('← Dashboard') measures ~117px +
       10px pin offset — 128px left it pixel-flush, which still reads
       as overlap (jj, round 23). flex-start (not center): centring
       the group inside the reserved space pushed composite bars'
       right-side controls past the pill edge (jj, round 25: billing's
       '…' button spilled). Content flows from the reserve edge and
       the title span absorbs the squeeze. */
    padding-left: 150px;
    justify-content: flex-start;
}
/* COMPOSITE drill bars (back + visible controls) run tight: their back
   label is the short '← Back' (~86px), so the Dashboard-sized reserve
   wastes 40px, and rigid control buttons ('Send to Jason' + '…') can
   spill the pill edge (jj, round 29: Harper Anderson billing). Smaller
   reserve + let the title wrapper shrink (its span keeps the 64px
   ellipsis floor) so buttons always stay inside. */
html[data-ui-mode="tablet"] .flex-bar:not(:has(.flex-bar-notif)):has(#topBarBackControls > *:not([style*="display: none"])):has(#topBarControls > div:not([style*="display: none"])),
html[data-ui-mode="tablet"] .flex-bar:not(:has(.flex-bar-notif)):has(#topBarBackControls > *:not([style*="display: none"])):has(.flex-bar-billing-context:not([style*="display: none"])) {
    padding-left: 110px;
}
html[data-ui-mode="tablet"] .flex-bar:not(:has(.flex-bar-notif)):has(#topBarBackControls > *:not([style*="display: none"])):has(#topBarControls > div:not([style*="display: none"])) .flex-bar-content,
html[data-ui-mode="tablet"] .flex-bar:not(:has(.flex-bar-notif)):has(#topBarBackControls > *:not([style*="display: none"])):has(.flex-bar-billing-context:not([style*="display: none"])) .flex-bar-content {
    min-width: 0;
}
/* Back-visible bars also get the container's full width budget — the
   46vw clamp left composite drill bars (back + title + controls) ~7px
   short even at flex-start. */
html[data-ui-mode="tablet"] .flex-bar-container:not(:has(.flex-bar-notif)):has(#topBarBackControls > *:not([style*="display: none"])) {
    width: min(66.67%, calc(100% - 430px));
}
/* TITLE-ONLY drill bars (no visible teleported controls — the `div`
   tag filter skips Alpine's always-present <template> mounts):
   flex-start left the lone label hugging the back reserve (jj, round
   26: "why is the Children label off centre?"). Symmetric padding
   re-centres it in the full pill; composite bars keep flex-start. */
html[data-ui-mode="tablet"] .flex-bar:not(:has(.flex-bar-notif)):has(#topBarBackControls > *:not([style*="display: none"])):not(:has(#topBarControls > div:not([style*="display: none"]))):not(:has(.flex-bar-billing-context:not([style*="display: none"]))) {
    /* 'safe center': centred while the title fits the symmetric box;
       a longer title falls back to flex-start and RUNS INTO the right
       padding instead of ellipsizing ('Infan…' with visible space,
       jj round 28) — complete beats perfectly centred. */
    justify-content: center;
    justify-content: safe center;
    padding-right: 150px;
}
/* The long-title fallback only works if the label itself refuses to
   shrink/ellipsize on these bars. */
html[data-ui-mode="tablet"] .flex-bar:not(:has(.flex-bar-notif)):has(#topBarBackControls > *:not([style*="display: none"])):not(:has(#topBarControls > div:not([style*="display: none"]))):not(:has(.flex-bar-billing-context:not([style*="display: none"]))) .label-centered,
html[data-ui-mode="tablet"] .flex-bar:not(:has(.flex-bar-notif)):has(#topBarBackControls > *:not([style*="display: none"])):not(:has(#topBarControls > div:not([style*="display: none"]))):not(:has(.flex-bar-billing-context:not([style*="display: none"]))) .flex-bar-content > span {
    flex-shrink: 0;
    max-width: none;
    overflow: visible;
    text-overflow: clip;
}
html[data-ui-mode="tablet"] .flex-bar:has(.flex-bar-content) .label-centered {
    display: none;
}
/* Controls sized to the 48px bar: the search box and picker pills sat
   nearly edge-to-edge vertically. */
html[data-ui-mode="tablet"] .flex-bar .docs-search {
    padding: 4px 10px;
}
/* Notification state — POPUP CARD, not a header pill (jj, round 25:
   long toasts/confirms never fit the crowded 48px tablet header; "show
   it as a pop up window"). The whole container pops out of the header
   as a fixed, centred card below the header line; the base rules
   already hide the bar's regular children while a notif shows, so the
   card IS the notification. Same store, timeouts, and confirm buttons
   — presentation only. */
html[data-ui-mode="tablet"] .flex-bar-container:has(.flex-bar-notif) {
    position: fixed;
    left: 50%;
    top: 84px;
    transform: translateX(-50%);
    /* FIXED card width (not max-content): the bar/notif/message chain
       sizes circularly under intrinsic sizing, and messages with
       embedded newlines (pre-line) collapsed the inner card into a
       crunched column inside a wide outer pill (jj, round 28). */
    width: min(80vw, 560px);
    max-width: min(80vw, 560px);
    z-index: 10050;
}
html[data-ui-mode="tablet"] .flex-bar:has(.flex-bar-notif) {
    height: auto;
    min-height: 0;
    min-width: 0;
    width: 100%;
    max-width: 100%;
    box-shadow: 0 10px 32px rgba(0, 0, 0, 0.3);
}
html[data-ui-mode="tablet"] .flex-bar:has(.flex-bar-notif) .flex-bar-notif {
    width: 100%;
    max-width: none;
}
html[data-ui-mode="tablet"] .flex-bar:has(.flex-bar-notif) .flex-bar-notif__msg {
    /* Popup flows text at card width; source strings' embedded
       newlines were tuned for the old in-bar layout. */
    white-space: normal;
    max-width: none;
}

/* Module-content zoom (jj round 16: "75% zoom — smaller but clear is
   better than bigger and suffocating"). Renders every module's
   desktop-proportioned content at 75%, giving the 1024px glass an
   effective ~1365px content viewport — the layout register jj approved
   on the (fictional) 1340 preset, now on the real device. The header,
   flex bar, and nav rail are OUTSIDE the display area and keep their
   tablet tuning. The dashboard is exempt: it is the finger-first
   check-in surface and keeps its approved 52px (9.2 mm) circles. */
html[data-ui-mode="tablet"] .app-display-area > * {
    zoom: 0.75;
}
html[data-ui-mode="tablet"] .app-display-area > .dashboard-container-wrapper {
    zoom: 1;
}

/* Quiet scrollbars for admin shells only (html[data-ui-mode] is set
   by app.html/admin.html for both tablet and desktop). parent.html
   never sets the attribute, so the parent portal keeps platform
   default scrollbars. Thin thumbs on a transparent track; the four
   JS-recipe surfaces keep their fade behaviour on top of this. */
html[data-ui-mode] * {
    scrollbar-width: thin;
    scrollbar-color: rgba(33, 48, 77, 0.18) transparent;
}
html[data-ui-mode] ::-webkit-scrollbar {
    width: 5px;
    height: 5px;
}
html[data-ui-mode] ::-webkit-scrollbar-track {
    background: transparent;
}
html[data-ui-mode] ::-webkit-scrollbar-thumb {
    background: rgba(33, 48, 77, 0.18);
    border-radius: 4px;
}

/* ── Liquid Glass modal base — shared by onboarding, messaging
   (topic compose) and the app-shell asset picker. Moved from
   onboarding.css: that file loads lazily on module entry, so these
   modals rendered unfrosted until Onboarding had been visited. ── */
/* Liquid Glass Modal Effect.
   Overlay blur bumped 5px → 12px to match the stronger blur on
   .glass-content below it — 5px was imperceptible on top of the already-
   translucent background, so the overlay read as a flat tint rather
   than frosted glass. 12px keeps the visual hierarchy (content > overlay)
   while making the frost effect visible. */
.glass-overlay {
    background: rgba(255, 255, 255, 0.15);
    backdrop-filter: blur(28px) saturate(1.4);
    -webkit-backdrop-filter: blur(28px) saturate(1.4);
    border: none;
}

.glass-content {
    background: rgba(255, 255, 255, 0.85);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border: 1px solid rgba(255, 255, 255, 0.5);
    box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.15);
    max-width: 700px;
}

.glass-content .modal-header {
    border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
.context-delete-btn {
    color: #b83b32;
}

.context-delete-btn:hover {
    color: #8f241d;
    background: rgba(184, 59, 50, 0.1);
}
