/*
   AIoFax calendar design system.
   Ported from Docs/Calendar/calendar-studio-export.css (itself extracted from
   https://ofaxy-dialogs.ai.studio on 2026-08-26), per Task 2 of
   Docs/Calendar/Calendar-Redesign-Plan.md.

   Only the token set and the page-frame / toolbar / view-selector sections are ported here.
   Month/week/day grid, event-chip layout, all-day row, rail and focus-matrix rules are added by
   later tasks in the plan as the corresponding markup lands.

   Differences from the export:
     - the --cat-* fixed six-colour category palette is dropped entirely. Event colour is driven
       per-item instead by --cal-item-color, set inline via
       AIoFax.Web/Components/Pages/Calendar/CalendarItemStyle.ColorVariable() (Task 1). See the
       chip rules below, which are new in this file (the export has no --cal-item-color consumer).
     - the token blocks are scoped to .cal-app-container instead of :root/.rz-theme-material, so
       they cannot leak into Tasks, Recipes, Media or any other Radzen-themed page.
     - dark-mode scoping: the export's original selectors (.rz-theme-material-dark,
       [data-theme="dark"]) are kept for parity with the reference, but neither actually occurs
       anywhere in this app as an ancestor of page content. [data-theme] is only ever set, scoped
       to .aio-dialog-scope, by AioDialogHost.razor.cs (see AioDialogHost.razor) — unrelated to the
       calendar page. The mechanism this app actually uses for page-level dark mode is
       .ap-shell--dark on the AppLayout root (see AppLayout.razor line 7 and its extensive use in
       site.css). .ap-shell--dark is therefore added alongside the export's selectors so the dark
       tokens actually activate when the calendar page (rendered inside .ap-main, itself inside
       .ap-shell) is viewed in dark mode.
     - .cal-app-container uses height: 100% instead of min-height: calc(100vh - 65px); it renders
       inside .ap-main, which already sizes itself, so the studio's standalone-document value would
       overflow the app shell.

   Hand-maintained from here on: do not overwrite with a fresh studio export.
*/

/* ---------------------------------------------------------------- tokens */

