/* ============================================================
   calendar.css
   Calendar tab styles, consolidated from CSS-in-JS modules.

   Loaded once via a stylesheet link in app.html instead of being
   re-injected on every render through DOM-emitted style tags.
   The selector surface is unchanged from the prior JS-string
   versions; classes here are calendar-prefixed and don't collide
   with other tabs (Tailwind utilities are independent).

   Sections:
     1. Layout shell                        (was CalendarResponsiveStyles)
     3. Week header chrome                  (was WeekHeaderStyles)
   ============================================================ */

/* ============================================================
   0. Shared measurements
   ============================================================ */

:root {
    /* How far an event block stops short of the right edge of its day
       column, in the day and week views.

       This strip is not decoration - it is the only empty grid left on a
       busy day, and clicking empty grid is how a new event gets started at
       a particular time. Blocks used to run the full width of the column,
       so a day of back-to-back meetings had nowhere left to click and the
       New event button was the only way in.

       The events overlay is pointer-events:none and the blocks opt back in,
       so the gap falls straight through to the hour cell beneath with no
       extra wiring. */
    --cal-event-gutter: 9px;

    /* Today's marker in the mini-month. Red, not the brand blue, because the
       brand blue already means "selected" in this grid (the day ring) and in
       the views around it - one colour cannot be both the fixed point and the
       cursor. Red is also what every calendar app the user already has marks
       today with, so it needs no learning.

       Not --km-danger: that token means "something is wrong" and gets tuned
       for that job. Today is not an error, and pinning this to a semantic
       danger colour is how a future retune of error states silently repaints
       the calendar.

       #DC3545 clears 4.5:1 against the white numeral on it, which the day
       number needs at 12.6px - a brighter, prettier red does not. */
    --cal-today: #dc3545;
    --cal-today-rgb: 220, 53, 69;

    /* How far an event that has already finished recedes in the lists - the
       agenda and the search results, from their own injected sheets. The
       grids fade by colour instead (--cal-fade 0.3, see the PAST EVENTS block
       below), which keeps their text readable. */
    --cal-past-opacity: 0.45;

    /* The top bar's pill pair: the view switcher (.calendar-view-menu) and
       Today beside it. Both wear the metal ring, so they share one height and
       one corner and read as a pair; size one and the other follows. */
    --cal-pill-height: 27px;
    --cal-pill-radius: 8.1px;
}

/* ============================================================
   1. Layout shell
   ============================================================ */