.cal-app-container {
    --cal-bg: var(--rz-base-background-color, #fff);
    --cal-body-bg: var(--rz-body-background-color, #f7f6fb);
    --cal-card-bg: #fff;
    --cal-sidebar-bg: #fbfaff;
    --cal-sidebar-border: #eeebf7;
    --cal-header-bg: #fff;
    --cal-header-border: #dfdbed;
    --cal-grid-border: #e8e4f3;
    --cal-subgrid-border: #f3f1f9;
    --cal-slot-hover: #f5f3fc;
    --cal-today-bg: #f5f0ff;
    --cal-today-accent: #4a00cc;
    /* Foreground for .cal-minimonth-day--today, which paints --cal-today-accent as a solid fill.
       White on this saturated dark purple clears WCAG AA with a wide margin (this is the same
       relationship --rz-on-primary already covers on the light theme's --rz-primary); the
       dark-mode override below is where this token earns its keep — see the comment there. */
    --cal-today-fg: #fff;
    --cal-now-indicator: #e11d48;
    --cal-nonworking-bg: #f3f1f9a6;
    --cal-time-col-width: 68px;
    --cal-hour-row-height: 64px;
    --cal-event-radius: 8px;
    --cal-chip-radius: 6px;
    --cal-pill-radius: 9999px;
    --cal-event-shadow: 0 2px 6px -1px #1e1b2e14, 0 1px 3px #1e1b2e0a;
    --cal-event-shadow-hover: 0 6px 16px -2px #1e1b2e29, 0 2px 6px #1e1b2e14;
    --cal-btn-active-shadow: 0 1px 3px rgba(0,0,0,.08);
    --cal-control-height: 36px;
    --cal-control-radius: 8px;
    --cal-control-hover-bg: color-mix(in srgb, var(--rz-primary) 8%, transparent);
    --cal-focus-ring: 0 0 0 3px color-mix(in srgb, var(--rz-primary) 35%, transparent);
    --cal-sidebar-shadow: 0 10px 30px #00000040;
    --cal-scrim-bg: #1e1b2e59;
    /* Elevation for the toolbar overflow menu's floating panel (.cal-overflow-panel). */
    --cal-overflow-shadow: 0 8px 24px #00000029;
    /* .cal-btn--primary's foreground/hover-background. White on the light theme's --rz-primary
       (material theme, a saturated dark purple) already clears WCAG AA with a wide margin, so
       this matches --rz-on-primary's usual value; the dark-mode override below is where this
       token earns its keep — see the comment there. */
    --cal-btn-primary-fg: #fff;
    --cal-btn-primary-hover-bg: var(--rz-primary-darker, var(--rz-primary));
    /* .cal-btn--secondary's filled-grey fill (carried-over fix: the toolbar's "AI Focus Plan" button
       is the demo's filled grey secondary, not the transparent cal-btn--light). --rz-base-200 is
       already theme-aware on its own (see .cal-view-selector above, which reads it directly with no
       .cal-app-container override) so the fill/foreground need no light/dark split of their own; the
       hover darken amount does, to match --cal-btn-primary-hover-bg's light/dark treatment above. */
    --cal-btn-secondary-bg: var(--rz-base-200);
    --cal-btn-secondary-fg: var(--rz-text-color);
    --cal-btn-secondary-hover-bg: color-mix(in srgb, var(--rz-base-200) 90%, black 10%);
    /* Fixed knob colour for .cal-layer-switch (Demo Parity Plan B1's "Calendars & Layers" toggle
       rows): white reads clearly against both an off-state neutral track and an on-state
       --cal-item-color track in either theme, so light and dark share one value — listed in both
       blocks per this file's "every token in both light and dark" rule, same as --cal-time-col-width
       above. */
    --cal-switch-knob-bg: #fff;
    /* Demo Parity Plan C3 — how much a non-matching event chip fades while a search query is
       active. Kept identical in both blocks per this file's "every token in both light and dark"
       rule (same reasoning as --cal-switch-knob-bg/--cal-time-col-width above): a flat opacity
       reads the same against either theme's chip fill, so light and dark share one value. */
    --cal-search-dim-opacity: 0.32;
    /* Demo Parity Plan E2 — Focus Matrix card elevation. Same light/dark alpha split as
       --cal-overflow-shadow above (a lighter shadow reads correctly in light mode but disappears
       against a dark card background, so dark needs a stronger alpha, not a stronger blur). */
    --cal-matrix-card-shadow: 0 2px 8px #1e1b2e0a;
    /* Weekly Capacity Distribution bar segment colours. --cal-matrix-focus-color intentionally
       reuses --rz-primary (already theme-aware on its own — see --cal-view-selector's background
       above, which reads --rz-base-200 directly with no override) rather than a fixed hex, so the
       "deep focus" segment always matches the app's actual primary accent. The other two are flat
       mid-saturation hues that read clearly as small dots/bar segments (not body text, so WCAG's
       3:1 non-text threshold applies, not 4.5:1) against either theme's card background, the same
       reasoning already used for --cal-switch-knob-bg/--cal-search-dim-opacity above — hence one
       value shared by both blocks rather than a light/dark split. */
    --cal-matrix-focus-color: var(--rz-primary);
    --cal-matrix-meeting-color: #f59e0b;
    --cal-matrix-buffer-color: #10b981;
}

.rz-theme-material-dark .cal-app-container,
[data-theme="dark"] .cal-app-container,
.ap-shell--dark .cal-app-container {
    --cal-bg: var(--rz-base-background-color, #171523);
    --cal-body-bg: var(--rz-body-background-color, #0d0c15);
    --cal-card-bg: #1e1b2e;
    --cal-sidebar-bg: #151321;
    --cal-sidebar-border: #2b2742;
    --cal-header-bg: #1a1728;
    --cal-header-border: #312d47;
    --cal-grid-border: #29253d;
    --cal-subgrid-border: #201d30;
    --cal-slot-hover: #26223b;
    --cal-today-bg: #8b5cf61f;
    --cal-today-accent: #a78bfa;
    /* --cal-today-accent is a light lavender tint in dark mode (Material dark's "state layers
       lighten" pattern, same reason --rz-primary is light here — see --cal-btn-primary-fg's
       comment below). The previous rule painted --rz-on-primary (white) as the today-cell text,
       which measured ~2.72:1 against #a78bfa — white #ffffff vs accent #a78bfa — under both the
       4.5:1 normal-text and 3:1 large-text WCAG AA thresholds. Black (#000000) against the same
       #a78bfa measures ~7.72:1, clearing AA (and just clearing the 7:1 AAA bar too). */
    --cal-today-fg: #000;
    --cal-now-indicator: #fb7185;
    --cal-nonworking-bg: #0d0c158c;
    /* Demo Parity Plan A1: same 68px in both themes, but the value belongs in this block too per
       the project's "every token in both light and dark" rule — a size token left light-only would
       still resolve correctly today (dark inherits from .cal-app-container when unset here), but
       that's exactly the silent-fallback trap the rule exists to prevent for the next token that
       does need to differ. */
    --cal-time-col-width: 68px;
    --cal-event-shadow: 0 2px 8px #00000059;
    --cal-event-shadow-hover: 0 8px 20px #00000080;
    --cal-btn-active-shadow: 0 1px 3px #00000059, 0 0 0 1px #ffffff14;
    --cal-control-height: 36px;
    --cal-control-radius: 8px;
    --cal-control-hover-bg: color-mix(in srgb, var(--rz-primary) 16%, transparent);
    --cal-focus-ring: 0 0 0 3px color-mix(in srgb, var(--rz-primary) 45%, transparent);
    --cal-sidebar-shadow: 0 10px 30px #00000080;
    --cal-scrim-bg: #00000080;
    /* Doubled alpha vs. the light value, matching --cal-sidebar-shadow's light/dark ratio above. */
    --cal-overflow-shadow: 0 8px 24px #00000052;
    /* Radzen's material-dark theme sets --rz-primary to #bb86fc (see
       material-dark-base.css). White text (the usual --rz-on-primary) on that background
       measures ~2.65:1 — well under the 4.5:1 WCAG AA text threshold — because #bb86fc is a
       light tint, not a saturated colour, in dark mode. Matches the actual Material Design dark
       theme spec, which also pairs this exact primary with a near-black "on-primary" rather than
       white. Black (#000) on #bb86fc computes to ~7.93:1, comfortably clearing AA (see the task
       report for the full calculation).
       --cal-btn-primary-hover-bg additionally avoids reusing --rz-primary-darker (#7f5bab in this
       theme) for the hover fill: darkening the already-light #bb86fc toward that shade drops the
       black-text contrast to ~3.99:1 (under the 4.5:1 text threshold, only just above the 3:1
       non-text/UI-component one). Lightening slightly instead — the same "state layers lighten
       in dark mode" pattern real Material dark themes use — raises it to ~9.03:1 instead. */
    --cal-btn-primary-fg: #000;
    --cal-btn-primary-hover-bg: color-mix(in srgb, var(--rz-primary) 88%, white 12%);
    /* --cal-btn-secondary-bg/-fg stay the same expression as the light block (--rz-base-200 and
       --rz-text-color are both already theme-aware Radzen tokens); only the hover direction flips,
       lightening rather than darkening — the same "state layers lighten in dark mode" pattern
       --cal-btn-primary-hover-bg uses above. */
    --cal-btn-secondary-bg: var(--rz-base-200);
    --cal-btn-secondary-fg: var(--rz-text-color);
    --cal-btn-secondary-hover-bg: color-mix(in srgb, var(--rz-base-200) 85%, white 15%);
    --cal-switch-knob-bg: #fff;
    --cal-search-dim-opacity: 0.32;
    /* Doubled alpha vs. the light value, matching --cal-overflow-shadow's light/dark ratio above. */
    --cal-matrix-card-shadow: 0 2px 8px #00000059;
    --cal-matrix-focus-color: var(--rz-primary);
    --cal-matrix-meeting-color: #f59e0b;
    --cal-matrix-buffer-color: #10b981;
}

/* ------------------------------------------------------------ page frame */

.cal-app-container { background-color: var(--cal-body-bg); height: 100%; color: var(--rz-text-color); flex-direction: column; display: flex; overflow: hidden; }

/* Migrated from site.css's superseded CALENDAR PAGE (cal-*) block (Task 7). Co-applied on the same
   root element as .cal-app-container (see Calendar.razor's "ap-page cal-page cal-app-container");
   it only adds the vertical gap between the toolbar, the AI assistant bar and the main layout, and
   lets the page shrink below content height. Purely layout, no colour tokens involved. */
.cal-page { gap: 0.85rem; min-height: 0; }

.cal-main-layout { flex: 1 1 0%; display: flex; position: relative; overflow: hidden; }
.cal-stage { background-color: var(--cal-bg); flex-direction: column; flex: 1 1 0%; display: flex; position: relative; overflow: hidden; padding-right:16px; }

.cal-sidebar { background-color: var(--cal-sidebar-bg); border-right: 1px solid var(--cal-sidebar-border); z-index: 10; flex-direction: column; gap: 16px; width: 290px; min-width: 290px; padding: 16px; transition: transform .2s, width .2s; display: flex; overflow-y: auto; }
.cal-sidebar--collapsed { border-right: none; width: 0; min-width: 0; padding: 0; overflow: hidden; }

/* Scrim behind the rail when it slides over the stage below 900px (see the mobile-open rules in
   the max-width: 900px block below). Hidden outside that breakpoint: the rail is always docked
   in-flow there, so nothing needs dimming behind it. */
.cal-rail-scrim { display: none; }

@media (prefers-reduced-motion: reduce) {
    .cal-sidebar { transition: none; }
}

/* --------------------------------------------------------------- toolbar */

.cal-toolbar { background-color: var(--cal-header-bg); border-bottom: 1px solid var(--cal-header-border); flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 16px; padding: 12px 20px; display: flex; }
.cal-nav-group { align-items: center; gap: 12px; display: flex; }
.cal-date-title { color: var(--rz-text-color); letter-spacing: -.015em; min-width: 210px; margin: 0; font-size: 1.25rem; font-weight: 700; }

.cal-view-selector { background-color: var(--rz-base-200); border-radius: 8px; gap: 2px; padding: 3px; display: inline-flex; }
.cal-view-btn { color: var(--rz-text-secondary-color); cursor: pointer; white-space: nowrap; background: none; border: none; border-radius: 6px; align-items: center; gap: 6px; padding: 6px 12px; font-size: 13px; font-weight: 600; transition: .15s; display: inline-flex; }
.cal-view-btn:hover { color: var(--rz-text-color); }
.cal-view-btn--active { background-color: var(--rz-base-background-color); color: var(--rz-primary); box-shadow: var(--cal-btn-active-shadow); }
.cal-view-btn:focus-visible { outline: none; box-shadow: var(--cal-focus-ring); }

/* ---------------------------------------------------------- event chips */

/* Event chips derive everything from one data-driven custom property. */
.cal-event-card {
    --cal-item-color: var(--rz-primary);
    border-radius: var(--cal-event-radius);
    box-shadow: var(--cal-event-shadow);
    border-left: 4px solid var(--cal-item-color);
    background-color: color-mix(in srgb, var(--cal-item-color) 14%, var(--cal-bg));
    color: var(--rz-text-color);
    box-sizing: border-box;
    cursor: pointer;
    padding: 6px 8px;
    font-size: 12px;
    line-height: 1.35;
    overflow: hidden;
}

.cal-event-card:hover {
    box-shadow: var(--cal-event-shadow-hover);
    background-color: color-mix(in srgb, var(--cal-item-color) 20%, var(--cal-bg));
}

/* AI-generated focus blocks are hatched so they read as machine-scheduled. */
.cal-event-card--focus {
    background-image: repeating-linear-gradient(
        45deg,
        transparent, transparent 10px,
        color-mix(in srgb, var(--cal-item-color) 8%, transparent) 10px,
        color-mix(in srgb, var(--cal-item-color) 8%, transparent) 20px);
}

/* Reminders are non-blocking markers, not filled blocks. */
.cal-event-card--reminder {
    background-color: transparent;
    border-left-width: 0;
    box-shadow: none;
}

/* Completed task entries desaturate rather than fade, so they stay legible in dark mode. */
.cal-event-card--done {
    background-color: var(--rz-base-200);
    border-left-color: var(--rz-text-disabled-color);
}

.cal-event-card--done .cal-event-title {
    color: var(--rz-text-secondary-color);
    text-decoration: line-through;
}

/* ------------------------------------------------------- event chip content (Task 8)

   FullCalendar renders its own event internals by default; fullcalendarInterop.js's eventContent
   hook replaces them with this markup instead, so the chip matches the design: a title, an
   iconised time line, and an optional location line. Colour arrives per-item as --cal-item-color,
   applied to .cal-event-body via style.setProperty from the ColorVariable payload field
   (Calendar.razor.cs's BuildCalendarEvents), because appointment/type colours are user-chosen and
   cannot be known at stylesheet authoring time.

   Every rule below targets .cal-event-body (the eventContent-rendered element) rather than the
   .fc-event/.fc-timegrid-event wrapper that actually carries the cal-event-card* modifier classes:
   the "FullCalendar override layer" above flattens that wrapper's own background/border/box-shadow
   to transparent/none at higher specificity (.cal-fullcalendar.fc .fc-timegrid-event is three
   classes; .cal-event-card--done etc. above is one), so a rule written against the modifier class
   alone never paints anything inside the grid — the base .cal-event-card rules above are only
   reachable outside that override, which nothing on this page renders into. Scoped under
   .cal-fullcalendar.fc per Task 7 (that's where .fc actually lives, not a descendant of
   .cal-fullcalendar). */

.cal-fullcalendar.fc .cal-event-body {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: 4px 6px;
    border-radius: var(--cal-event-radius);
    border-left: 4px solid var(--cal-item-color);
    background-color: color-mix(in srgb, var(--cal-item-color) 14%, var(--cal-bg));
    overflow: hidden;
    box-sizing: border-box;
}

/* Demo Parity Plan A5 — chip title row. fullcalendarInterop.js's eventContent hook now wraps
   .cal-event-title in this flex row (mirrors the demo's inline-styled
   `display:flex; align-items:center; justify-content:space-between; gap:4px` wrapper, ported here
   as a class instead of an inline style per this project's no-inline-styles rule) so a trailing
   badge has somewhere to sit later without moving the title itself. min-width: 0 keeps the title's
   own ellipsis working now that it is a flex item on its main (horizontal) axis, where a flex
   item's default min-width: auto would otherwise refuse to shrink below its content's natural
   width. */
.cal-fullcalendar.fc .cal-event-title-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 4px;
    min-width: 0;
}

.cal-fullcalendar.fc .cal-event-title {
    /* Calendar Redesign Fix 1: explicit high-contrast title colour, matching the demo's
       color: var(--rz-text-color) on .cal-event-title. Declared directly on the title (not just
       inherited from the --fc-event-text-color override above) so it wins outright regardless of
       inheritance order — any explicit declaration beats an inherited value no matter the
       specificity of the ancestor rule that set it, so this alone would already fix the measured
       white-on-pale-tint bug; the --fc-event-text-color neutralisation above is the defence in
       depth for the rest of the chip (e.g. the time/location rows' fallback colour). Legible on
       every item hue: --rz-text-color is the theme's body-text token, chosen for contrast against
       the page background, not against any one item colour, and every chip tint is a ~14% mix of
       the item colour into --cal-bg (near-white in light mode), so dark body text clears WCAG AA
       on all of them the same way it does on the page itself. */
    color: var(--rz-text-color);
    font-weight: 600;
    font-size: 12px;
    line-height: 1.3;
    margin-bottom: 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

.cal-fullcalendar.fc .cal-event-time,
.cal-fullcalendar.fc .cal-event-location {
    display: flex;
    align-items: center;
    gap: 4px;
    color: var(--rz-text-secondary-color);
    font-size: 11px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Calendar Redesign Fix 1: the hatching on .cal-event-card--focus (see the repeating-linear-gradient
   rule below) lays a diagonal stripe of the item colour at 8% opacity over the chip tint, which on
   top of --rz-text-secondary-color's already-reduced contrast can read too faint on some hues.
   Bumping the time/location line to the same full-strength --rz-text-color as the title on focus
   blocks specifically (left alone everywhere else, where the plain 14% tint already gives
   --rz-text-secondary-color enough contrast) keeps both lines legible without changing their
   smaller font-size/icon treatment. */
.cal-fullcalendar.fc .cal-event-card--focus .cal-event-time,
.cal-fullcalendar.fc .cal-event-card--focus .cal-event-location {
    color: var(--rz-text-color);
}

.cal-fullcalendar.fc .cal-event-time .material-icons-outlined,
.cal-fullcalendar.fc .cal-event-location .material-icons-outlined { font-size: 12px; }

/* AI-generated focus blocks are hatched so they read as machine-scheduled. */
.cal-fullcalendar.fc .cal-event-card--focus .cal-event-body {
    background-image: repeating-linear-gradient(
        45deg,
        transparent, transparent 10px,
        color-mix(in srgb, var(--cal-item-color) 8%, transparent) 10px,
        color-mix(in srgb, var(--cal-item-color) 8%, transparent) 20px);
}

/* Reminders are non-blocking markers, not filled blocks. */
.cal-fullcalendar.fc .cal-event-card--reminder .cal-event-body {
    background-color: transparent;
    border-left-width: 0;
}

/* Completed task/reminder entries desaturate rather than merely fade: a plain opacity fade dims
   colour and text contrast together, whereas flattening the fill to a neutral surface and muting
   the rail (paired with the .cal-event-card--done .cal-event-title strikethrough above) keeps the
   text legible in both themes. */
.cal-fullcalendar.fc .cal-event-card--done .cal-event-body {
    background-color: var(--rz-base-200);
    background-image: none;
    border-left-color: var(--rz-text-disabled-color);
}

/* Demo Parity Plan C3 — search dims rather than removes: opacity on the whole chip (not just
   .cal-event-body, unlike the modifiers above) so the accent bar dims too, keeping the grid's
   spatial layout intact while a non-matching item visibly recedes. Applied to the .fc-event
   wrapper itself, which — unlike background/border/box-shadow — nothing in this file's "FullCalendar
   override layer" further down resets, so this rule does not need the .cal-event-body indirection
   the modifiers above require. */
.cal-fullcalendar.fc .cal-event-card--search-dim { opacity: var(--cal-search-dim-opacity); }

/* Short chips (FullCalendar's own short-duration class) collapse to a single row so a 15-minute
   event stays readable at ~20px tall: the icon and time move onto the title's line and the
   location line is dropped rather than clipped illegibly. */
.cal-fullcalendar.fc .fc-timegrid-event-short .cal-event-body {
    flex-direction: row;
    align-items: center;
    gap: 5px;
    padding: 2px 6px;
}
.cal-fullcalendar.fc .fc-timegrid-event-short .cal-event-title { margin-bottom: 0; }
.cal-fullcalendar.fc .fc-timegrid-event-short .cal-event-location { display: none; }

/* ----------------------------------------------------------- toolbar (cont.) */

.cal-nav-arrows { display: inline-flex; gap: 2px; }

.cal-toolbar-actions { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }

.cal-sync-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    border-radius: var(--cal-pill-radius);
    background-color: color-mix(in srgb, var(--rz-primary) 10%, transparent);
    color: var(--rz-primary);
    font-size: 12px;
    font-weight: 600;
}

.cal-sync-pill .material-icons-outlined { font-size: 15px; }
.cal-sync-spin { animation: cal-spin 1.1s linear infinite; }

@keyframes cal-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .cal-sync-spin { animation: none; } }

/* Native toolbar controls, styled entirely from --cal-* tokens so they don't depend on
   dialogs.css's --dlg-* tokens (those resolve empty outside .aio-dialog-scope). One shared
   height and radius keep the icon buttons, the Today button, the view selector and the
   Radzen "New event" button aligned on the same row. */
.cal-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--cal-control-height);
    height: var(--cal-control-height);
    border-radius: var(--cal-control-radius);
    border: 1px solid transparent;
    background: none;
    color: var(--rz-text-secondary-color);
    cursor: pointer;
    padding: 0;
    transition: background-color .15s, color .15s;
}
.cal-icon-btn .material-icons-outlined { font-size: 20px; }
.cal-icon-btn:hover { background-color: var(--cal-control-hover-bg); color: var(--rz-text-color); }
.cal-icon-btn:focus-visible { outline: none; box-shadow: var(--cal-focus-ring); }

.cal-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: var(--cal-control-height);
    padding: 0 14px;
    border-radius: var(--cal-control-radius);
    border: 1px solid transparent;
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: background-color .15s, color .15s, border-color .15s;
}
.cal-btn:focus-visible { outline: none; box-shadow: var(--cal-focus-ring); }
/* Shared disabled treatment for every cal-btn variant — covers the toolbar's "AI Focus Plan"
   (cal-btn--light) as well as cal-btn--primary, which used to define this on its own. */
.cal-btn:disabled { opacity: .55; cursor: not-allowed; }

.cal-btn--light {
    background-color: transparent;
    border-color: var(--cal-header-border);
    color: var(--rz-text-color);
}
.cal-btn--light:hover { background-color: var(--cal-control-hover-bg); }

/* Match the Radzen "New event" button's box to the native cal-* controls beside it. */
.cal-new-btn.rz-button {
    height: var(--cal-control-height);
    border-radius: var(--cal-control-radius);
}

/* Demo Parity Plan C3 — toolbar search box, sitting between the nav group and the view switcher
   per the demo's layout. Built from the same --cal-* tokens as the other native toolbar controls
   above, so it lines up with them on height/radius. */
.cal-search-group {
    position: relative;
    display: inline-flex;
    align-items: center;
    flex: 0 1 220px;
    min-width: 140px;
}

.cal-search-icon {
    position: absolute;
    left: 10px;
    font-size: 18px;
    color: var(--rz-text-secondary-color);
    pointer-events: none;
}

.cal-search-input {
    width: 100%;
    height: var(--cal-control-height);
    border-radius: var(--cal-control-radius);
    border: 1px solid var(--cal-header-border);
    background-color: transparent;
    color: var(--rz-text-color);
    font-family: inherit;
    font-size: 13px;
    padding: 0 10px 0 34px;
}