.calendar-layout {
    display: flex;

    /* Stack the full-width top bar above the calendar body (view + sidebar)
       so the bar spans the entire content panel rather than just the view. */
    flex-direction: column;

    /* Fill the content panel exactly. The old viewport math
       (calc(100vh - 100px)) assumed a fixed 100px of top chrome,
       but the real panel is 100dvh minus the (now variable, 34-42px)
       topbar - so the layout fell ~60px short and left a strip of
       the panel uncovered at the bottom. With the no-accounts lock
       on (inset: 0 within this box) that strip showed through below
       the lock: a white stripe on email, and the real week grid -
       out of phase with the lock's faux grid - on calendar.
       height: 100% fills the parent regardless of topbar size, so
       the lock reaches the bottom edge. */
    height: 100%;

    /* The whole calendar tab shares the content panel's grey canvas. Surfaces
       inside (top bar, view grids, sidebar) read these tokens so they all
       match in both themes; the layout itself is transparent so the panel
       shows through.

       --cal-gutter-surface IS the panel colour (--app-canvas in light, the
       panel's --bg-primary in dark) - the grey the top bar and the Plan view
       show. It used to be a hard-coded #F8F9FA, a shade lighter than the
       panel's #F4F5F7, so the day view and the week's gutters read as a
       different surface from the top bar right above them.

       --cal-surface is what the views paint with, and defaults to the same.

       --cal-grid-surface is the hour grid's own colour: the gutter's, so the
       time column and the working hours read as one surface. The off-hours
       are laid in that colour a shade darker (--cal-offhours-tint, in the
       day and week views). */
    --cal-gutter-surface: var(--app-canvas, #f4f5f7);
    --cal-surface: var(--cal-gutter-surface);
    --cal-grid-surface: var(--cal-gutter-surface);

    /* No gap between the top bar and the body - the bar carries its own
       bottom border. The view/sidebar gutter lives on .calendar-body. */
    gap: 0;

    /* Flush with the content panel - the sidebar carries
       its own bottom-left curve so the layout no longer
       needs outer padding. */
    padding: 0;
    position: relative;

    /* One source for the sidebar's width: .calendar-sidebar's flex-basis, the
       booking panel's offset and the top bar's date-group offset all read
       it, so they cannot drift apart. Declared on the LAYOUT rather than on
       .calendar-body because the top bar is the body's sibling, not its
       child, and has to line its date group up with a column it does not
       contain. It is the sidebar's FOOTPRINT from the row's right edge: the
       glass card (226.3px: 10% narrower than the 251.4px it was, founder,
       5 November 2026, the room going to the view beside it), flush with the content panel's edge - so
       the booking panel, at left: var(--cal-sidebar-w), meets
       the card's right edge. It used to hold its contents a further 10px in
       from that edge, which left an empty strip down the card's right side;
       that 10px went to the view. */
    --cal-sidebar-w: 226.3px;

    /* The air between the joined sidebar-and-view panel and the content
       panel's right edge (founder decision, 2 November 2026): the row's
       right padding. */
    --cal-panel-edge: 10px;

    /* The booking panel's width, declared beside the sidebar's so the two
       numbers live together. */
    --cal-booking-panel-w: 306px;
}

/* A narrower panel on a narrower screen: 340 beside a 254 sidebar leaves a
   1100px window a grid too thin to read a week off. */
@media (width <= 1100px) {
    .calendar-layout {
        --cal-booking-panel-w: 270px;
    }
}

[data-theme='dark'] .calendar-layout {
    /* A shade under the app's dark page colour so the main view sits back. */
    --cal-gutter-surface: color-mix(in srgb, var(--bg-primary) 70%, #000);
    --cal-surface: var(--cal-gutter-surface);
    --cal-grid-surface: var(--cal-gutter-surface);
}

/* The row beneath the full-width top bar: the sidebar (mini-month,
   scheduling, calendars) on the LEFT, flush against the left nav, and the
   active day/week/month view on the right (founder decision, 4 November
   2026). The markup still renders the view first; the sidebar is laid out
   of flow over the row's left edge. */
.calendar-body {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;

    /* 10px under the top bar and off the floor, --cal-panel-edge in from
       the content panel's right edge, and nothing on the left: the sidebar
       is laid over the row's left edge, out of its flow, touching the nav,
       and the view's card keeps the room for it as its left margin. The
       booking panel measures from that same left edge. */
    gap: 0;
    padding: 10px var(--cal-panel-edge) 10px 0;
    overflow: hidden;

    /* Positioning context for the sidebar and the booking panel, which are
       absolutely placed against this row's right edge. */
    position: relative;
}

/* The booking panel: a column that OVERLAYS the grid, pinned to the sidebar's
   right edge, the way Notion Calendar's scheduling panel sits beside its week.

   It used to be a flex item that took its width out of the grid, so opening it
   squeezed the week into whatever was left - and the week is the thing a person
   setting up a link is looking at. It floats over the grid instead: the columns
   behind it keep every pixel they had, and the panel is a card laid on top,
   80% of the row's height with a tenth of it clear above and below so the grid
   reads as continuing behind it rather than being replaced by it.

   Its slot is STILL always in the row (CalendarShellView), out of flow - the
   ~1,100-node week grid beside it is never rebuilt to open or close the panel,
   CalendarTab._syncBookingPanelDom just fills the slot and flips the body class.

   Opacity, not transform: a transform on the slot would make it a containing
   block for the row menu's position: fixed, which has to escape the panel's
   overflow to sit over the grid.

   It is pulled OUT OF the sidebar rather than laid beside it: its left edge
   meets the sidebar's right edge with no gap, it wears the sidebar's colour,
   and it is square and border-less on that side, so the two read as one
   surface. It used to
   stand 12px off the sidebar on a white (or, in dark mode, navy) card with
   every corner rounded, which read as a popup that had landed near the
   sidebar rather than a part of it. */
.cal-booking-panel {
    /* The panel's own surface, so the sticky bars inside it (the editor's tab
       strip and its footer) can paint the same colour the panel does rather
       than each naming a token of their own. The panel wears the sidebar
       card's glass, so its sticky bars take the glass's flat colour. */
    --cal-booking-surface: var(--card-glass-solid);

    position: absolute;
    top: 10%;
    height: 80%;
    left: var(--cal-sidebar-w);
    z-index: 29;
    width: var(--cal-booking-panel-w);
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    background: var(--card-glass-shine), var(--card-glass-bg);
    border: 0.9px solid var(--card-glass-border-color);
    border-left: none;
    border-radius: 0 10.8px 10.8px 0;

    /* Cast RIGHT only: the panel sits over the grid on that side, and the
       shadow is what tells you it is above the week rather than cut into it.
       The offset and negative spread together hold the shadow's left edge
       30px inside the panel - further than its 20px blur reaches - so none of
       it gets round the square edge onto the sidebar, where even a few
       percent of black draws a seam down the join. */
    box-shadow: 14.4px 0 18px -12.6px rgb(0 0 0 / 18%);
    transition:
        opacity 0.2s ease,
        visibility 0.2s;
}

[data-theme='dark'] .cal-booking-panel {
    box-shadow: 14.4px 0 18px -12.6px rgb(0 0 0 / 60%);
}

.calendar-body.has-booking-panel .cal-booking-panel {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}

/* While the panel is editing a link's hours, the grid is the hours editor:
   a drag adds a window rather than an event, and the cursor says so before
   the user finds out. */
.calendar-layout.is-booking-hours-mode .calendar-week-cell,
.calendar-layout.is-booking-hours-mode .calendar-day-cell {
    cursor: copy;
}

@media (prefers-reduced-motion: reduce) {
    .cal-booking-panel {
        transition: none;
    }
}

/* ============================================================
   3. Week header chrome
   ============================================================ */

.calendar-week-header {
    display: flex;
    align-items: center;

    /* Nav + view switcher on the left, action icons (timezone / find-a-time /
       booking / settings / provider cube) pushed to the right. The right
       edge is padded clear of the app's top-right cut-out bay (padding-right
       below) so the provider cube lands just before it. */
    justify-content: space-between;
    padding: 0 10.8px;

    /* Transparent rather than removed. The bar's height is pinned (the
       cut-out's own height) and app.html sizes border-box, so
       the 1px is part of that measurement - it is what makes the bar's bottom
       edge land EXACTLY on the app's top-right cut-out edge rather than a
       hairline above it. Dropping the declaration would move the bar by a
       pixel to hide a line; this hides the line and moves nothing. Same trick
       the email tab's locked state already uses on its own bar. */
    border-bottom: 0.9px solid transparent;

    /* A glass strip (--card-glass-*, the Dashboard widget card's surface),
       like the Email tab's bar: flush with the content panel's left edge, its
       top and its right (the right end runs under the app's top-right
       cut-out), square on the left, where it meets the nav, with a
       see-through left border. Its bottom border is the transparent one
       above, coloured.

       No backdrop-filter. It used to carry blur(16px) "for the stacking
       context the dropdowns rely on", but the positioned z-index below
       already creates that context, so the blur bought nothing - and it
       cost a full-width backdrop layer that the compositor re-sampled and
       re-blurred on every frame the panel's geometry moved, i.e. every
       frame of every nav-rail slide (perf plan Round 8). The glass is a flat
       gradient, so there is nothing to blur. */
    margin-left: 0;
    border-left: 0.9px solid transparent;
    border-bottom-color: var(--card-glass-border-color);
    border-radius: 0;
    background: var(--tab-topbar-bg);
    box-shadow: var(--card-glass-shadow);

    /* On desktop the bar is drawn as two halves (.tb-split,
       SplitTopBarStyles). The right one opens on the date, which is text
       rather than a button with air of its own, so it starts a little
       further out. */
    --tb-split-pad-r: 12.6px;

    /* The left half runs a little past its last control (the week number),
       so the controls don't crowd its rounded end. */
    --tb-split-pad-l: 16px;

    /* Without an explicit z-index the header sits at the equivalent of
       z-index 0, which trapped the timezone / settings dropdowns beneath
       the week grid's events (z-index 5-20) and the current-time indicator
       (z-index 20). position + z-index makes this a stacking context and
       pins the header above any of its siblings in the calendar-main
       column, so the dropdown's own z-index: 1000 actually takes effect. */
    position: relative;
    z-index: 50;

    /* Pad the header's right edge clear of the app's top-right cut-out bay
       so the right-aligned action icons (…, provider cube last) land just
       before it instead of sliding underneath. --topbar-cutout-w is the
       measured cut-out width (AppInterface._trackCutoutWidth); the fallback
       covers the cluster before the first measurement lands.

       Same height as the Email tab's bar, which pins itself to the
       cut-out's full border-box height rather than the compact 53px (see
       .email-list-header.compact in EmailStyles). Two things ride on it:
       the bar's 1px bottom divider lands EXACTLY on the cut-out's bottom
       edge instead of a hairline above it, and Create - stretched to the
       bar - comes out the same 44px tall as Compose rather than 43. */
    height: var(--nav-cutout-height, 46.2px);
    min-height: var(--nav-cutout-height, 46.2px);
    max-height: var(--nav-cutout-height, 46.2px);
    padding-right: calc(var(--topbar-cutout-w, 189px) + 9px);

    /* Keep the reserve in step with the notch's glide when the cut-out
       resizes. Per-consumer, because transitioning --topbar-cutout-w
       itself restyled the whole document each frame. */
    transition: padding-right 0.3s cubic-bezier(0.4, 0, 0.2, 1);

    /* The least the two clusters stand apart. The left one takes all the
       width the right one leaves, so once the search field has narrowed
       to fit, this is what keeps it off the date. */
    column-gap: 14.4px;
}

/* The bar's left half (SplitTopBarStyles) is square on the left too. */
.calendar-week-header.tb-split::before {
    border-left-color: transparent;
    border-radius: 0 var(--radius-xl) var(--radius-xl) 0;
}

.calendar-week-header-title-row {
    display: flex;
    align-items: center;

    /* Full bar height, so Create can stretch to the divider. */
    align-self: stretch;
    gap: 5.4px;

    /* Gives first when the bar runs short, and only down to its own content
       - Create, and the search field at its narrowest. It takes whatever
       width the right cluster leaves rather than shrinking alongside it: a
       basis of 0 that grows, so the right cluster keeps every pixel of its
       own width until this one is at its minimum, and only then does the
       date start to give. A shrink factor would take from both at once, and
       the date would truncate while the field still had room to spare.
       Create stays where it is either way - it leads this cluster, which
       starts at the bar's edge - and so does the date, which is held to the
       right.

       So the box is often wider than what it holds; the bar's split halves
       end at the search control itself (.tb-split-l), not at this box. */
    flex: 1 0 0;
}

/* The Create block used to reserve the width of the sidebar beside it, so
   the date group that followed started on the main panel's left edge - which
   was then a sidebar's width in from the layout's. With the view on the left
   that edge IS the layout's edge, in both sidebar states, and the date group
   simply follows Create. Nothing left to reserve. */

/* Date + year and the two steps that move it - now the head of the RIGHT
   cluster, immediately before the view switcher.

   It has been three things. Centred in the gap the end clusters leave, which
   made the one label read on every glance at this bar the one thing that
   never held still - it slid whenever the space around it changed. Then
   pinned a fixed 48px off the left cluster, which held it still but split the
   bar's busiest reading across both ends: WHICH slice of time at the left
   edge, HOW WIDE a slice at the right. They answer one question between them,
   so they sit together now, and the group needs no pin of its own: it is a
   child of the right cluster, which is already held to the right by the
   header's space-between.

   The arrows sit TOGETHER after the date, back then forward, so they read
   as one pair of controls acting on the label beside them.

   No blanket gap. The four things in here are two pairs - the month and its
   week number, the back and forward steps - and one gap across all of them
   is what made the row read wrong: the label jammed together while the two
   arrows sat a whole button apart. Each pair spaces itself below (the
   subtitle's margin, the arrows' width and the step before the first). */
.calendar-week-header-nav {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 0;
    flex: 0 1 auto;

    /* In the left cluster now, after search (founder decision, 2 November
       2026): the cluster's own 5.4px gap is the step off the search button,
       so the arrows sit right beside it. */
    margin: 0;

    /* Without this a flex item refuses to shrink below its content, and the
       long titles (agenda's "Tue, May 11 - Mon, May 17") would push the rest
       of the cluster towards the cut-out bay instead. */
    min-width: 0;

    /* When it does give, its labels truncate (below) and the arrows hold
       their size; past that, it clips rather than drawing its arrows over
       the view switcher beside it. */
    overflow: hidden;
}

/* The days you are looking at, drawn as a strip behind them - Notion
   Calendar's trick, and the thing the mini-month was missing. Marking only
   today told you where TODAY is, which you rarely need; the strip tells you
   where the main view is pointed, which is the question you actually ask the
   mini-month while paging through weeks.

   ONE element per row, spanning its columns, not a wash on each day. The row
   is a grid with a 4px gap, and a grid item spanning columns 3 to 7 covers
   those gaps as well as the cells - so a week panned to start on Tuesday is
   an unbroken bar from Tuesday to Saturday, and then a second bar on the next
   row for the Sunday and Monday that finish it. It used to be a background on
   each day cell, which left daylight between every square, and it marked only
   the WORKING days of the selected week: Monday to Friday of an aligned week,
   which is neither the run on screen nor a run at all once the week is
   panned.

   It sits under the day buttons (earlier in the DOM, and they draw their own
   backgrounds over it), so today's red square and the selected day's red ring
   land on top of it with nothing to override.

   A translucent black/white wash rather than a theme-specific grey: the card
   sits on different surfaces in the four themes, and one rgba value lands
   correctly on all of them without enumerating each. */
.cal-mini-strip {
    border-radius: 6.3px;
    background: rgb(0 0 0 / 5.5%);
    pointer-events: none;
}

[data-theme='dark'] .cal-mini-strip {
    background: rgb(255 255 255 / 7%);
}

/* Week-number gutter down the left of the mini-month. A label, not a
   control: no hover, no cursor, out of the tab order, and faded to the
   tertiary ink at a smaller size so the seven dates beside it still lead the
   eye. The strip behind the viewed week stops at the dates (the number is
   not one of the days of that week), so this sits clear of it. */
.cal-mini-weekno {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 8.5px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--text-tertiary);
    opacity: 0.65;
    user-select: none;
    pointer-events: none;
}

/* Mini-month day cells: quiet hover tint. Replaces the inline
   onmouseover/onmouseout handlers removed in the CSP (data-cal-*) migration.
   Today keeps its filled red square (excluded here); the selected day's
   ring sits over a transparent fill, so it still takes the tint on hover.
   !important overrides the per-cell inline `background: transparent`. */
.cal-mini-day:not(.is-today):hover {
    background: var(--bg-hover) !important;
}

/* Over the strip, --bg-hover is within a couple of percent of the wash
   itself, so the plain hover above reads as no hover at all on exactly the
   days the pointer spends most of its time on. Deepen it to the same wash,
   twice over. The class is on the day (not the strip) only so this rule has
   something to key off; the strip itself is what draws the grey. */
.cal-mini-day.in-view:not(.is-today):hover {
    background: rgb(0 0 0 / 11%) !important;
}

[data-theme='dark'] .cal-mini-day.in-view:not(.is-today):hover {
    background: rgb(255 255 255 / 15%) !important;
}

.calendar-week-header-title {
    /* 15.75px (15 x the tab's 1.05 scale) until it moved to the head of its
       own centred cluster - the label the arrows act on, so it carries a
       little more weight than it did tucked behind them. Then 16.8px, then
       18.9px (18 x 1.05), and 17px since the app's sizes were redrawn at 0.9:
       it is the one label read on every glance at this bar, and at the old
       size it sat level with the controls around it instead of leading them. */
    font-size: 17px;
    font-weight: 700;
    color: var(--text-primary);
    white-space: nowrap;

    /* The second thing to give when the date group runs short, after the
       week number: an ellipsis says the label goes on, where a clipped
       "October 202" would read as a different year. */
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* The two steps, as glyphs. They were filled, bordered boxes - two hard
   rectangles in a bar whose other controls (search, the gear) are bare icons,
   which made the pair read as heavier than the date they act on. Chevrons
   alone say the same thing: the box was never carrying meaning, only weight.

   The hit area stays the full icon box, so nothing got harder to press; only
   the paint is gone. Hover changes the ink rather than filling a shape back
   in, and the keyboard ring is drawn explicitly, because with no border and
   no background a focused arrow would otherwise be indistinguishable from an
   unfocused one.

   24px wide rather than the bar's 34.5px icon box, and nothing between the
   two: at the full box the chevrons stood a whole button apart and read as
   two controls rather than one pair. 24px is the smallest a pointer target
   should be; touch keeps a bigger one (the pointer: coarse rule in
   CalendarWeekView), and the height stays the mini-month arrows' 28px. */
.calendar-week-nav-btn {
    /* Never what gives: the labels before them do. */
    flex-shrink: 0;
    width: 21.6px;
    height: 25.2px;
    background: none;
    border: none;
    border-radius: 8.1px;
    padding: 0;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-secondary);
    transition:
        color 0.18s cubic-bezier(0.4, 0, 0.2, 1),
        transform 0.18s cubic-bezier(0.4, 0, 0.2, 1);
}

.calendar-week-nav-btn:hover {
    color: var(--brand-primary);
}

.calendar-week-nav-btn:focus-visible {
    outline: 1.8px solid var(--brand-primary);
    outline-offset: -1.8px;
}

.calendar-week-nav-btn:active {
    transform: scale(0.92);
}

/* The pair leads the group, beside the search button, and the date stands a
   clear step off it - wider than the step between the two arrows, so they
   group with each other rather than with the date. */
.calendar-week-nav-btn + .calendar-week-header-title {
    margin-left: 9px;
}

/* Today follows the date it takes you back from, a step off whichever label
   comes last (the week number is opt-in). */
.calendar-week-header-title + .calendar-week-today-btn,
.calendar-week-header-subtitle + .calendar-week-today-btn {
    margin-left: 10.8px;
}

/* Today leads the right cluster, directly before the date it takes you back
   from, and is drawn as the view switcher's partner: the same height and corner
   (--cal-pill-height / --cal-pill-radius) and the same metal ring - the
   shared hairline and glint (MetalRingStyles.js), opted into with the
   `metal-ring` class in the markup, so the two run on one ring rule and one
   clock rather than a copy of it. Still well clear of the 24px it used to be.

   The ring is laid over a 0.9px border, as on the switcher. That border is
   transparent and the fill stops at it (padding-box), so the ring's outer
   half sits on the bar exactly as the switcher's does instead of tinting a
   red hairline. Hover darkens the fill only: the switcher's ring does not
   change on hover or focus, so Today's doesn't either.

   It wears the today red (--cal-today), not the brand blue: today is already
   red everywhere else in the tab - the day number in the mini-month, the
   column header, the now-line - so the button that takes you there says the
   same thing in the same colour, instead of being one more blue control in a
   row of them.

   FILLED red with white text, rather than the red-on-white outline it used to
   be: it is the one control in the bar you press without looking for it, and
   an outlined pill in a row of quiet, transparent icon buttons still read as
   one of them. The solid fill is the same red, so it says the same thing
   louder - and white text on #dc3545 clears 4.5:1, in both themes. */
.calendar-week-today-btn {
    /* In the right cluster, which may shrink: the date gives, Today holds. */
    flex-shrink: 0;

    /* The last thing in the date group, so nothing after it to step off. */
    margin-right: 0;
    white-space: nowrap;
    box-sizing: border-box;
    height: var(--cal-pill-height);
    padding: 0 12.6px;
    border-radius: var(--cal-pill-radius);
    background: var(--cal-today) padding-box;
    border: 0.9px solid transparent;
    cursor: pointer;
    font-size: var(--cutout-pill-font, 11.3px);
    font-weight: 600;
    color: #fff;
    transition: all 0.18s cubic-bezier(0.4, 0, 0.2, 1);
    font-family: inherit;
    box-shadow: 0 0.9px 1.8px rgb(0 0 0 / 8%);

    /* Its metal ring glints in the same red, not the pills' aqua: the ring
       belongs to the button, and the button is today's colour. */
    --metal-ring-rgb: var(--cal-today-rgb);
}

/* Same fill either side of the theme switch - the red is the point, and the
   dark theme's own surfaces would only mute it. */
[data-theme='dark'] .calendar-week-today-btn {
    background: var(--cal-today) padding-box;
    border-color: transparent;
    color: #fff;
}

/* Hover darkens the fill rather than tinting a white one - the filled button
   has nowhere to tint. background-color only, so the fill keeps stopping at
   the border and the ring over it stays as it is at rest. */
.calendar-week-today-btn:hover,
[data-theme='dark'] .calendar-week-today-btn:hover {
    background-color: #bb2d3b;
    color: #fff;
}

.calendar-week-today-btn:active {
    transform: scale(0.93);
}

/* Today is somewhere on screen, so there is nothing to go back to: the button
   is not shown at all. Page away until today drops out of the range and it
   appears, filled red, as the way back.

   Visible - not selected. Looking at this week with Wednesday picked, today is
   right there, so the button stays away even though pressing it would still
   move the selection; T still does that from the keyboard.

   .is-today-visible is stamped at render time and kept in step by
   CalendarTab._syncTodayButton, since the grid-scoped refresh leaves the
   header's controls mounted. */
.calendar-week-today-btn.is-today-visible {
    display: none;
}

/* A no-op press is the only one that loses the pointer. */
.calendar-week-today-btn[aria-disabled='true'] {
    cursor: default;
}

/* Only the no-op press loses the press animation - a quiet-but-live button
   should still respond when you click it. */
.calendar-week-today-btn[aria-disabled='true']:active {
    transform: none;
}

/* Leading "Create" new-event button - the tab's primary action, labelled
   rather than a bare "+" glyph so it says what it does, and matched to the
   Email tab's "Compose" button (.email-compose-icon-btn: 34px tall, 0 14px
   padding, 9px radius) so the two tabs' primary actions read as the same
   control. (Class name is historical - it was the "+" icon button.) */

/* Create fills the top bar's LEFT END rather than floating as a pill inset
   from it - the mirror of the Email tab's Compose (see .email-compose-icon-btn
   in EmailStyles): out through the header's own 12px left padding to the
   bar's edge, and stretched to the bar's full height. Its left corners follow
   the bar's rounded ones (less the bar's 0.9px edge), so the button does not
   square off the curve it sits in.

   It grows up, down and LEFT only; the width is otherwise the label's, so
   "Create" reads exactly as it did. */
.calendar-week-add-btn {
    flex-shrink: 0;
    box-sizing: border-box;

    /* Stretched by .calendar-week-header-title-row, itself stretched to the bar. */
    align-self: stretch;
    height: auto;

    /* Cancels the header's padding: 0 12px so the left edge lands on the
       panel's. The header is a flex row, so this moves the button alone. */
    margin-left: -10.8px;
    padding: 0 12.6px;

    /* The corner block is the same size in every tab - see
       --tab-primary-action-w (TemplateBuilder) and the Email tab's
       .email-compose-icon-btn, which carries the same floor. Without it
       "Create" sized to its own label and came out 19px narrower than
       "Compose", so the block visibly changed shape between the two tabs.
       A floor, not a fixed width: a longer label still sizes the button.
       10px over the corner block: the bar runs flush into the nav now. */
    min-width: calc(var(--tab-primary-action-w, 88.2px) + 10px);

    /* Square on the left, flush with the panel's top-left corner and the
       nav; rounded on the right like the bar's left half. */
    border-radius: 0 calc(var(--radius-xl) - 0.9px) calc(var(--radius-xl) - 0.9px) 0;
    border: none;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: #fff;
    font-family: inherit;
    font-size: var(--tab-topbar-font, 12.3px);
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    background: var(--brand-gradient, var(--brand-primary));
    box-shadow: 0 0.9px 2.7px rgb(20 51 210 / 22%);
    transition:
        filter 0.15s ease,
        transform 0.06s ease;
    margin-right: 1.8px;
}

.calendar-week-add-btn:hover {
    filter: brightness(1.06);
}

.calendar-week-add-btn:active {
    transform: scale(0.93);
}

/* Day / Week / Month pill toggle - mirrors the Email tab's
   .email-detail-tabs pill, calendar-namespaced and scaled to the 44px bar. */

/* Calendar view switcher: a single hover/focus-expand dropdown (mirrors the
   email tab's view-mode changer). At rest only the active view's row shows
   (icon + label); hovering or focusing the control drops the other views
   down beneath it, and clicking one switches. The resting surface AND the
   active-row treatment match the email control: an elevated pill with a soft
   shadow, aqua-accent (--brand-accent) text/icons, and an aqua-tinted active
   row, so restyling here keeps the switcher identical to the email view-mode
   changer. */

/* The control sizes to the ACTIVE option's icon + label (adaptive width), just
   like the email tab's view-mode changer: the active row sits in normal flow,
   the rest live in an overlay that never widens or heightens the header. */
.calendar-view-menu {
    position: relative;
    flex-shrink: 0;
    align-self: center;
    display: inline-flex;
    height: var(--cal-pill-height);
    padding: 1.8px;

    /* Resting surface matches the email view-mode control: an elevated
       background with a soft shadow. The var adapts per theme, so no
       light/dark-specific overrides are needed. */
    background: var(--bg-elevated);

    /* NB: var(--border-light) is the full "1px solid <color>" shorthand, so it
       is used WITHOUT a "1px solid" prefix (that would expand to invalid CSS). */
    border: var(--border-light);
    border-radius: var(--cal-pill-radius);
    box-shadow: 0 1.8px 7.2px rgb(0 0 0 / 8%);
    z-index: 5;
}

/* Wearing the metal ring (MetalRingStyles.js): no fill and 1px of padding,
   so the ring covers border and padding and the tinted option sits right
   against it. The create-event category picker keeps the surface above. */
.calendar-view-menu.metal-ring {
    padding: 0.9px;
    background: transparent;
}

.calendar-view-menu-btn {
    appearance: none;
    display: inline-flex;
    align-items: center;
    gap: 6.3px;
    height: 23.4px;
    padding: 0 9px;
    background: transparent;
    border: none;
    border-radius: 6.3px;
    color: var(--brand-accent, #2596be);
    font-family: inherit;
    font-size: 11.8px;
    font-weight: 600;
    line-height: 1;
    text-align: left;
    white-space: nowrap;
    cursor: pointer;
    transition:
        background 0.15s ease,
        color 0.15s ease;
}

.calendar-view-menu-btn:hover {
    background: rgba(var(--brand-accent-rgb, 37, 150, 190), 0.12);
}

.calendar-view-menu-btn.active {
    background: rgba(var(--brand-accent-rgb, 37, 150, 190), 0.14);
    color: var(--brand-accent, #2596be);
}

.calendar-view-menu-icon {
    display: inline-flex;
    flex-shrink: 0;
    color: inherit;
}

.calendar-view-menu-icon svg {
    width: 13.5px;
    height: 13.5px;
}

/* The caret on the active row of a `chevron` menu: the one thing the control
   has to promise, which is that there is a list behind it. It sits AFTER the
   label (margin-left: auto pins it to the trailing edge however wide the
   label is) and flips over when the list is actually open, so it reads as the
   state it is in rather than as decoration.

   Quieter than the label by design - it is the hinge, not the answer. */
.calendar-view-menu-caret {
    display: inline-flex;
    flex-shrink: 0;
    margin-left: auto;
    color: inherit;
    opacity: 0.75;
    transition: transform 0.15s ease;
}

.calendar-view-menu-caret svg {
    width: 11.7px;
    height: 11.7px;
}

.calendar-view-menu:hover .calendar-view-menu-caret,
.calendar-view-menu:focus-within .calendar-view-menu-caret {
    transform: rotate(180deg);
}

@media (prefers-reduced-motion: reduce) {
    .calendar-view-menu-caret {
        transition: none;
    }
}

/* Non-active rows drop into an overlay flush under the control, sized to the
   widest option; left-aligned by default (for menus in the header's left
   cluster, so they never run off-screen). */
.calendar-view-menu-pop {
    position: absolute;
    top: 100%;
    left: -0.9px;
    right: auto;
    min-width: 100%;
    width: max-content;
    margin-top: 2.7px;
    display: none;
    flex-direction: column;
    gap: 1.8px;
    padding: 1.8px;
    background: var(--bg-elevated);
    border: var(--border-light);
    border-radius: 8.1px;
    box-shadow: 0 3.6px 10.8px rgb(0 0 0 / 12%);
    z-index: 60;
}

/* Transparent bridge over the 3px gap so moving the cursor down to an option
   doesn't drop the hover (matches the email view-mode changer). */
.calendar-view-menu-pop::before {
    content: '';
    position: absolute;
    top: -4.5px;
    left: 0;
    right: 0;
    height: 4.5px;
}

.calendar-view-menu-pop .calendar-view-menu-btn {
    width: 100%;
}

.calendar-view-menu:hover .calendar-view-menu-pop,
.calendar-view-menu:focus-within .calendar-view-menu-pop {
    display: flex;
}

/* View menus in the RIGHT cluster (the layout + range switchers, ahead of the
   "More" menu) right-align their overlay: a left-aligned pop would open toward
   the header's edge and clip. */
.calendar-week-header-actions .calendar-view-menu-pop {
    left: auto;
    right: -0.9px;
}

/* An event sheet parked on another tab.

   The create form, the editor and the event read view are mounted on <body>,
   deliberately: a background re-render of the calendar must not be able to
   wipe a half-written event. But <body> outlives the tab, so a form left open
   and a tab switch used to put the Calendar tab's event sheet over the Email
   tab, the dashboard and everything else - a modal from a workspace the user
   had left, with a Create button for a grid that was no longer on screen.

   Each one belongs to the workspace it was opened from, which is not always
   this one: the same form opens docked in the Email tab's day panel, and the
   assistant can open one from anywhere. CalendarActions._bindOverlayToActiveView
   stamps the owner on the overlay and toggles this class on every view change.

   Hidden, not closed: half a typed event is worth keeping, so coming back
   brings it out exactly as it was. display: none also makes the focus trap
   inert on its own - the trap's keydown listener is on the overlay, and
   nothing inside a hidden element can take focus.

   Here rather than in either modal's own injected \3c style> because this sheet
   is linked from app.html and is therefore always present, whichever of the
   two the user happens to open first. !important because the inline docking
   writes geometry straight onto the element. */
#create-event-modal.is-off-view,
#event-detail-modal.is-off-view {
    display: none !important;
}

/* Drag-to-create selection band. Painted (position: fixed, body-level) while
   the user click-drags across an empty day/week grid to mark out a new event's
   time range; removed on release when the event form opens. */
.calendar-create-selection {
    position: fixed;
    z-index: 9999;
    box-sizing: border-box;
    padding: 2.7px 5.4px;
    border: 1.4px solid var(--brand-primary);
    border-radius: 5.4px;
    background: color-mix(in srgb, var(--brand-primary) 22%, transparent);
    color: var(--brand-primary);
    font-size: 10.4px;
    font-weight: 700;
    line-height: 1.3;
    overflow: hidden;
    pointer-events: none;
    box-shadow: 0 1.8px 7.2px rgb(0 0 0 / 12%);
}

[data-theme='dark'] .calendar-create-selection {
    background: color-mix(in srgb, var(--brand-primary) 30%, transparent);
    color: #fff;
}

/* A step off the month it qualifies, so the label reads as a month and a
   note on it rather than one run-on string. */
.calendar-week-header-subtitle {
    font-size: 11.3px;
    color: var(--text-tertiary);

    /* The first thing to give when the date group runs short - it is a note
       on the month, not the month - and on one line while it does: it used
       to wrap to "Week" over "41". A basis of 0 that grows takes exactly
       what the title and the arrows leave, so it truncates before the title
       loses a letter (the title row's rule above does the same between the
       two clusters). */
    flex: 1 0 0;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Its step off the month, drawn inside it rather than as a margin, so it
   goes with the label when the label gives - a margin would stay behind,
   9px of nothing taken from the arrows on the narrowest bars. */
.calendar-week-header-subtitle::before {
    content: '';
    display: inline-block;
    width: 9px;
}

.calendar-week-header-actions {
    display: flex;
    align-items: center;
    gap: 5.4px;

    /* The date group moved in here, so this cluster is no longer purely
       fixed-width: it may shrink, and when it does the date's min-width: 0
       is what gives (the switcher and the icons hold their size). The left
       cluster still holds its width, so Create never moves. */
    flex: 0 1 auto;
    min-width: 0;
}

/* The header's icon glyphs, sized from CSS rather than their inline
   width/height attributes so they track the navigation-size setting like
   the buttons around them. CSS width/height win over those attributes. */
.calendar-week-header .calendar-week-nav-btn svg,
.calendar-week-header .calendar-settings-btn svg {
    width: var(--tab-topbar-icon-glyph, 18.6px);
    height: var(--tab-topbar-icon-glyph, 18.6px);
}

/* Header search, in the LEFT cluster after Create and always open, as in
   Email. Enter opens the results view (CalendarSearchResultsView).
   The Email and Files tabs' search pill, to the pixel: 38px tall, the
   light border, the elevated fill, fully rounded. 324px when the bar has the
   room, capped on narrow windows, and narrowing to 162px when it has not (a
   little less on the smallest screens, where the date's arrows need what is
   left): a flex basis rather than a width, so it is the first thing in the
   bar to give (see .calendar-week-header-title-row). */
.calendar-header-search-bar {
    display: flex;
    align-items: center;
    gap: 7.2px;
    box-sizing: border-box;
    flex: 0 1 324px;
    max-width: 30vw;
    min-width: min(162px, 13vw);
    height: 34.2px;
    padding: 0 5.4px 0 10.8px;
    background: var(--bg-elevated);
    border: var(--border-light);
    border-radius: 999px;
}

.calendar-header-search-icon {
    flex-shrink: 0;
    width: var(--tab-topbar-icon-glyph, 18.6px);
    height: var(--tab-topbar-icon-glyph, 18.6px);
    color: var(--text-tertiary);
}

.calendar-header-search-input {
    flex: 1;
    min-width: 0;

    /* Sized by the flex above, not by its own default width, which would
       otherwise hold the field open past its min-width when the bar runs
       short. */
    width: 0;
    height: 100%;
    padding: 0;
    font-size: var(--tab-topbar-font, 12.3px);
    font-family: inherit;
    color: var(--text-primary);
    background: transparent;
    border: none;
    outline: none;
}

.calendar-header-search-input::placeholder {
    color: var(--text-tertiary);
}

/* The browser's own clear (x) control would double up with our close button. */
.calendar-header-search-input::-webkit-search-cancel-button {
    display: none;
}

.calendar-header-search-close {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 25.2px;
    height: 25.2px;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: var(--text-tertiary);
    cursor: pointer;
    transition:
        background 0.15s ease,
        color 0.15s ease;
}

.calendar-header-search-close:hover {
    background: rgb(0 0 0 / 5%);
    color: var(--text-primary);
}

[data-theme='dark'] .calendar-header-search-close:hover {
    background: rgb(255 255 255 / 8%);
}

.calendar-timezone-wrapper {
    position: relative;
}

.calendar-timezone-btn {
    display: flex;
    align-items: center;
    gap: 3.6px;
    padding: 3.6px 7.2px;
    background: rgb(255 255 255 / 72%);
    backdrop-filter: blur(10.8px);
    border: 0.9px solid rgb(255 255 255 / 45%);
    border-radius: 6.3px;
    font-size: 10.4px;
    cursor: pointer;
    color: var(--text-secondary);
    transition: all 0.18s cubic-bezier(0.4, 0, 0.2, 1);
    font-family: inherit;
    box-shadow: 0 0.9px 1.8px rgb(0 0 0 / 4%);
}

[data-theme='dark'] .calendar-timezone-btn {
    background: rgb(30 30 30 / 65%);
    border-color: rgb(255 255 255 / 8%);
}

.calendar-timezone-btn:hover {
    background: rgb(212 175 55 / 6%);
    border-color: rgb(212 175 55 / 20%);
    color: var(--brand-primary);
}

.calendar-timezone-dropdown {
    position: absolute;
    top: 100%;
    right: 0;
    margin-top: 3.6px;

    /* Opaque surface: the dropdown floats over the week grid, so a
       translucent fill let the events show through and made the list
       hard to read. Solid background keeps it legible. */
    background: var(--bg-primary);
    border: var(--border-light);
    border-radius: 12.6px;
    box-shadow:
        0 7.2px 28.8px rgb(0 0 0 / 12%),
        0 0 0 0.5px rgb(0 0 0 / 4%);
    z-index: 1000;
    min-width: 288px;
    max-height: 360px;
    overflow-y: auto;
}

[data-theme='dark'] .calendar-timezone-dropdown {
    background: var(--bg-primary);
    border-color: rgb(255 255 255 / 8%);
    box-shadow: 0 7.2px 28.8px rgb(0 0 0 / 35%);
}

.calendar-timezone-dropdown::-webkit-scrollbar {
    width: 5.4px;
}

.calendar-timezone-dropdown::-webkit-scrollbar-track {
    background: transparent;
}

.calendar-timezone-dropdown::-webkit-scrollbar-thumb {
    background: var(--border-light);
    border-radius: 2.7px;
}

.calendar-timezone-dropdown::-webkit-scrollbar-thumb:hover {
    background: var(--text-tertiary);
}

.timezone-region-header {
    padding: 5.4px 10.8px;
    font-size: 9.5px;
    font-weight: 600;
    color: var(--text-tertiary);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    background: var(--bg-hover);
    position: sticky;
    top: 0;
}

.timezone-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: calc(100% - 7.2px);
    padding: 6.3px 10.8px;
    background: transparent;
    border: none;
    cursor: pointer;
    text-align: left;
    transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
    font-family: inherit;
    border-radius: 7.2px;
    margin: 0.9px 3.6px;
}

.timezone-item:hover {
    background: rgb(0 0 0 / 4%);
}

[data-theme='dark'] .timezone-item:hover {
    background: rgb(255 255 255 / 6%);
}

.timezone-item.active {
    background: rgb(212 175 55 / 8%);
}

.timezone-item-label {
    font-size: 11.3px;
    color: var(--text-primary);
}

.timezone-item.active .timezone-item-label {
    color: var(--brand-primary);
    font-weight: 600;
}

.timezone-item-offset {
    font-size: 10.4px;
    color: var(--text-tertiary);
}

.calendar-create-btn {
    padding: 6.3px 12.6px;
    background: var(--brand-gradient);
    backdrop-filter: var(--glass-blur);
    color: white;
    border: 0.9px solid rgb(255 255 255 / 25%);
    border-radius: 10.8px;
    font-size: 11.8px;
    font-weight: 600;
    letter-spacing: -0.01em;
    cursor: pointer;
    transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
    white-space: nowrap;
    font-family: inherit;
    box-shadow:
        0 0.9px 2.7px rgb(0 0 0 / 12%),
        0 5.4px 18px rgb(0 0 0 / 10%),
        inset 0 0.9px 0 rgb(255 255 255 / 20%);
    position: relative;
    overflow: hidden;
}

.calendar-create-btn::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 50%;
    background: linear-gradient(to bottom, rgb(255 255 255 / 18%), transparent);
    border-radius: 10.8px 10.8px 0 0;
    pointer-events: none;
}

.calendar-create-btn:hover {
    transform: translateY(-0.9px);
    box-shadow:
        0 1.8px 5.4px rgb(0 0 0 / 15%),
        0 7.2px 21.6px rgb(0 0 0 / 12%),
        inset 0 0.9px 0 rgb(255 255 255 / 25%);
}

.calendar-create-btn:active {
    transform: translateY(0) scale(0.98);
}

[data-theme='dark'] .calendar-create-btn {
    box-shadow:
        0 0.9px 2.7px rgb(212 175 55 / 30%),
        0 5.4px 18px rgb(212 175 55 / 25%),
        inset 0 0.9px 0 rgb(255 255 255 / 15%);
}

[data-theme='dark'] .calendar-create-btn:hover {
    box-shadow:
        0 1.8px 5.4px rgb(212 175 55 / 35%),
        0 7.2px 21.6px rgb(212 175 55 / 30%),
        inset 0 0.9px 0 rgb(255 255 255 / 20%);
}

/* Mirror the Email tab's .icon-btn chrome so the gear/refresh
   buttons sitting next to the platform icons look identical across
   tabs - transparent ground, 30x30 hit area, 18x18 glyph. */
.calendar-settings-btn {
    width: var(--tab-topbar-icon-box, 31.1px);
    height: var(--tab-topbar-icon-box, 31.1px);
    padding: 0;
    border-radius: 8.1px;
    background: transparent;
    border: none;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--text-secondary);
    transition: all 0.18s cubic-bezier(0.4, 0, 0.2, 1);
}