.cal-search-input::placeholder { color: var(--rz-text-secondary-color); }
.cal-search-input:hover { background-color: var(--cal-control-hover-bg); }
.cal-search-input:focus-visible { outline: none; box-shadow: var(--cal-focus-ring); border-color: transparent; }

/* Demo Parity Plan C4 — toolbar timezone select, styled to match the other native controls
   (cal-icon-btn/cal-btn/cal-search-input) rather than the browser's default select chrome. */
.cal-tz-select {
    height: var(--cal-control-height);
    border-radius: var(--cal-control-radius);
    border: 1px solid var(--cal-header-border);
    background-color: transparent;
    color: var(--rz-text-color);
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    padding: 0 8px;
    cursor: pointer;
}

.cal-tz-select:hover { background-color: var(--cal-control-hover-bg); }
.cal-tz-select:focus-visible { outline: none; box-shadow: var(--cal-focus-ring); }

/* ---- Toolbar overflow menu ----
   Migrated from site.css's superseded CALENDAR PAGE (cal-*) block (Task 7): the brief called for
   deleting that whole block, but this family (Connect/Sync/Disconnect Google Calendar, Appointment
   types, Habits, Scheduling preferences) has no replacement anywhere else, so it is ported here
   instead with its --ap-* tokens converted to the --cal-* / --rz-* equivalents already used
   throughout this file. */
.cal-overflow { position: relative; display: inline-flex; }

.cal-overflow-overlay {
    position: fixed;
    inset: 0;
    z-index: 150;
}

.cal-overflow-panel {
    position: absolute;
    top: calc(100% + 0.4rem);
    right: 0;
    z-index: 200;
    min-width: 232px;
    padding: 0.35rem;
    display: flex;
    flex-direction: column;
    gap: 1px;
    background-color: var(--cal-card-bg);
    border: 1px solid var(--rz-border-color);
    border-radius: 0.6rem;
    box-shadow: var(--cal-overflow-shadow);
}

.cal-overflow-status {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    padding: 0.45rem 0.6rem 0.5rem;
}

.cal-overflow-status-label {
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--rz-text-secondary-color);
}

.cal-overflow-status-value {
    font-size: 0.8rem;
    color: var(--rz-text-color);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cal-overflow-item {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    width: 100%;
    padding: 0.5rem 0.6rem;
    border: none;
    border-radius: 0.45rem;
    background: transparent;
    color: var(--rz-text-color);
    font-size: 0.83rem;
    text-align: left;
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}

.cal-overflow-item .rzi { font-size: 1.05rem; color: var(--rz-text-secondary-color); }
.cal-overflow-item:hover { background-color: var(--cal-control-hover-bg); color: var(--rz-primary); }
.cal-overflow-item:hover .rzi { color: var(--rz-primary); }
.cal-overflow-item:disabled { opacity: 0.55; cursor: default; }

.cal-overflow-divider {
    height: 1px;
    margin: 0.3rem 0.2rem;
    background-color: var(--rz-border-color);
}

/* Toolbar single-row fix (Demo Parity Plan E follow-up). Phase E added the search box, the
   timezone select and three more view buttons (Work Week, Agenda, Focus Matrix — six views total)
   after the toolbar's fit had already been checked, and only by width arithmetic rather than an
   actual render; the arithmetic was wrong; at a 1440px viewport the toolbar's children measured
   ~1757px against ~1155px of available width and wrapped onto a second row.
   Below 1700px (comfortably covers both 1440px and 1280px, well above the existing 900px
   icon-only breakpoint below) the toolbar recovers the width the six-view switcher, the
   Radzen "New event" button and the "AI Focus Plan" button spend on labels, the same icon-only
   treatment those three already fall back to below 900px — every button here keeps its
   aria-label, so the accessible name is unaffected, only the visible text goes away. Paired with
   a narrower search box (still usable, just not claiming a fixed 220px) this closes the gap
   without removing any control. */
@media (max-width: 1700px) {
    .cal-view-btn span:last-child { display: none; }
    .cal-view-btn { padding: 6px 8px; }
    .cal-new-btn.rz-button .rz-button-text { display: none; }
    .cal-focusplan-btn span:last-child { display: none; }

    .cal-search-group { flex: 0 1 120px; min-width: 100px; }

    .cal-nav-group { gap: 8px; }
    .cal-toolbar-actions { gap: 6px; }
}

/* Below 900px the label drops and the button becomes icon-only. The docked-collapse rail
   (.cal-sidebar--collapsed, width: 0) makes no sense once the sidebar can no longer share a row
   with the stage at this width, so the rail becomes a slide-over instead: off-canvas by default,
   revealed with .cal-sidebar--mobile-open.

   Collapsed (desktop) and MobileOpen (mobile) are two independent booleans on Calendar.razor.cs,
   seeded with opposite defaults because Blazor Server cannot know the client's viewport before
   first render — see Calendar.razor.cs's ToggleRail(). CalendarRail.razor renders whichever of
   .cal-sidebar--collapsed / .cal-sidebar--mobile-open applies to each flag, and BOTH are present
   together after every odd-numbered toggle (the common case: from the seeded false/false they flip
   to true/true as one unit). At >=900px that combination is fine as-is: .cal-sidebar--mobile-open
   has no rules outside this block, so only .cal-sidebar--collapsed's width: 0 has any effect. Below
   900px it is NOT fine on its own: .cal-sidebar--collapsed's width: 0 (unconditional, defined near
   .cal-sidebar above) would zero out the very rail .cal-sidebar--mobile-open just slid into view,
   making the "open" state invisible. The compound override below restores the open rail's normal
   box whenever both classes land on the element at once, at this breakpoint only. */
@media (max-width: 900px) {
    .cal-view-btn span:last-child { display: none; }
    .cal-new-btn.rz-button .rz-button-text { display: none; }
    /* Demo Parity Plan A6: the toolbar's "AI Focus Plan" button collapses to icon-only alongside
       the view switcher and New event above, rather than crowding the narrow toolbar. */
    .cal-focusplan-btn span:last-child { display: none; }

    .cal-sidebar {
        position: absolute;
        top: 0;
        bottom: 0;
        left: 0;
        transform: translateX(-100%);
        box-shadow: var(--cal-sidebar-shadow);
    }

    .cal-sidebar--mobile-open { transform: translateX(0); }

    /* See the block comment above: undoes .cal-sidebar--collapsed's width: 0 specifically when
       .cal-sidebar--mobile-open is also present, so the slide-over actually has a box to show. */
    .cal-sidebar--collapsed.cal-sidebar--mobile-open {
        width: 290px;
        min-width: 290px;
        padding: 16px;
        overflow-y: auto;
        border-right: 1px solid var(--cal-sidebar-border);
    }

    .cal-date-title { min-width: auto; font-size: 1.1rem; }

    /* Rendered by CalendarRail.razor only while MobileOpen is true, so it exists in the DOM exactly
       when there is something to dim behind. Click-to-close mirrors the toolbar's own
       .cal-overflow-overlay pattern elsewhere on this page. */
    .cal-rail-scrim {
        display: block;
        position: fixed;
        inset: 0;
        z-index: 9;
        background-color: var(--cal-scrim-bg);
    }
}

/* -------------------------------------------------------------------- rail */

/* Card shell for the rail's cards, including the mini-month. Built from --cal-* tokens rather
   than dialogs.css's dlg-card (its --dlg-* tokens resolve empty outside .aio-dialog-scope — see
   the .cal-icon-btn comment above for the same issue with dlg-icon-btn). */
.cal-rail-card {
    background-color: var(--cal-card-bg);
    border: 1px solid var(--cal-sidebar-border);
    border-radius: var(--cal-control-radius);
    padding: 12px;
}

.cal-minimonth-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.cal-minimonth-title { font-size: 13px; font-weight: 700; color: var(--rz-text-color); }

.cal-minimonth-dow,
.cal-minimonth-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }

.cal-minimonth-dow span {
    text-align: center;
    font-size: 10px;
    font-weight: 700;
    color: var(--rz-text-secondary-color);
    padding-bottom: 4px;
}

.cal-minimonth-day {
    aspect-ratio: 1;
    border: none;
    background: none;
    border-radius: 50%;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--rz-text-color);
    cursor: pointer;
    transition: background-color .12s;
}

.cal-minimonth-day:hover { background-color: var(--cal-slot-hover); }
.cal-minimonth-day--other { color: var(--rz-text-disabled-color); }

/* The band showing what the main grid is displaying. Square, so a run of days reads as a range. */
.cal-minimonth-day--inrange {
    background-color: color-mix(in srgb, var(--rz-primary) 12%, transparent);
    border-radius: var(--cal-chip-radius);
}

.cal-minimonth-day--today {
    background-color: var(--cal-today-accent);
    color: var(--cal-today-fg);
    font-weight: 700;
}

.cal-minimonth-day:focus-visible { outline: none; box-shadow: var(--cal-focus-ring); }

/* Section title used by the rail's "Up next" and "This week" cards, built from --cal-* /
   Radzen tokens instead of dialogs.css's dlg-section-title (its --dlg-* tokens resolve empty
   outside .aio-dialog-scope — see the .cal-rail-card comment above for the same issue). */
.cal-section-title {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin: 0 0 8px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--rz-text-secondary-color);
}

.cal-rail-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 16px 8px;
    color: var(--rz-text-secondary-color);
    font-size: 12px;
}

.cal-rail-empty .material-icons-outlined { font-size: 24px; opacity: .6; }

.cal-upnext-list { display: flex; flex-direction: column; gap: 8px; }

.cal-upnext-item {
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding: 6px 8px;
    border-left: 3px solid var(--cal-item-color);
    border-radius: 0 var(--cal-chip-radius) var(--cal-chip-radius) 0;
    background-color: color-mix(in srgb, var(--cal-item-color) 7%, transparent);
}