.calendar-settings-btn:hover {
    background: rgb(0 0 0 / 5%);
    color: var(--text-primary);
}

[data-theme='dark'] .calendar-settings-btn:hover {
    background: rgb(255 255 255 / 8%);
}

.calendar-settings-btn:active {
    background: rgb(0 0 0 / 8%);
    transform: scale(0.94);
}

[data-theme='dark'] .calendar-settings-btn:active {
    background: rgb(255 255 255 / 10%);
}

/* ============================================================
   Header action buttons (Settings + Booking link) sit inline to the
   right of the timezone selector. The wrapper stays the positioning
   context for the dropdowns those buttons open.
   ============================================================ */

.calendar-header-overflow {
    position: relative;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 1.8px;
}

/* The docked create/edit form is repositionable by its header - wired up in
   CalendarActions._enableInlineFormDrag, so the class is only present on the
   inline presentation, which is the one where dragging works. */
.event-modal-header.is-draggable {
    cursor:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28' viewBox='0 0 32 32'%3E%3Cpath d='M10 14V7a2 2 0 0 1 4 0v6h1V5a2 2 0 0 1 4 0v8h1V7a2 2 0 0 1 4 0v10c0 5-3 9-8 9h-1c-3 0-5-1-6.5-3.5L8 24l-3.2-4.2a2 2 0 0 1 3.1-2.5L10 20z' fill='%231f2937' stroke='%23fff' stroke-width='1.5' stroke-linejoin='round'/%3E%3C/svg%3E")
            10 6,
        grab;
    touch-action: none;
    user-select: none;
}