.cal-upnext-time { font-size: 11px; font-weight: 700; color: var(--cal-item-color); }
.cal-upnext-title { font-size: 12.5px; font-weight: 600; color: var(--rz-text-color); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-upnext-meta { font-size: 11px; color: var(--rz-text-secondary-color); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* This week / insight card. Mirrors .cal-minimonth-header's pattern above: the row owns the
   bottom margin and resets the title's own margin, rather than the title carrying spacing that
   would also apply to its stand-alone use on the "Up next" card. */
.cal-insight-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.cal-insight-header .cal-section-title { margin: 0; }
.cal-insight-figure { margin: 4px 0 2px; font-size: 1.6rem; font-weight: 800; color: var(--rz-text-color); letter-spacing: -.02em; }
.cal-insight-approx { color: var(--rz-text-secondary-color); font-weight: 600; }
.cal-insight-unit { font-size: .85rem; font-weight: 600; color: var(--rz-text-secondary-color); margin-left: 3px; }
.cal-insight-body { margin: 0; font-size: 11.5px; line-height: 1.45; color: var(--rz-text-secondary-color); }
/* .cal-insight-action (width: 100%, sized the card's "Apply AI time-blocks" button) removed with
   Demo Parity Plan A6: that action moved to the toolbar as "AI Focus Plan", so the card now ends
   with cal-insight-body and no longer has a button to size. */

/* Habits card. Mirrors .cal-upnext-item's per-item colour wash (--cal-item-color, set inline via
   CalendarItemStyle.ColorVariable) but without the left border accent, since a habit row has no
   time column to visually anchor against. */
.cal-habit-list { display: flex; flex-direction: column; gap: 6px; }

.cal-habit-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border-radius: var(--cal-chip-radius);
    background-color: color-mix(in srgb, var(--cal-item-color) 7%, transparent);
}

.cal-habit-icon { font-size: 18px; color: var(--cal-item-color); }
.cal-habit-copy { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.cal-habit-name { font-size: 12.5px; font-weight: 600; color: var(--rz-text-color); }
.cal-habit-meta { font-size: 11px; color: var(--rz-text-secondary-color); }

/* Demo Parity Plan B4: the rail's "🔥 Nd streak" badge, pushed to the row's trailing edge so it
   reads as a status chip rather than a third line of copy. */
.cal-habit-streak {
    flex-shrink: 0;
    margin-left: auto;
    padding-left: 8px;
    font-size: 10.5px;
    font-weight: 700;
    color: var(--rz-text-color);
    white-space: nowrap;
}

/* "Calendars & Layers" card (Demo Parity Plan B1). Each row is a full-width plain button (not a
   native checkbox) so it can carry --cal-item-color per row, the same inline-colour mechanism
   .cal-upnext-item/.cal-habit-row use, set via CalendarItemStyle.ColorVariable in the markup. The
   off state is deliberately NOT a disabled/greyed-out treatment — the row stays fully legible and
   clickable, it just loses its colour cue and the switch visibly parks left, so "off" reads as
   "hidden on purpose", not "unavailable". */
.cal-layer-list { display: flex; flex-direction: column; gap: 2px; }

.cal-layer-row {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 6px 8px;
    border: none;
    border-radius: var(--cal-chip-radius);
    background: none;
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--rz-text-color);
    cursor: pointer;
    text-align: left;
    transition: background-color .12s;
}
.cal-layer-row:hover { background-color: var(--cal-slot-hover); }
.cal-layer-row:focus-visible { outline: none; box-shadow: var(--cal-focus-ring); }

.cal-layer-dot { flex-shrink: 0; width: 9px; height: 9px; border-radius: 50%; background-color: var(--cal-item-color); }
.cal-layer-name { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.cal-layer-row--off .cal-layer-dot { background-color: var(--rz-text-disabled-color); }
.cal-layer-row--off .cal-layer-name { color: var(--rz-text-secondary-color); }

.cal-layer-switch {
    flex-shrink: 0;
    position: relative;
    width: 28px;
    height: 16px;
    border-radius: var(--cal-pill-radius);
    background-color: var(--cal-sidebar-border);
    transition: background-color .15s;
}
.cal-layer-switch--on { background-color: var(--cal-item-color); }

.cal-layer-switch-knob {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background-color: var(--cal-switch-knob-bg);
    box-shadow: 0 1px 2px #00000040;
    transition: transform .15s;
}
.cal-layer-switch--on .cal-layer-switch-knob { transform: translateX(12px); }

/* "N hidden" filter-active indicator (Demo Parity Plan B1): a filtered grid with no visible cue
   reads as an empty calendar, so this sits next to the card title whenever any row is off. Reuses
   --rz-warning the same way site.css's .ri-warn/.rk-insight-icon--star already do elsewhere in this
   app — a global Radzen token, already theme-aware without a .cal-app-container override. */
.cal-layer-filter-badge {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    flex-shrink: 0;
    padding: 2px 7px;
    border-radius: var(--cal-pill-radius);
    background-color: color-mix(in srgb, var(--rz-warning, #f59e0b) 16%, transparent);
    color: var(--rz-warning, #f59e0b);
    font-size: 10px;
    font-weight: 700;
}
.cal-layer-filter-badge .material-icons-outlined { font-size: 13px; }

/* "Task Inbox" card (Demo Parity Plan D1). Rows mirror .cal-habit-row's colour-washed treatment
   (--cal-item-color set inline via CalendarItemStyle.ColorVariable) since a task's accent colour is
   as meaningful here as a habit's. The "Timebox" button reuses .cal-btn/.cal-btn--light/.cal-btn--sm
   and .cal-spinner as-is (defined below) rather than introducing task-inbox-specific button rules. */
.cal-task-inbox-hint {
    margin: -4px 0 8px;
    font-size: 11px;
    line-height: 1.4;
    color: var(--rz-text-secondary-color);
}

.cal-task-inbox-list { display: flex; flex-direction: column; gap: 6px; }

.cal-task-inbox-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border-radius: var(--cal-chip-radius);
    background-color: color-mix(in srgb, var(--cal-item-color) 7%, transparent);
}

.cal-task-inbox-dot { flex-shrink: 0; width: 9px; height: 9px; border-radius: 50%; background-color: var(--cal-item-color); }
.cal-task-inbox-copy { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; gap: 1px; }
.cal-task-inbox-title { font-size: 12.5px; font-weight: 600; color: var(--rz-text-color); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.cal-task-inbox-meta {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    color: var(--rz-text-secondary-color);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cal-task-inbox-btn { flex-shrink: 0; }
.cal-task-inbox-more { width: 100%; justify-content: center; margin-top: 2px; }

/* "Today's Meals" card (Demo Parity Plan B2). Flat neutral rows — meals carry no user colour like
   appointment types/habits do, so there is no --cal-item-color to wash the row with; --cal-slot-hover
   gives it a quiet background instead of leaving it flush with the card. */
.cal-meal-list { display: flex; flex-direction: column; gap: 6px; }

.cal-meal-row {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 6px 8px;
    border-radius: var(--cal-chip-radius);
    background-color: var(--cal-slot-hover);
}

.cal-meal-icon { font-size: 18px; color: var(--rz-text-secondary-color); margin-top: 1px; }
.cal-meal-copy { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.cal-meal-slot { font-size: 10px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--rz-text-secondary-color); }
.cal-meal-name { font-size: 12.5px; font-weight: 600; color: var(--rz-text-color); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-meal-meta { font-size: 11px; color: var(--rz-text-secondary-color); }

/* Demo Parity Plan B5: the rail's "Working Hours & AI Rules" footer button. .cal-sidebar's flex
   column already stretches block-level children to its full width (align-items defaults to
   stretch), same as every .cal-rail-card above it, so only the icon+label centring is this file's
   to add. */
.cal-rail-footer-btn { justify-content: center; }

/* Filled/compact button modifiers layered onto the existing .cal-btn / .cal-btn--light pair
   above, so "Apply AI time-blocks" can be a filled, smaller button without reaching for
   dialogs.css's dlg-btn-primary/dlg-btn-sm (same --dlg-* scoping issue noted throughout this
   file). --rz-primary is a global Radzen theme variable (see site.css) that is already
   theme-aware without a .cal-app-container override — the same assumption .cal-view-btn--active
   already makes with --rz-primary above. The foreground and hover-background are NOT read from
   Radzen's --rz-on-primary/--rz-primary-darker, though: material-dark's --rz-primary (#bb86fc) is
   a light tint, and white-on-it fails WCAG AA (~2.65:1). --cal-btn-primary-fg/-hover-bg (defined
   in the token blocks above, both light and dark) fix that for this button specifically —
   see the dark-mode token block for the contrast maths. .cal-new-btn (the Radzen "New event"
   button elsewhere on this page) has the identical white-on-#bb86fc problem and is NOT fixed
   here: it's a RadzenButton, not one of this file's own cal-* controls, and is left for a
   separate app-wide Radzen-theme pass. */
.cal-btn--primary {
    background-color: var(--rz-primary);
    border-color: var(--rz-primary);
    color: var(--cal-btn-primary-fg);
    box-shadow: var(--cal-btn-active-shadow);
}
.cal-btn--primary:hover:not(:disabled) { background-color: var(--cal-btn-primary-hover-bg); border-color: var(--cal-btn-primary-hover-bg); }

/* Filled grey secondary (carried over from the toolbar work): the demo's "AI Focus Plan" button is a
   filled grey fill, not the transparent-with-border look .cal-btn--light gives every other secondary
   toolbar action. Tokens defined in both light/dark blocks above. */
.cal-btn--secondary {
    background-color: var(--cal-btn-secondary-bg);
    border-color: var(--cal-btn-secondary-bg);
    color: var(--cal-btn-secondary-fg);
}
.cal-btn--secondary:hover:not(:disabled) { background-color: var(--cal-btn-secondary-hover-bg); border-color: var(--cal-btn-secondary-hover-bg); }

.cal-btn--sm { height: auto; padding: 6px 10px; font-size: 12px; border-radius: var(--cal-chip-radius); }

/* Inline busy spinner for .cal-btn--primary, replacing dlg-spinner. Reuses the cal-spin
   keyframes already defined above for the Google-sync icon. */
.cal-spinner {
    width: 13px;
    height: 13px;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    display: inline-block;
    animation: cal-spin .7s linear infinite;
}
@media (prefers-reduced-motion: reduce) { .cal-spinner { animation: none; } }

/* ---- FullCalendar override layer -------------------------------------
   The studio hand-rolled its grid; these rules map that visual language
   onto FullCalendar's real DOM. Left column = studio class it replaces.
   ---------------------------------------------------------------------- */

.cal-fullcalendar { height: 100%; }

/* Demo Parity Plan E2: the Focus Matrix view hides the live FullCalendar instance instead of
   unmounting it (see Calendar.razor.cs's SetViewAsync and aiFaxCalendar.setStageVisible in
   fullcalendarInterop.js) so its state (scroll position, active view) survives switching away and
   back. Never remove .cal-fullcalendar from the DOM with @if in the .razor file — that would
   destroy() the instance instead of just hiding it. */
.cal-fullcalendar--hidden { display: none; }

.cal-fullcalendar.fc {
    --fc-border-color: var(--cal-grid-border);
    --fc-today-bg-color: var(--cal-today-bg);
    --fc-now-indicator-color: var(--cal-now-indicator);
    --fc-page-bg-color: var(--cal-bg);
    --fc-neutral-bg-color: var(--cal-sidebar-bg);
    --fc-small-font-size: .72rem;
    /* Demo Parity Plan A4: FullCalendar's own non-business-hours shading, driven by the
       businessHours option (built server-side from CalendarAvailabilityRule) rather than the
       hand-rolled .fc-day-sat/.fc-day-sun weekend wash this replaces below. */
    --fc-non-business-color: var(--cal-nonworking-bg);
    /* Calendar Redesign Fix 1: FullCalendar defaults --fc-event-text-color to white and paints it
       on the .fc-event wrapper itself. eventContent's replaced markup (.cal-event-body/-title/-time)
       sits INSIDE that wrapper, so without an override it inherits white text on the pale
       color-mix() chip tint below — unreadable, and the human's exact screenshot complaint.
       Neutralised here at the source (not just on .cal-event-title below) so every FullCalendar-
       rendered text node under .fc-event — including ones this file doesn't explicitly restyle —
       inherits a legible colour by default instead of white. */
    --fc-event-text-color: var(--rz-text-color);
}

/* cal-time-grid-header */
.cal-fullcalendar.fc .fc-col-header-cell {
    background-color: var(--cal-header-bg);
    border-bottom: 1px solid var(--cal-grid-border);
    padding: 6px 8px;
}

.cal-fullcalendar.fc .fc-day-today.fc-col-header-cell { background-color: var(--cal-today-bg); }

/* cal-time-axis-slot: 64px hour rows, so a 30-minute slot is 32px */
.cal-fullcalendar.fc .fc-timegrid-slot { height: 32px; }

.cal-fullcalendar.fc .fc-timegrid-slot-label-cushion {
    font-size: 11.5px;
    font-weight: 500;
    color: var(--rz-text-secondary-color);
}

/* cal-hour-slot::after — the dashed half-hour line */
.cal-fullcalendar.fc .fc-timegrid-slot-minor { border-top-style: dashed; border-top-color: var(--cal-subgrid-border); }

/* cal-day-column--nonworking: shading now comes from FullCalendar's own businessHours option
   (--fc-non-business-color, set above) instead of a hardcoded Sat/Sun wash, so it reflects each
   user's actual CalendarAvailabilityRule windows. See Calendar.razor.cs's BuildBusinessHours. */

/* cal-now-line, including the pulsing dot */
.cal-fullcalendar.fc .fc-timegrid-now-indicator-line {
    border-top-width: 2px;
    border-color: var(--cal-now-indicator);
}

/* Demo Parity Plan A3 — pulsing dot on the now-indicator.
   The demo builds this as a ::before on its own hand-rolled .cal-now-line. FullCalendar's DOM
   differs: it renders exactly one .fc-timegrid-now-indicator-arrow (in the time axis) alongside one
   .fc-timegrid-now-indicator-line PER VISIBLE DAY COLUMN, so the arrow — not the line — is restyled
   into the dot; a ::before on the line would multiply into one dot per column in Week/Work Week
   view. FullCalendar sets this element's vertical offset itself (inline style, to track the current
   time) and already centers a 10px-tall shape on that offset via its own margin-top: -5px (sized for
   its default 5px-border triangle, which is also 10px tall) — left untouched here so the circle
   lands in the same place without an extra correction. */
.cal-fullcalendar.fc .fc-timegrid-now-indicator-arrow {
    width: 10px;
    height: 10px;
    border: none;
    border-radius: 50%;
    background-color: var(--cal-now-indicator);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--cal-now-indicator) 25%, transparent);
    animation: cal-now-pulse-ring 2s ease-out infinite;
}

/* Ring expands outward and fades while the dot itself stays solid and fully opaque throughout,
   matching the "the dot itself should remain visible" requirement even before reduced-motion is
   considered. */
@keyframes cal-now-pulse-ring {
    0%   { box-shadow: 0 0 0 2px color-mix(in srgb, var(--cal-now-indicator) 25%, transparent); }
    100% { box-shadow: 0 0 0 10px color-mix(in srgb, var(--cal-now-indicator) 0%, transparent); }
}

@media (prefers-reduced-motion: reduce) {
    /* The dot (background-color, size, border-radius) is untouched and stays visible; only the
       looping ring animation is disabled, falling back to the static glow ring set above. */
    .cal-fullcalendar.fc .fc-timegrid-now-indicator-arrow { animation: none; }
}

/* cal-allday-row */
.cal-fullcalendar.fc .fc-timegrid-axis { background-color: var(--cal-sidebar-bg); }
.cal-fullcalendar.fc .fc-daygrid-body { background-color: var(--cal-sidebar-bg); }

/* Demo Parity Plan A1 — widen the time gutter 56px -> 68px. (Fix round 2.)
   Round-1 recap: forcing min-width on the frame divs did nothing to the cell (cells collapsed to
   0px, frame overflowed — labelOverlapsLane). Forcing width/min-width !important onto the cells
   themselves (.fc-timegrid-axis / .fc-timegrid-slot-label / header .fc-timegrid-axis) got further —
   no more overlap — but still measured 44px, not 68px.
   Round-2 root cause, found live: FullCalendar's timegrid tables use table-layout: fixed. Under
   fixed layout, column width comes ENTIRELY from the <colgroup>'s <col> elements — width/min-width
   on the cell is ignored outright, which is exactly why round 1's cell rule computed correctly and
   still changed nothing on screen. FullCalendar writes its own measured width (the widest slot
   label's natural width, e.g. 44px for "12am" — a dynamic value, not this file's 68px) as an inline
   style directly on the first <col> of each of its several internal timegrid tables (header row,
   all-day row, body slots).
   Fixed by overriding that <col> width directly, scoped to .fc-timegrid: every other class this
   file already targets in this view (fc-timegrid-axis, -slot-label, -body, -now-indicator-*, …) is
   an "element" of that same "block" in FullCalendar's BEM-style naming, and .fc-timegrid — the
   timeGrid view's own root wrapper — exists ONLY for Week/Day views. Month view (dayGridMonth)
   renders inside .fc-daygrid instead, where the first <col> is Monday's real day column, not an
   axis spacer; scoping under .fc-timegrid means this selector cannot ever reach that colgroup, so
   Month view's first day column keeps its normal width. !important is still required here because
   FullCalendar's own <col> width is a plain (non-!important) inline style. */
.cal-fullcalendar.fc .fc-timegrid colgroup col:first-child {
    width: var(--cal-time-col-width) !important;
}

/* The frame now just fills the cell above (which is itself sized to 68px in fixed layout once its
   <col> is 68px, per the rule above) instead of trying to force its own width. */
.cal-fullcalendar.fc .fc-timegrid-axis-frame,
.cal-fullcalendar.fc .fc-timegrid-slot-label-frame {
    box-sizing: border-box;
    width: 100%;
    padding-right: 8px;
    justify-content: flex-end;
}

/* Demo Parity Plan A2 — "All Day" gutter label.
   Text is injected via the allDayContent hook in fullcalendarInterop.js rather than a CSS ::after:
   the other content hooks in that file (dayHeaderContent, eventContent) already build their copy as
   DOM text nodes so titles/locations stay out of innerHTML, and allDayContent is the option
   FullCalendar exposes for exactly this cell — a ::after would work too (the cell is otherwise
   empty), but it would put literal English copy in a CSS content: value, and it can't reuse
   arg.text as a fallback if that copy ever needs to be localised or removed later. This rule only
   styles the injected label; positioning/sizing (including the fix-round-1 cell width above) is
   inherited from .fc-timegrid-axis-frame / .fc-timegrid-axis above. */
.cal-fullcalendar.fc .cal-allday-axis-label {
    font-size: 11px;
    font-weight: 600;
    color: var(--rz-text-secondary-color);
}

/* cal-month-day-cell */
.cal-fullcalendar.fc .fc-daygrid-day { min-height: 110px; }
.cal-fullcalendar.fc .fc-daygrid-day:hover { background-color: var(--cal-slot-hover); }
.cal-fullcalendar.fc .fc-day-other { opacity: .38; background-color: var(--cal-body-bg); }

/* cal-day-number--today */
.cal-fullcalendar.fc .fc-daygrid-day-number { font-size: 13px; font-weight: 600; padding: 6px; }

.cal-fullcalendar.fc .fc-day-today .fc-daygrid-day-number {
    background-color: var(--cal-today-accent);
    color: var(--cal-today-fg);
    border-radius: 50%;
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    margin: 4px;
}

/* FullCalendar paints its own event background; ours comes from the chip. */
.cal-fullcalendar.fc .fc-timegrid-event,
.cal-fullcalendar.fc .fc-daygrid-block-event,
.cal-fullcalendar.fc .fc-daygrid-dot-event {
    background-color: transparent;
    border: none;
    box-shadow: none;
    padding: 0;
}

.cal-fullcalendar.fc .fc-event-main { padding: 0; }

/* cal-month-chip / fc-popover */
.cal-fullcalendar.fc .fc-daygrid-more-link {
    font-size: 11px;
    font-weight: 600;
    color: var(--rz-primary);
    padding: 1px 6px;
}

/* NOTE: the plan's own Step 2 snippet specified --dlg-radius/--dlg-shadow here, but those tokens
   are scoped to .aio-dialog-scope (see dialogs.css:5 and this file's .cal-icon-btn/.cal-rail-card
   comments for the same trap) and resolve to nothing on the calendar page, leaving the popover with
   no radius and no shadow. Using a literal radius plus the --cal-overflow-shadow token (already
   defined above for .cal-overflow-panel, the same floating-panel pattern) instead. */
.cal-fullcalendar.fc .fc-popover {
    background-color: var(--cal-card-bg);
    border: 1px solid var(--rz-border-color);
    border-radius: 12px;
    box-shadow: var(--cal-overflow-shadow);
}

.cal-fullcalendar.fc .fc-popover-header {
    background-color: var(--cal-sidebar-bg);
    color: var(--rz-text-color);
    font-weight: 700;
    font-size: 12.5px;
}

/* Only task-linked entries are draggable; everything else must not offer a grab cursor. */
.cal-fullcalendar.fc .fc-event { cursor: pointer; }
.cal-fullcalendar.fc .fc-event-draggable { cursor: grab; }
.cal-fullcalendar.fc .fc-event-dragging { cursor: grabbing; }

/* ---- Day headers (Week/Day view) ----
   Migrated from site.css's superseded CALENDAR PAGE (cal-*) block (Task 7). Not part of the
   brief's override-layer snippet above, but still actively rendered: fullcalendarInterop.js's
   dayHeaderContent callback builds this exact markup (.cal-dayhead[--today] wrapping
   .cal-dayhead-dow / .cal-dayhead-num) for Week/Day view's two-line column header, replacing
   FullCalendar's default cushion content. Deleting it without a replacement would have left that
   header unstyled, the same class of mistake the brief already flagged for .cal-overflow-*.
   --ap-* tokens are converted to --cal-* / --rz-* equivalents; the today pill reuses
   --cal-today-accent/--cal-today-fg (the same pairing used by the month-view today marker above
   and .cal-minimonth-day--today) rather than --rz-on-primary, which fails contrast on
   --cal-today-accent in dark mode (see that token's comment in the token block). */
.cal-dayhead {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.15rem;
}

/* Calendar Redesign Fix 2: the label is now the full weekday name ("Monday") built by
   dayHeaderContent as two child spans (.cal-dayhead-dow-full / .cal-dayhead-dow-abbr) rather than
   one textContent string, so a narrow column can fall back to the short, uppercased form in CSS
   alone — no JS re-render needed. max-width/overflow/ellipsis is a last-resort safety net (per the
   brief: "does not overflow or clip"), not the primary narrow-column strategy; the primary strategy
   is the full<->abbr swap below, which should already have engaged well before ellipsis would. */
.cal-dayhead-dow {
    display: block;
    max-width: 100%;
    font-size: 0.68rem;
    font-weight: 600;
    color: var(--rz-text-secondary-color);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cal-dayhead-dow-abbr { display: none; letter-spacing: .03em; }

/* Mirrors the demo's own narrow-column fallback: below this width a 7-day week grid's per-column
   share is tight enough that full weekday names risk the ellipsis case above, so the short,
   uppercased form (already built by dayHeaderContent, just hidden until now) takes over instead. */
@media (max-width: 640px) {
    .cal-dayhead-dow-full { display: none; }
    .cal-dayhead-dow-abbr { display: inline; }
}

.cal-dayhead-num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.7rem;
    height: 1.7rem;
    padding: 0 0.3rem;
    border-radius: 999px;
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--rz-text-color);
}

.cal-dayhead--today .cal-dayhead-dow { color: var(--rz-primary); }

.cal-dayhead--today .cal-dayhead-num {
    background-color: var(--cal-today-accent);
    color: var(--cal-today-fg);
    font-weight: 700;
}

/* Habit dots under each Week/Day header (Demo Parity Plan B3). Ported from
   Docs/Calendar/calendar-studio-export.css's .cal-habits-header-row/.cal-habit-dot, but recoloured
   from the export's fixed --cat-habit token to --cal-item-color, this app's existing per-item colour
   mechanism (see .cal-habit-row above): fullcalendarInterop.js's dayHeaderContent hook sets it inline
   per dot from that habit's own ColorHex, the same way eventContent already does for event chips.
   Falls back to --rz-primary (an existing themed token, not a hard-coded colour) if a stored
   ColorHex is ever missing. Sized 18px to match calendar-studio-export.css's .cal-habit-dot exactly
   (Calendar Redesign Fix 3) — this only ever affects header row height, not the 68px time-gutter
   column width set by --cal-time-col-width, which is driven by <col> in the timegrid's colgroup,
   not by cell content. */
.cal-habits-header-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    margin-top: 3px;
}

/* Calendar Redesign Fix 3: unfilled = a coloured ring on a transparent fill; completed (below) =
   solid coloured fill with a white glyph. --cal-item-color arrives inline per dot (set by
   dayHeaderContent in fullcalendarInterop.js from the habit's own ColorHex — the only sanctioned
   inline-style use, same mechanism the event chips use for --cal-item-color), so the ring/fill
   colour is always the individual habit's own colour, never a fixed hex and never --cat-habit (that
   demo token does not exist in this app's token set). */
.cal-habit-dot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    padding: 0;
    border: 1.5px solid var(--cal-item-color, var(--rz-primary));
    border-radius: 50%;
    background: none;
    color: var(--cal-item-color, var(--rz-primary));
    cursor: pointer;
    transition: background-color .15s, color .15s;
}

.cal-habit-dot:hover {
    background-color: color-mix(in srgb, var(--cal-item-color, var(--rz-primary)) 15%, transparent);
}

.cal-habit-dot:focus-visible {
    outline: 2px solid var(--rz-primary);
    outline-offset: 1px;
}

.cal-habit-dot--completed {
    background-color: var(--cal-item-color, var(--rz-primary));
    color: #fff;
}

/* Completed task-linked calendar entries. Migrated from site.css's superseded CALENDAR PAGE
   (cal-*) block (Task 7): TaskCalendarEventStyle.cs still assigns this class name to completed
   task-linked entries (see its ClassNames property), so it remains live pending Task 8's
   ChipClasses rework. No --ap-* tokens were involved (opacity/text-decoration only). */
.taskcal-done { opacity: 0.55; }
.taskcal-done .fc-event-title,
.taskcal-done .fc-list-item-title { text-decoration: line-through; }

/* ---------------------------------------------------------- Agenda (list) view */

/* Demo Parity Plan C2 — Agenda maps to FullCalendar's built-in listWeek (confirmed present in the
   loaded CDN global bundle: fc-list-* classes and view types ship in index.global.min.js@6.1.15
   alongside dayGrid/timeGrid, so no plugin swap was needed). FullCalendar's own list view already
   gives the demo's day-grouped rows with a time column; these rules just re-theme it from --cal-*
   tokens instead of FullCalendar's default palette, matching the rest of this override layer.
   Scoped under .cal-fullcalendar.fc per this file's rule — see the "FullCalendar override layer"
   comment further up for why the descendant form would match nothing. */
.cal-fullcalendar.fc .fc-list {
    border-color: var(--cal-grid-border);
    background-color: var(--cal-bg);
}

.cal-fullcalendar.fc .fc-list-day-cushion {
    background-color: var(--cal-sidebar-bg);
    color: var(--rz-text-color);
}

.cal-fullcalendar.fc .fc-list-table td {
    border-color: var(--cal-subgrid-border);
}

.cal-fullcalendar.fc .fc-list-event:hover td {
    background-color: var(--cal-slot-hover);
}

.cal-fullcalendar.fc .fc-list-event-time {
    color: var(--rz-text-secondary-color);
    font-size: 12.5px;
}

.cal-fullcalendar.fc .fc-list-empty {
    background-color: var(--cal-bg);
    color: var(--rz-text-secondary-color);
}

/* Replaces FullCalendar's default .fc-list-event-title cell content via the eventContent hook in
   fullcalendarInterop.js (title + an optional location line, same iconised pattern as the grid
   chip's .cal-event-location) — the dot and time cell either side stay FullCalendar's own. */
.cal-fullcalendar.fc .cal-agenda-title { color: var(--rz-text-color); font-weight: 600; font-size: 13px; }

.cal-fullcalendar.fc .cal-agenda-location {
    display: flex;
    align-items: center;
    gap: 4px;
    color: var(--rz-text-secondary-color);
    font-size: 12px;
    margin-top: 2px;
}

/* ------------------------------------------------------------ focus matrix */

/* Demo Parity Plan E2. Ported from Docs/Calendar/calendar-studio-export.css's cal-matrix-grid /
   cal-matrix-card / cal-matrix-stat (lines 172-176 there), with the export's --dlg-radius and its
   hard-coded rgba() card shadow swapped for --cal-* tokens (--dlg-* resolves empty outside
   .aio-dialog-scope — see the .cal-rail-card comment above for the same issue elsewhere in this
   file). Rendered by Calendar.razor as a sibling of .cal-fullcalendar inside .cal-stage, shown only
   while ActiveView is FocusMatrix; .cal-fullcalendar itself is hidden via the class above rather
   than unmounted, so this section never needs to know about FullCalendar's own state. */
.cal-matrix-grid {
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 16px;
    padding: 20px;
    overflow-y: auto;
    display: grid;
}

.cal-matrix-card {
    background-color: var(--cal-card-bg);
    border: 1px solid var(--rz-border-color);
    border-radius: var(--cal-control-radius);
    box-shadow: var(--cal-matrix-card-shadow);
    flex-direction: column;
    gap: 8px;
    padding: 20px;
    display: flex;
}

/* The Weekly Capacity Distribution card spans the full row width, matching the demo's layout
   (a single wide summary card beneath the four stat cards above it). */
.cal-matrix-card--wide { grid-column: 1 / -1; }

.cal-matrix-stat {
    letter-spacing: -.02em;
    color: var(--rz-primary);
    font-size: 2rem;
    font-weight: 800;
    line-height: 1.1;
}

.cal-matrix-stat-suffix {
    margin-left: 2px;
    color: var(--rz-text-secondary-color);
    font-size: 1rem;
    font-weight: 600;
}

.cal-matrix-score-label { color: var(--rz-text-color); font-size: 13px; font-weight: 700; }

.cal-matrix-explain { margin: 0; color: var(--rz-text-secondary-color); font-size: 12.5px; line-height: 1.4; }

/* Weekly Capacity Distribution's stacked bar. Each segment's width is a data-driven custom
   property (--cal-matrix-seg-pct, set inline in Calendar.razor from
   Calendar.razor.cs's MatrixSegmentPercent) — this project's one allowed use of inline style="",
   the same pattern already used by .cal-event-card's --cal-item-color and the rail's --chip-color
   controls. */
.cal-matrix-bar {
    display: flex;
    height: 10px;
    border-radius: var(--cal-pill-radius);
    background-color: var(--cal-subgrid-border);
    overflow: hidden;
}

.cal-matrix-bar-seg { width: var(--cal-matrix-seg-pct, 0%); height: 100%; }
.cal-matrix-bar-seg--focus { background-color: var(--cal-matrix-focus-color); }
.cal-matrix-bar-seg--meetings { background-color: var(--cal-matrix-meeting-color); }
.cal-matrix-bar-seg--buffer { background-color: var(--cal-matrix-buffer-color); }

.cal-matrix-legend { flex-wrap: wrap; gap: 14px; margin-top: 4px; display: flex; }

.cal-matrix-legend-item {
    align-items: center;
    gap: 6px;
    color: var(--rz-text-secondary-color);
    font-size: 12px;
    display: flex;
}

.cal-matrix-legend-dot { width: 8px; height: 8px; border-radius: 50%; }
.cal-matrix-legend-dot--focus { background-color: var(--cal-matrix-focus-color); }
.cal-matrix-legend-dot--meetings { background-color: var(--cal-matrix-meeting-color); }
.cal-matrix-legend-dot--buffer { background-color: var(--cal-matrix-buffer-color); }

.cal-fullcalendar.fc .cal-agenda-location .material-icons-outlined { font-size: 12px; }