.event-modal-header.is-dragging {
    cursor:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28' viewBox='0 0 32 32'%3E%3Cpath d='M10 16v-3a2 2 0 0 1 4 0v2h1v-4a2 2 0 0 1 4 0v4h1v-3a2 2 0 0 1 4 0v5c0 5-3 9-8 9h-1c-3 0-5-1-6.5-3.5L8 24l-3.2-4.2a2 2 0 0 1 3.1-2.5L10 21z' fill='%231f2937' stroke='%23fff' stroke-width='1.5' stroke-linejoin='round'/%3E%3C/svg%3E")
            10 8,
        grabbing;
}

/* Touch feedback for cells / event chips that suppress the OS tap-highlight.
   Several views set `-webkit-tap-highlight-color: transparent` (calendar
   month / day / week event chips, reauth banner buttons) to avoid the dark
   blue flash on iOS / Android. Without a replacement the user gets zero
   feedback when tapping. These :active rules add a subtle press state on
   pointer-coarse devices only - desktop hover styles continue to handle
   the mouse case. */
@media (pointer: coarse) {
    .calendar-day-cell:active {
        background: rgb(0 0 0 / 4%);
    }

    [data-theme='dark'] .calendar-day-cell:active {
        background: rgb(255 255 255 / 6%);
    }

    .calendar-week-cell:active {
        background: rgb(212 175 55 / 6%);
    }

    .calendar-week-event-positioned:active,
    .calendar-day-cell-event:active,
    .calendar-event-badge:active {
        opacity: 0.78;
        transform: scale(0.985);
    }
}

/* Hide the chat-bridge "pending event" banner whenever a calendar modal is
   visible. Without this the banner sits behind the modal backdrop and
   re-appears each time the modal closes - the banner is only meant to
   surface when the user is *between* flows, not while they're already
   editing. Uses :has() (Chrome 105+, FF 121+, Safari 15.4+); the codebase
   already relies on similarly-modern CSS in the calendar styles. */
body:has(#create-event-modal),
body:has(#event-detail-modal),
body:has(.event-modal-backdrop),
body:has(.edm-backdrop) {
    .kabiri-pending-event-banner {
        display: none !important;
    }
}

.calendar-settings-toggle {
    position: relative;
    width: 39.6px;
    height: 21.6px;
    background: rgb(0 0 0 / 9%);
    border-radius: 10.8px;
    cursor: pointer;
    transition: background 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    border: none;
}

[data-theme='dark'] .calendar-settings-toggle {
    background: rgb(255 255 255 / 10%);
}

.calendar-settings-toggle.active {
    background: #34c759;
}

.calendar-settings-toggle::after {
    content: '';
    position: absolute;
    top: 1.8px;
    left: 1.8px;
    width: 18px;
    height: 18px;
    background: white;
    border-radius: 50%;
    transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    box-shadow:
        0 0.9px 2.7px rgb(0 0 0 / 15%),
        0 0.9px 0.9px rgb(0 0 0 / 6%);
}

.calendar-settings-toggle.active::after {
    transform: translateX(18px);
}

/* Event Type Filter Toggle - Apple Segmented Control */
.calendar-event-type-filter {
    display: flex;
    align-items: center;
    gap: 1.8px;
    background: rgb(0 0 0 / 4%);
    border: 0.9px solid rgb(0 0 0 / 4%);
    border-radius: 8.1px;
    padding: 1.8px;
}

[data-theme='dark'] .calendar-event-type-filter {
    background: rgb(255 255 255 / 6%);
    border-color: rgb(255 255 255 / 4%);
}

.calendar-event-type-btn {
    padding: 4.5px 9.9px;
    background: transparent;
    border: none;
    border-radius: 6.3px;
    font-size: 11.3px;
    font-weight: 500;
    cursor: pointer;
    color: var(--text-secondary);
    transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
    font-family: inherit;
    white-space: nowrap;
    display: flex;
    align-items: center;
    gap: 5.4px;
}

.calendar-event-type-btn:hover {
    color: var(--text-primary);
}

.calendar-event-type-btn.active {
    background: var(--bg-primary);
    color: var(--text-primary);
    font-weight: 600;
    box-shadow:
        0 0.9px 2.7px rgb(0 0 0 / 8%),
        0 0.9px 1.8px rgb(0 0 0 / 4%);
}

[data-theme='dark'] .calendar-event-type-btn.active {
    background: rgb(255 255 255 / 12%);
}

.calendar-event-type-btn.work-active {
    background: rgba(var(--brand-primary-rgb), 0.12);
    color: var(--brand-primary);
    font-weight: 600;
    box-shadow: 0 0.9px 2.7px rgba(var(--brand-primary-rgb), 0.1);
}

.calendar-event-type-btn.personal-active {
    background: rgb(16 185 129 / 12%);
    color: var(--accent-green);
    font-weight: 600;
    box-shadow: 0 0.9px 2.7px rgb(16 185 129 / 10%);
}

.event-type-indicator {
    width: 7.2px;
    height: 7.2px;
    border-radius: 50%;
}

.event-type-indicator.work {
    background: var(--brand-primary);
}

.event-type-indicator.personal {
    background: var(--accent-green);
}

/* ============================================================
   Inline task checkbox (day & week views). Shown on task blocks and
   all-day task pills so a task can be ticked complete / incomplete
   without opening it. currentColor keeps the empty box legible on the
   task's own fill; the done state fills with the brand colour.
   ============================================================ */

.calendar-task-check {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 12.6px;
    height: 12.6px;
    flex-shrink: 0;
    margin-right: 4.5px;
    vertical-align: middle;
    border: 1.4px solid currentcolor;
    border-radius: 3.6px;
    color: inherit;
    cursor: pointer;
    opacity: 0.85;
    transition:
        background 0.12s ease,
        border-color 0.12s ease,
        opacity 0.12s ease;
}

.calendar-task-check:hover {
    opacity: 1;
}

.calendar-task-check svg {
    opacity: 0;
}

.calendar-task-check.is-done {
    background: var(--brand-primary, #1433d2);
    border-color: var(--brand-primary, #1433d2);
    color: #fff;
    opacity: 1;
}

.calendar-task-check.is-done svg {
    opacity: 1;
}

/* A block of tasks that end together ("2 tasks", utils/taskGroups.js) with
   some of them done: the box fills from the bottom by the share that is
   done, in the done colour, with no tick - some done, not all. */
.calendar-task-check.cal-task-group-check.is-partial {
    border-color: var(--brand-primary, #1433d2);
    background: linear-gradient(
        to top,
        var(--brand-primary, #1433d2) var(--cal-group-done, 50%),
        transparent var(--cal-group-done, 50%)
    );
    opacity: 1;
}

/* Completed tasks fade back in the day & week grids so finished work reads as
   done at a glance (the ticked checkbox already marks the state). In the
   timed grid the fade is colour (--cal-fade, see PAST EVENTS below), so the
   block stays solid over the grid lines. */
.calendar-week-event-positioned.calendar-task-done,
.calendar-day-cell-event.calendar-task-done {
    --cal-fade: 0.5;
    --cal-event-ink: var(--text-tertiary);
}

.calendar-allday-pill.calendar-task-done,
.calendar-day-allday-pill.calendar-task-done,
.calendar-agenda-event.calendar-task-done,
.calendar-event-badge.calendar-task-done {
    opacity: 0.5;
}

/* ============================================================================
   PAST EVENTS
   Anything that has already finished recedes, so the grid reads forwards:
   what is left at full strength is what is still ahead of you. Notion
   Calendar's trick, and the reason its week looks like a plan rather than a
   log. The rule is CalendarUtils.isPastEvent - end < now, ends exclusive -
   stamped at render time and swept on the minute by refreshPastEvents.

   The fade is colour, not opacity. Every block - timed tile, all-day pill,
   month bar and chip - paints its wash and text through
   CalendarUtils.solidWash / EVENT_INK, which read --cal-fade (how
   much of the event's colour is left over the grid surface) and
   --cal-event-ink: the block recedes but stays SOLID. Opacity dimmed the
   tile too, but let the hour and day lines show through every past event -
   and it faded the text with the fill, which left it short of 4.5:1 on every
   colour in the light theme.

   The words fade with the block: a past event's title and time keep the
   event's own ink (EVENT_INK / EVENT_COLOUR_INK) at 65% strength, so the
   whole tile recedes together rather than turning grey. 65% is the least
   that keeps the time line at 3:1 on every colour in the light theme (half
   strength fell short; CalendarPastEventContrast.test.js).

   0.3: only a third of the colour is left, so the day ahead stands clear of
   what is over at a glance (it was 0.6, which left past and upcoming too
   close). A done task that is also past goes quieter still, at 0.25.
   ============================================================================ */

.calendar-week-event-positioned.is-past,
.calendar-day-cell-event.is-past,
.calendar-allday-pill.is-past,
.calendar-day-allday-pill.is-past,
.calendar-month-bar.is-past,
.calendar-event-badge.is-past {
    --cal-fade: 0.3;

    /* The words fade with the block: the event's own ink at 65% strength. */
    --cal-event-ink: color-mix(in srgb, var(--cal-ink, var(--text-primary)) 65%, transparent);
}

/* EVENT INK. An event's title and time are in its own colour, taken
   deep enough to read on its wash (CalendarUtils.eventInkStyle, which works
   out both themes' inks and leaves the pick to this). A finished event's
   restore rules below unset --cal-event-ink (initial) so this ink comes back
   rather than black. */
[style*='--cal-ink-l'] {
    --cal-ink: var(--cal-ink-l);
}

[data-theme='dark'] [style*='--cal-ink-d'] {
    --cal-ink: var(--cal-ink-d);
}

/* Reaching for one brings it back: a faded block is still a live control -
   click to open, drag to reschedule - and it should not read as disabled the
   moment you go to use it. Matches the agenda list and search results, which
   have restored on hover since they grew the same fade. */
.calendar-week-event-positioned.is-past:hover,
.calendar-day-cell-event.is-past:hover,
.calendar-week-event-positioned.is-past:focus-within,
.calendar-day-cell-event.is-past:focus-within {
    --cal-fade: 1;
    --cal-event-ink: initial;
}

.calendar-allday-pill.is-past:hover,
.calendar-day-allday-pill.is-past:hover,
.calendar-month-bar.is-past:hover,
.calendar-event-badge.is-past:hover,
.calendar-allday-pill.is-past:focus-visible,
.calendar-day-allday-pill.is-past:focus-visible,
.calendar-month-bar.is-past:focus-visible,
.calendar-event-badge.is-past:focus-visible {
    --cal-fade: 1;
    --cal-event-ink: initial;
}

/* A backdrop (out-of-office, a standing "lunch" block) is quiet by COLOUR -
   greyed, see .is-backdrop below - and fades like everything else only once it
   is over. It used to be dimmed to 0.72 at all times as well, which is the
   same property, and so the same look, as "this has already happened": a
   repeating away-block such as a daily lunch read as faded on every day still
   ahead of you, and the repeats stood out against one-off events as though
   repeating were what dimmed them. Now fade means past, and only past. */

/* A completed task is both done and behind you; one fade is the point, two
   would compound into a block you cannot read. .calendar-task-done wins. */
.calendar-week-event-positioned.calendar-task-done.is-past,
.calendar-day-cell-event.calendar-task-done.is-past {
    --cal-fade: 0.25;
}

/* The tick recedes with it. The timed grid fades by colour, which the tick -
   solid Kabiri blue - never read, so a finished task in the past kept one
   vivid square and looked live beside the faded meetings around it. The
   pills below fade by opacity and take their tick with them already.
   Reaching for the block brings it back, as for any past event. */
.calendar-week-event-positioned.calendar-task-done.is-past .calendar-task-check.is-done,
.calendar-day-cell-event.calendar-task-done.is-past .calendar-task-check.is-done {
    opacity: 0.5;
}

.calendar-week-event-positioned.calendar-task-done.is-past:hover .calendar-task-check.is-done,
.calendar-week-event-positioned.calendar-task-done.is-past:focus-within
    .calendar-task-check.is-done,
.calendar-day-cell-event.calendar-task-done.is-past:hover .calendar-task-check.is-done,
.calendar-day-cell-event.calendar-task-done.is-past:focus-within .calendar-task-check.is-done {
    opacity: 1;
}

/* The pills' done fade is still opacity (.calendar-task-done above), so here
   it is the past colour fade that stands down. */
.calendar-allday-pill.calendar-task-done.is-past,
.calendar-day-allday-pill.calendar-task-done.is-past,
.calendar-agenda-event.calendar-task-done.is-past,
.calendar-event-badge.calendar-task-done.is-past {
    --cal-fade: 1;
    --cal-event-ink: var(--text-primary);

    opacity: 0.5;
}

/* The whole effect is decoration. Someone who has asked for less contrast -
   or more - is not helped by a tile they can barely see, so it stands down. */
@media (prefers-contrast: more) {
    .calendar-week-event-positioned.is-past,
    .calendar-day-cell-event.is-past,
    .calendar-allday-pill.is-past,
    .calendar-day-allday-pill.is-past,
    .calendar-month-bar.is-past,
    .calendar-event-badge.is-past {
        --cal-fade: 1;
        --cal-event-ink: initial;
    }
}

/* ============================================================================
   KEYBOARD SHORTCUTS HELP (?)
   A self-contained surface mounted under <body> by ShortcutsHelp.js.
   Definition comes from the shadow (explicit hairline borders are used
   because the --glass-border / --border-light tokens are full
   "1px solid <color>" shorthands, not colours).
   ============================================================================ */
.cal-shortcuts-backdrop {
    position: fixed;
    inset: 0;
    background: rgb(15 17 23 / 35%);
    -webkit-backdrop-filter: blur(3.6px);
    backdrop-filter: blur(3.6px);
    z-index: 9999;
    animation: calCmdkFade 0.14s cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes calCmdkFade {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

/* Shortcuts help overlay */
.cal-shortcuts {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: min(378px, calc(100vw - 28.8px));
    max-height: 80vh;
    overflow-y: auto;
    background: var(--bg-primary, #fff);
    border: 0.9px solid rgb(0 0 0 / 8%);
    border-radius: 12.6px;
    box-shadow:
        0 21.6px 54px rgb(0 0 0 / 25%),
        0 5.4px 14.4px rgb(0 0 0 / 12%);
    z-index: 10000;
    animation: calCmdkIn 0.16s cubic-bezier(0.16, 1, 0.3, 1);
}

[data-theme='dark'] .cal-shortcuts {
    border-color: rgb(255 255 255 / 12%);
}

.cal-shortcuts-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12.6px 14.4px;
    border-bottom: 0.9px solid rgb(0 0 0 / 8%);
    font-size: 12.3px;
    font-weight: 700;
    color: var(--text-primary);
}

[data-theme='dark'] .cal-shortcuts-head {
    border-bottom-color: rgb(255 255 255 / 10%);
}

.cal-shortcuts-x {
    border: 0;
    background: transparent;
    color: var(--text-tertiary);
    font-size: 18.9px;
    line-height: 1;
    cursor: pointer;
    padding: 0 3.6px;
}

.cal-shortcuts-x:hover {
    color: var(--text-primary);
}

.cal-shortcuts-body {
    padding: 7.2px 14.4px 14.4px;
}

.cal-shortcuts-row {
    display: flex;
    align-items: center;
    gap: 10.8px;
    padding: 6.3px 0;
}

.cal-shortcuts-keys {
    display: flex;
    align-items: center;
    gap: 4.5px;
    flex-shrink: 0;
    min-width: 99px;
}

.cal-shortcuts-keys kbd {
    font-size: 10.4px;
    font-weight: 600;
    padding: 1.8px 6.3px;
    border: 0.9px solid rgb(0 0 0 / 12%);
    border-radius: 4.5px;
    background: var(--bg-hover, rgb(0 0 0 / 4%));
    color: var(--text-secondary);
    font-family: inherit;
}

[data-theme='dark'] .cal-shortcuts-keys kbd {
    border-color: rgb(255 255 255 / 14%);
}

.cal-shortcuts-or {
    font-size: 9.5px;
    color: var(--text-tertiary);
}

.cal-shortcuts-desc {
    font-size: 12.3px;
    color: var(--text-primary);
}

/* ============================================================================
   "JOIN" BUTTON on day/week event blocks
   Hidden until the block carries .is-joinable, which CalendarWeekView.refresh-
   JoinButtons() toggles (on the live-time tick) while a meeting with a
   conferencing link is imminent / in progress.
   ============================================================================ */
.cal-join-btn {
    display: none;
    position: absolute;
    top: 2.7px;
    right: 2.7px;
    z-index: 2;
    align-items: center;
    padding: 0.9px 7.2px;
    border: none;
    border-radius: 4.5px;
    background: #0b8043; /* meeting green */
    color: #fff;
    font-family: inherit;
    font-size: 9.9px;
    font-weight: 700;
    line-height: 1.6;
    cursor: pointer;
    box-shadow: 0 0.9px 2.7px rgb(0 0 0 / 25%);
}

.cal-join-btn:hover {
    filter: brightness(1.08);
}

.calendar-week-event-positioned.is-joinable .cal-join-btn,
.calendar-day-cell-event.is-joinable .cal-join-btn {
    display: inline-flex;
}

/* A thin green ring draws the eye to a meeting you can join right now. */
.calendar-week-event-positioned.is-joinable,
.calendar-day-cell-event.is-joinable {
    outline: 1.4px solid #0b8043;
    outline-offset: -1.4px;
}

/* ============================================================
   QUICK RSVP
   Three buttons on an unanswered invite - Yes, Maybe, No -
   revealed when you hover its block in the grid.

   Answering used to mean opening the event and finding the
   "Going?" row: three clicks and a modal for a one-word
   decision, on the single most common thing a calendar wants
   one click for. Hidden until hover (or until keyboard focus
   lands inside the block) so a screen of answered meetings
   looks exactly as it did.
   ============================================================ */
.cal-rsvp-quick {
    display: none;
    position: absolute;
    right: 2.7px;
    bottom: 2.7px;
    z-index: 3;
    gap: 0.9px;
    padding: 0.9px;
    border-radius: 5.4px;

    /* Its own surface rather than the block's fill: an unanswered
       invite renders as an OUTLINE (responseStyleString), so the
       buttons would otherwise sit on the grid showing through it. */
    background: var(--bg-elevated, #fff);
    box-shadow: 0 0.9px 3.6px rgb(0 0 0 / 22%);
}

.calendar-week-event-positioned:hover .cal-rsvp-quick,
.calendar-week-event-positioned:focus-within .cal-rsvp-quick,
.calendar-day-cell-event:hover .cal-rsvp-quick,
.calendar-day-cell-event:focus-within .cal-rsvp-quick {
    display: inline-flex;
}

.cal-rsvp-quick-btn {
    padding: 0 4.5px;
    border: none;
    border-radius: 3.6px;
    background: transparent;
    color: var(--text-secondary, #6b7280);
    font-family: inherit;
    font-size: 9.1px;
    font-weight: 700;
    line-height: 14.4px;
    cursor: pointer;
}

/* Colour on hover only, so the strip reads as one control at rest
   rather than a traffic light. The tokens are semantic because the
   colour-safe appearance mode redefines the green/red pair. */
.cal-rsvp-quick-btn:hover,
.cal-rsvp-quick-btn:focus-visible {
    color: #fff;
}

.cal-rsvp-quick-btn.is-accepted:hover,
.cal-rsvp-quick-btn.is-accepted:focus-visible {
    background: var(--accent-green, #0b8043);
}

.cal-rsvp-quick-btn.is-tentative:hover,
.cal-rsvp-quick-btn.is-tentative:focus-visible {
    background: var(--accent-amber, #b7791f);
}

.cal-rsvp-quick-btn.is-declined:hover,
.cal-rsvp-quick-btn.is-declined:focus-visible {
    background: var(--accent-red, #c5221f);
}

.cal-rsvp-quick-btn:focus-visible {
    outline: 1.8px solid var(--brand-primary, #1433d2);
    outline-offset: 0.9px;
}

/* A block squeezed by 4+ concurrent events has no width to spare;
   the renderer already leaves the strip out there, and this keeps
   it out if one ever reaches the DOM another way. Answering such an
   event goes through its detail modal, as before. */
.calendar-week-event-positioned.is-narrow .cal-rsvp-quick {
    display: none;
}

/* A block too narrow for all three answers shows none of them
   (fitQuickRsvp in utils/rsvp.js measures it on hover). Answering it
   goes through its detail modal. */
.calendar-week-event-positioned.rsvp-no-room .cal-rsvp-quick,
.calendar-day-cell-event.rsvp-no-room .cal-rsvp-quick {
    display: none;
}

/* A quarter-hour block is a few pixels of colour - there is no room for a
   strip inside it, and one overlaying it would cover the title. Those are
   answered from the detail modal, as before. */
.calendar-week-event-positioned.is-tiny .cal-rsvp-quick,
.calendar-day-cell-event.is-short .cal-rsvp-quick,
.calendar-week-event-positioned.is-tiny:hover .cal-rsvp-quick,
.calendar-day-cell-event.is-short:hover .cal-rsvp-quick {
    display: none;
}

/* ============================================================
   Reduced motion: collapse the calendar's transitions/animations
   for users who ask the OS to minimise movement. Scoped to the
   calendar surfaces this stylesheet owns.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
    .calendar-layout *,
    .calendar-layout *::before,
    .calendar-layout *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

/* A backdrop block - out-of-office - is the band the day is painted on, not a
   thing competing for attention in it. It already spans the full column and
   paints first (see partitionBackdrops); this is the other half of reading as
   a background: a greyed fill and a border that does not argue with the real
   events layered over it. Notion and Google both grey theirs for the same
   reason. Greyed, not dimmed: opacity is the grid's "already over" (see PAST
   EVENTS), so an away-block still ahead of you is at full strength. */
.calendar-week-event-positioned.is-backdrop,
.calendar-day-event.is-backdrop,
.calendar-day-cell-event.is-backdrop {
    filter: saturate(0.35);
}

.calendar-week-event-positioned.is-backdrop:hover,
.calendar-day-event.is-backdrop:hover,
.calendar-day-cell-event.is-backdrop:hover {
    /* Still reachable: it is a real event you can open, so hovering brings its
       colour back rather than leaving it permanently greyed out. */
    filter: saturate(0.6);
}

/* The Away icon before an Away block's title (CalendarUtils.awayIconHTML). */
.cal-away-icon {
    flex-shrink: 0;
    margin-right: 4.5px;
}

/* ============================================================
   4. Glass panels
   ============================================================

   The calendar is laid out like the Dashboard and the Email tab: three glass
   cards (--card-glass-*, the Dashboard widget card's own surface) on one
   sheet of graph paper - the top bar, the view (plan / agenda / day / week /
   month / year) and the sidebar. 10px under the top bar, between the cards
   and to the content panel's edges (.calendar-body's padding, and the
   sidebar's own margins). The cards themselves are styled
   where they are declared: the top bar above, the view and the sidebar in
   CalendarTab._getSidebarStyles.

   The graph paper is painted once, here on .calendar-layout, which never
   scrolls - a viewport-attached background on a scroller is repainted on
   every scroll frame - with the same tile and line token as the Email
   tab's, so the cells line up across every gap. */
.calendar-layout {
    background-color: var(--app-canvas, #f4f5f7);
    background-image:
        repeating-linear-gradient(
            0deg,
            transparent,
            transparent 20.7px,
            var(--app-grid-line) 20.7px,
            var(--app-grid-line) 21.6px
        ),
        repeating-linear-gradient(
            90deg,
            transparent,
            transparent 20.7px,
            var(--app-grid-line) 20.7px,
            var(--app-grid-line) 21.6px
        );
    background-size: 21.6px 21.6px;
    background-attachment: fixed;
}

[data-theme='dark'] .calendar-layout {
    background-color: var(--bg-primary);
}

/* Inside the view's card every view paints from the card's own surface, so
   its gutters and sticky bars read as part of the glass rather than the
   canvas grey they used to match. Opaque (the glass's flat colour), because
   the sticky bars cover what scrolls under them.

   The hour grid is the same surface as the time-zone gutter beside it, in
   either theme. The off-hours are the cell's own colour a shade darker
   (--cal-offhours-tint, mixed from --cal-surface in the day and week views):
   a few levels, so the working day reads without standing out of the grid
   the way it used to - as a pale block in dark mode, as white in the light
   day view - against a canvas-grey or near-black off-hours. Restated here
   rather than inherited: --cal-grid-surface is computed where it is
   declared. */
.calendar-body > .calendar-main {
    --cal-gutter-surface: var(--card-glass-solid);
    --cal-surface: var(--cal-gutter-surface);
    --cal-grid-surface: var(--cal-gutter-surface);

    /* The room for the sidebar joined to this card's left edge. */
    margin-left: var(--cal-sidebar-w);

    /* The sidebar runs flush into the left nav (founder decision, 4
       November 2026) and this card is joined to its right edge, with a
       border all round that draws the join. Its top-left corner is square
       where it meets the sidebar; the rest curve, the bottom-left too,
       since the sidebar is only as tall as its contents. */
    border-radius: 0 var(--radius-xl) var(--radius-xl) var(--radius-xl);
}

/* Once the sidebar reaches down to the card's bottom (navEdge.js), the
   bottom-left corner squares too: the two meet edge to edge all the way. */
.calendar-body > .calendar-main.has-sidebar-to-foot {
    border-bottom-left-radius: 0;
}

/* The view's card is the content panel's own colour, as in the neumorphic
   look: the day-and-date row, the time-zone gutters and the working hours
   all read as the panel, and the card is set off it by its border and
   bevel alone. Flat, so the card itself (under the Plan view, below the
   month grid, between the year's months) is the colour every view paints
   and no view shows a lighter patch of glass. Light takes the panel's
   canvas grey, dark its ground (--bg-primary). (The [data-theme='dark']
   .calendar-layout rule near the top of this file does not reach in here:
   these rules restate the tokens on this card.) High contrast keeps its
   own flat glass. */
:root:not([data-high-contrast]) .calendar-body > .calendar-main {
    --cal-gutter-surface: var(--app-canvas, #f4f5f7);
    --cal-surface: var(--cal-gutter-surface);
    --cal-grid-surface: var(--cal-gutter-surface);

    background: var(--cal-gutter-surface);
}

[data-theme='dark']:not([data-high-contrast]) .calendar-body > .calendar-main {
    --cal-gutter-surface: var(--bg-primary);
    --cal-surface: var(--cal-gutter-surface);
    --cal-grid-surface: var(--cal-gutter-surface);

    background: var(--cal-gutter-surface);
}

/* Pointing at a ticked calendar in the sidebar (calendarHoverPulse.js): its
   events pulse on the grid, all in step - the class lands on every one in a
   single pass, so the animations share a start frame - and everything else
   steps back, so they pop off the view. `scale` rather than `transform`, so
   it composes with any transform a block already carries. */
@keyframes cal-hover-pulse {
    0%,
    100% {
        scale: 1;
        filter: none;
    }

    50% {
        scale: 1.05;
        filter: drop-shadow(0 2.7px 7.2px rgb(0 0 0 / 22%)) brightness(1.06);
    }
}

.calendar-layout .is-cal-pulse {
    z-index: 6;
    animation: cal-hover-pulse 1.1s ease-in-out infinite;
}

.calendar-layout.has-cal-pulse :is([data-event-id], [data-meet-with-id]):not(.is-cal-pulse) {
    opacity: 0.35;
}

/* No movement for anyone who asked for less: the rest still steps back, which
   is enough to pick the calendar's events out. */
@media (prefers-reduced-motion: reduce) {
    .calendar-layout .is-cal-pulse {
        animation: none;
    }
}
