/* ============================================================
   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 + mobile breakpoints   (was CalendarResponsiveStyles)
     2. Mobile stacked view                 (was CalendarMobileStyles)
     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 to the same 0.6 instead (--cal-fade, see the PAST
       EVENTS block below), which keeps their text readable. */
    --cal-past-opacity: 0.6;

    /* 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 + mobile breakpoints
   ============================================================ */

.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);

    background: transparent;

    /* 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
       collapse handle'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 (251.4px, 15% wider than the 218.6px it was, the room coming
       out of the view beside it) plus its 10px margin to the content panel's
       edge - so the handle and the booking panel, at right: var(--cal-sidebar-w),
       meet the card's left edge. */
    --cal-sidebar-w: 261.4px;

    /* The booking panel's width, read by the panel itself and by the collapse
       handle's offset while the panel is open - declared beside the sidebar's
       for the same reason it is: two readers, one number. */
    --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 active day/week/month view on
   the LEFT and the sidebar (mini-month, scheduling, calendars) on the right,
   in that order in the markup too - the view is what you came to read, so it
   takes the edge your eye starts from and the width it needs, and the
   sidebar sits where a sidebar sits. */
.calendar-body {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;

    /* 10px under the top bar and in from the content panel's left and
       bottom edges, and 10px between the view's card and the sidebar's - see
       "4. Glass panels". The sidebar is laid over the row's right edge, out
       of its flow, and the view's card keeps the room for it as its right
       margin (the sidebar's footprint plus the gap; 10px once it is
       collapsed), so the row's right edge is the panel's edge and the
       collapse handle and the booking panel measure from it. */
    gap: 0;
    padding: 10px 0 10px 10px;
    overflow: hidden;

    /* Positioning context for the sidebar's collapse handle, which is
       absolutely placed against this row's right edge. */
    position: relative;
}

/* Collapsed: the whole right-hand panel goes and the grid takes the width.
   The card slides out past the panel's right edge over 0.3s (the transition
   is on .calendar-sidebar, in CalendarTab._getSidebarStyles) - a transform,
   so it moves on its own layer - while the view's card takes the width in
   one step (its margin, in "4. Glass panels"), so the week grid is laid out
   once rather than on every frame of the slide. visibility takes it out of
   the tab order once the slide has finished, and brings it back the moment
   it starts to open. The handle stays - it is a sibling of the panel, not a
   child, so there is always something left to bring it back with. */
.calendar-body.is-sidebar-collapsed .calendar-sidebar {
    transform: translateX(calc(100% + 10px));
    visibility: hidden;
}

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

/* The collapse handle: a tab, not a puck.

   Its RIGHT edge is flat and butts against whatever edge it belongs to - the
   sidebar's left edge while the sidebar is open, the content panel's own
   right edge once it is closed - so it reads as attached to that edge and
   pulled out from it, rather than floating over the grid. Rounded on the
   left, square and border-less on the right, because the edge it meets draws
   that line already.

   It moves by transform between the two states, on the panel's own curve,
   so the tab slides across with the panel's edge - both on their own
   layers, starting in the same frame. */
.calendar-sidebar-toggle {
    position: absolute;
    right: var(--cal-sidebar-w);

    /* 14.4px off the cards' bottom edge, which sits 10px off the row's. */
    bottom: 24.4px;

    /* Above the week view's current-time indicator, which sits at 27 in the
       buffered strip (CalendarWeekView.indicatorZ) - at 25 the red now-line
       and its dot drew straight across the tab whenever the clock reached
       that height. Still under the sticky header row (30), which the tab sits
       far below and must never cover. */
    z-index: 28;
    display: flex;
    align-items: center;
    justify-content: center;

    /* 42px - half again on the 28 it was, which was itself a widening of the
       18 the tab first shipped at. The height carries the tab's identity, so
       widening costs nothing: it still reads as a tab pulled out from the
       edge, with more of it to aim at.

       None of that width comes off the grid. The tab is absolutely positioned
       against .calendar-body, so it is out of flow entirely and overhangs the
       view rather than making the grid give up space for it - widening it
       moves nothing else on screen. */
    width: 37.8px;
    height: 46.8px;
    padding: 0;
    border: 0.9px solid var(--card-glass-border-color);
    border-right: none;
    border-radius: 7.2px 0 0 7.2px;

    /* The sidebar card's glass, so the tab reads as pulled out of it. */
    background: var(--card-glass-bg);
    color: var(--text-tertiary);
    cursor: pointer;

    /* Cast to the LEFT: the tab overhangs the grid on that side, and a
       centred shadow would bleed out from under the flat edge it is
       supposed to be flush against. */
    box-shadow: -1.8px 0 7.2px rgb(0 0 0 / 8%);

    /* On the sidebar's 0.3s curve, so the tab rides the card's edge as it
       slides rather than arriving ahead of it. */
    transition:
        transform 0.3s cubic-bezier(0.4, 0, 0.2, 1),
        color 0.15s ease,
        border-color 0.15s ease,
        background-color 0.15s ease;
}

/* The sidebar is only as tall as its contents, so a tab pinned to the foot
   of the row would hang below a short card. Where anchor positioning is
   supported the tab sits 14.4px above the card's own bottom edge instead -
   which is the row's foot whenever the card fills it. It keeps showing when
   the card is hidden (collapsed): the default position-visibility would hide
   it with its anchor. */
@supports (anchor-name: --cal-sidebar) {
    .calendar-sidebar {
        anchor-name: --cal-sidebar;
    }

    .calendar-sidebar-toggle {
        position-anchor: --cal-sidebar;
        position-visibility: always;
        top: calc(anchor(--cal-sidebar bottom) - 46.8px - 14.4px);
        bottom: auto;
    }
}

@media (prefers-reduced-motion: reduce) {
    .calendar-sidebar-toggle {
        transition: none;
    }
}

.calendar-sidebar-toggle:hover {
    color: var(--brand-primary);
    border-color: var(--brand-primary);
    background: var(--bg-hover, #f3f4f6);
}

.calendar-sidebar-toggle:focus-visible {
    outline: 1.8px solid var(--brand-primary);
    outline-offset: 1.8px;
}

/* The chevron points the way the sidebar will go: right to push it away,
   left to bring it back. The glyph itself points right, so the OPEN state is
   the unrotated one. Targeted by class, not as a bare `svg` descendant: this
   sheet carries plenty of later `... svg` rules, and a high-specificity
   element selector this early in the file trips no-descending-specificity
   against every one of them. */
.calendar-sidebar-toggle-chevron {
    /* Up from 12px with the tab's widening - the glyph was sized for a 28px
       tab and read small once it grew. */
    width: 13.5px;
    height: 13.5px;
    transform: rotate(0deg);
    transition: transform 0.24s ease;
}

.calendar-body.is-sidebar-collapsed .calendar-sidebar-toggle-chevron {
    transform: rotate(180deg);
}

[data-theme='dark'] .calendar-sidebar-toggle {
    box-shadow: -1.8px 0 7.2px rgb(0 0 0 / 30%);
}

/* Collapsed state last: it outranks every base rule above, and ordering it
   the other way round trips no-descending-specificity. Closed, there is
   nothing to the right of the grid, so the tab sits on the content panel's
   own right edge: moved the panel's whole footprint across. */
.calendar-body.is-sidebar-collapsed .calendar-sidebar-toggle {
    transform: translateX(var(--cal-sidebar-w));
}

/* The booking panel: a column that OVERLAYS the grid, pinned to the sidebar's
   left 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 right edge
   meets the sidebar's left edge with no gap, it wears the sidebar's colour,
   and it is square and border-less on that side - the same drawer shape the
   collapse handle above has - 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%;
    right: 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-right: none;
    border-radius: 10.8px 0 0 10.8px;

    /* Cast LEFT 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 right 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;
}

/* Collapsed, there is no sidebar to dock against, so the panel keeps to the
   content panel's own right edge. */
.calendar-body.is-sidebar-collapsed .cal-booking-panel {
    right: 0;
}

/* The collapse handle stays on the sidebar's left edge whether or not the
   panel is open: the panel floats over the grid now rather than taking width
   out of it, so there is no edge for the handle to follow out. It sits below
   the panel's bottom edge (the panel clears the bottom tenth of the row) and
   under it in the stack, which is why the panel's z-index is above the
   handle's 28. */

/* 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;
}

/* The stacked mobile view replaces the sidebar entirely, so there is nothing
   for the handle to collapse. */
@media (width <= 768px) {
    .calendar-sidebar-toggle {
        display: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .calendar-sidebar-toggle,
    .calendar-sidebar-toggle-chevron,
    .cal-booking-panel {
        transition: none;
    }
}

.calendar-mobile-sidebar-toggle {
    display: none;
    position: fixed;
    bottom: 18px;
    left: 18px;
    z-index: 1000;
    width: 43.2px;
    height: 43.2px;
    border-radius: 50%;
    background: linear-gradient(135deg, rgb(212 175 55 / 85%), rgb(79 70 229 / 90%));
    backdrop-filter: blur(21.6px);
    color: white;
    border: 0.9px solid rgb(255 255 255 / 20%);
    cursor: pointer;
    box-shadow:
        0 1.8px 7.2px rgb(212 175 55 / 25%),
        0 5.4px 18px rgb(212 175 55 / 20%),
        inset 0 0.9px 0 rgb(255 255 255 / 20%);
    align-items: center;
    justify-content: center;
    transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}

.calendar-mobile-sidebar-toggle:active {
    transform: scale(0.93);
}

.calendar-mobile-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgb(0 0 0 / 50%);
    z-index: 998;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
}

.calendar-mobile-overlay.visible {
    opacity: 1;
    pointer-events: auto;
}

/* Mobile stacked view - hidden on desktop */
.calendar-mobile-stacked {
    display: none;
}

@media (width <= 768px) {
    .calendar-layout {
        padding: 0;
        gap: 0;
        flex-direction: column;
        height: auto;
        min-height: calc(100vh - 90px);
    }

    /* Hide desktop elements on mobile */
    .calendar-mobile-sidebar-toggle,
    .calendar-mobile-overlay,
    .calendar-week-header,
    .calendar-body,
    .calendar-sidebar,
    .calendar-main {
        display: none !important;
    }

    /* Show mobile stacked view */
    .calendar-mobile-stacked {
        display: flex;
        flex-direction: column;
        width: 100%;
        padding: 10.8px;

        /* Clear the fixed create-event FAB (plus the device safe-area) so the
           last section isn't hidden underneath it. */
        padding-bottom: calc(86.4px + env(safe-area-inset-bottom, 0px));
        gap: 14.4px;
        overflow-y: auto;
    }

    /* Settings takes over the stacked view (see CalendarShellView). The panel
       scrolls its own content pane and draws its own padding, so the stacked
       view's page padding and section gap would only inset a full-bleed
       surface and add a second scroller. The create-event FAB renders inside
       the stacked view, so it is simply absent here - no rule needed, and
       nothing to clear at the bottom. */
    .calendar-mobile-stacked--settings {
        padding: 0;
        gap: 0;
        overflow: hidden;
        min-height: calc(100vh - 144px);
    }

    /* The booking panel on a phone: the same markup as the docked column,
       but the whole stacked view (CalendarShellView renders it in the
       settings wrapper above), so the desktop overlay rules stand down - it
       is back in flow, full width, full height, with nothing to float over. */
    .calendar-mobile-stacked--settings > .cal-booking-panel {
        position: static;
        flex: 1 1 auto;
        width: 100%;
        height: auto;
        opacity: 1;
        visibility: visible;
        pointer-events: auto;
        border: 0;
        border-radius: 0;
        box-shadow: none;
    }

    .calendar-mobile-section {
        background: rgb(255 255 255 / 72%);
        backdrop-filter: blur(21.6px);
        border-radius: 14.4px;
        border: 0.9px solid rgb(255 255 255 / 45%);
        box-shadow: 0 1.8px 14.4px rgb(0 0 0 / 6%);
        overflow: hidden;
    }

    [data-theme='dark'] .calendar-mobile-section {
        background: rgb(30 30 30 / 65%);
        border-color: rgb(255 255 255 / 8%);
        box-shadow: 0 1.8px 14.4px rgb(0 0 0 / 25%);
    }

    .calendar-mobile-week-section {
        display: flex;
        flex-direction: column;
    }

    .calendar-mobile-section-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 9px 12.6px;
        font-size: 13.2px;
        font-weight: 600;
        color: var(--text-primary);
        border-bottom: 0.9px solid rgb(0 0 0 / 4%);
        letter-spacing: -0.01em;
    }

    [data-theme='dark'] .calendar-mobile-section-header {
        border-bottom-color: rgb(255 255 255 / 4%);
    }

    /* Compact month view for mobile stacked */
    .calendar-mobile-section .calendar-month-view {
        padding: 10.8px;
    }

    /* Compact week view for mobile stacked */
    .calendar-mobile-week-section .calendar-week-view {
        max-height: 270px;
        overflow-y: auto;
    }
}

@media (width <= 480px) {
    .calendar-mobile-stacked {
        padding: 7.2px;
        gap: 10.8px;
    }
}

/* ============================================================
   2b. Mobile stacked view
   ============================================================ */

/* Navigation Row: Arrows + Date + View Toggle */
.calendar-mobile-nav-row {
    display: flex;
    align-items: center;
    gap: 7.2px;
    padding: 7.2px 0;
}

.calendar-mobile-nav-btn {
    width: 32.4px;
    height: 32.4px;
    border-radius: 9px;
    background: rgb(255 255 255 / 72%);
    backdrop-filter: blur(10.8px);
    border: 0.9px solid rgb(255 255 255 / 45%);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-secondary);
    transition: all 0.18s cubic-bezier(0.4, 0, 0.2, 1);
    flex-shrink: 0;
    box-shadow: 0 0.9px 1.8px rgb(0 0 0 / 4%);
}

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

.calendar-mobile-nav-btn:active {
    background: rgb(212 175 55 / 6%);
    color: var(--brand-primary);
    transform: scale(0.93);
}

.calendar-mobile-view-title {
    font-size: 15.1px;
    font-weight: 600;
    color: var(--text-primary);
    min-width: 54px;
    text-align: center;
}

.calendar-mobile-view-toggle {
    display: flex;
    background: rgb(0 0 0 / 4%);
    border: 0.9px solid rgb(0 0 0 / 4%);
    border-radius: 9px;
    padding: 1.8px;
    gap: 1.8px;
    margin-left: auto;
}

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

.calendar-mobile-view-btn {
    padding: 5.4px 10.8px;
    border: none;
    background: transparent;
    border-radius: 7.2px;
    font-size: 11.3px;
    font-weight: 500;
    color: var(--text-secondary);
    cursor: pointer;
    transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
    font-family: inherit;
}

.calendar-mobile-view-btn:active {
    transform: scale(0.96);
}

.calendar-mobile-view-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-mobile-view-btn.active {
    background: rgb(255 255 255 / 12%);
}

.calendar-mobile-view-btn:not(.active):hover {
    color: var(--text-primary);
}

/* Toolbar Row: Search + Action Icons */
.calendar-mobile-toolbar {
    display: flex;
    align-items: center;
    gap: 7.2px;
    padding: 7.2px 0;
    border-bottom: 0.9px solid rgb(0 0 0 / 4%);
    margin-bottom: 7.2px;
}

[data-theme='dark'] .calendar-mobile-toolbar {
    border-bottom-color: rgb(255 255 255 / 4%);
}

.calendar-mobile-search-wrapper {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 7.2px;
    background: rgb(255 255 255 / 72%);
    backdrop-filter: blur(10.8px);
    border: 0.9px solid rgb(255 255 255 / 45%);
    border-radius: 9px;
    padding: 7.2px 10.8px;
    transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}

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

.calendar-mobile-search-wrapper:focus-within {
    border-color: rgba(var(--brand-primary-rgb), 0.4);
    box-shadow: 0 0 0 2.7px rgba(var(--brand-primary-rgb), 0.1);
}

.calendar-mobile-search-wrapper svg {
    color: var(--text-tertiary);
    flex-shrink: 0;
}

.calendar-mobile-search-input {
    flex: 1;
    border: none;
    background: none;
    font-size: 13.2px;
    color: var(--text-primary);
    outline: none;
    font-family: inherit;
    min-width: 0;
}

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

.calendar-mobile-toolbar-actions {
    display: flex;
    align-items: center;
    gap: 7.2px;
}

/* 36px drawn, 44px to the finger (N10): the pseudo-element carries the hit
   area 4px past each edge, and the 8px gap above keeps neighbours' areas
   from overlapping. */
.calendar-mobile-toolbar-btn {
    position: relative;
    width: 32.4px;
    height: 32.4px;
    border-radius: 9px;
    background: rgb(255 255 255 / 72%);
    backdrop-filter: blur(10.8px);
    border: 0.9px solid rgb(255 255 255 / 45%);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-secondary);
    transition: all 0.18s cubic-bezier(0.4, 0, 0.2, 1);
    flex-shrink: 0;
    box-shadow: 0 0.9px 1.8px rgb(0 0 0 / 4%);
}

.calendar-mobile-toolbar-btn::before {
    content: '';
    position: absolute;
    inset: -3.6px;
}

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

.calendar-mobile-toolbar-btn:active {
    background: rgb(212 175 55 / 6%);
    color: var(--brand-primary);
    transform: scale(0.93);
}

.calendar-mobile-today-link {
    padding: 5.4px 12.6px;
    background: rgb(255 255 255 / 72%);
    backdrop-filter: blur(10.8px);
    border: 0.9px solid rgb(255 255 255 / 45%);
    border-radius: 7.2px;
    font-size: 11.3px;
    font-weight: 500;
    color: var(--text-secondary);
    cursor: pointer;
    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-mobile-today-link {
    background: rgb(30 30 30 / 65%);
    border-color: rgb(255 255 255 / 8%);
}

.calendar-mobile-today-link:active {
    background: rgb(212 175 55 / 6%);
    color: var(--brand-primary);
    transform: scale(0.96);
}

.calendar-mobile-month-label {
    font-size: 12.3px;
    font-weight: 600;
    color: var(--text-primary);
}

.calendar-mobile-filter-row {
    display: flex;
    align-items: center;
    gap: 7.2px;
}

.calendar-mobile-view-container {
    min-height: 270px;
}

.calendar-mobile-view-container .calendar-week-view,
.calendar-mobile-view-container .calendar-month-view,
.calendar-mobile-view-container .calendar-day-view {
    max-height: 360px;
    overflow-y: auto;
}

/* Hide redundant day view date header on mobile - date already shown in nav row */
.calendar-mobile-view-container .calendar-day-view > div > div:first-child {
    display: 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. On desktop the
       right edge is padded clear of the app's top-right cut-out bay (see the
       @media block 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 (53px, or
       the cut-out's own height on desktop) 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;

    /* Compact week-header chrome - kept slim to match the Email tab's top bar
       as it renders for the user. An earlier change bumped this to 52px to
       chase the --email-header-height variable and line the gear up with the
       email gear, but that made the calendar bar visibly taller than the
       email one, so it's back to the slim height. Desktop takes the cut-out's
       height instead (see the @media block below) - that is what the email
       bar actually measures there, and a literal leaves this one short. */
    height: 47.7px;
    min-height: 47.7px;
    max-height: 47.7px;

    /* A glass strip (--card-glass-*, the Dashboard widget card's surface),
       like the Email tab's bar: 10px in from the content panel's left edge,
       flush with its top and right (the right end runs under the app's
       top-right cut-out), rounded on the left only. 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: 10px;
    border-left: 0.9px solid var(--card-glass-border-color);
    border-bottom-color: var(--card-glass-border-color);
    border-radius: var(--radius-xl) 0 0 var(--radius-xl);
    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;

    /* 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;
}

/* Desktop: 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. */
@media (width >= 769px) {
    .calendar-week-header {
        /* 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;
    }
}

.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 the way it does on mobile. 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;

    /* A step off the view switcher that follows it, so the date reads as its
       own group rather than as a prefix to the switcher's label. The 48px
       that used to hold it clear of the search magnifier went with the move:
       there is no left cluster beside it any more. */
    margin-right: 5.4px;

    /* 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 stands a clear step off the label it acts on - wider than the
   step between the two arrows, so they group with each other rather than
   with the date. Keyed off whichever label comes last: the week number is
   opt-in, and without it the arrows follow the title. */
.calendar-week-header-title + .calendar-week-nav-btn,
.calendar-week-header-subtitle + .calendar-week-nav-btn {
    margin-left: 14.4px;
}

/* Today sits in the right cluster, directly after the view switcher, and is
   drawn as that 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;
    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. */
    min-width: var(--tab-primary-action-w, 88.2px);
    border-radius: calc(var(--radius-xl) - 0.9px) 0 0 calc(var(--radius-xl) - 0.9px);
    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;
}

/* Header search: a bare magnifier in the LEFT cluster, after Create.
   Pressing it opens the search field in its place - the same pill the Email
   and Files tabs carry (.calendar-header-search-bar below) - and the rest of
   the bar stays up. Clicking out before submitting collapses back to the
   icon; Enter opens the results view (CalendarSearchResultsView).

   Icon only: the magnifier says search on its own. Squared to 30px, quiet and
   transparent at rest, it matches the settings gear at the far end of the bar
   rather than Create - the bar's icon-button treatment. title / aria-label
   carry the name for screen readers and on hover. */
.calendar-week-search-btn {
    flex-shrink: 0;
    box-sizing: border-box;
    width: var(--tab-topbar-icon-box, 31.1px);
    height: var(--tab-topbar-icon-box, 31.1px);
    padding: 0;
    border-radius: 8.1px;
    border: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: var(--text-secondary);
    background: transparent;
    transition: all 0.18s cubic-bezier(0.4, 0, 0.2, 1);
}

/* 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-search-btn svg,
.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);
}

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

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

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

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

/* 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;
}

/* ============================================================
   Mobile drawer (Phase 3a)
   ============================================================ */

/* Backdrop sits below the drawer, above all calendar surfaces. Hidden by
   default; .open fades it in. Tap-to-dismiss is on the element itself. */
.kabiri-mobile-drawer-backdrop {
    position: fixed;
    inset: 0;
    background: rgb(0 0 0 / 50%);
    z-index: 1100;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s ease;
    display: none;
}

.kabiri-mobile-drawer {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: min(324px, 90vw);
    max-width: 100vw;
    z-index: 1101;
    background: var(--bg-primary);
    box-shadow: -7.2px 0 28.8px rgb(0 0 0 / 18%);
    transform: translateX(100%);
    transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1);
    display: flex;
    flex-direction: column;
    outline: none;
}

.kabiri-mobile-drawer.open {
    transform: translateX(0);
}

.kabiri-mobile-drawer-backdrop.open {
    display: block;
    opacity: 1;
    pointer-events: auto;
}

/* The drawer is a mobile-only surface. Hide on desktop so a stray .open
   from cross-tab navigation never leaks across breakpoints. */
@media (width > 768px) {
    .kabiri-mobile-drawer,
    .kabiri-mobile-drawer-backdrop {
        display: none !important;
    }
}

.kabiri-mobile-drawer-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12.6px 16.2px;
    border-bottom: var(--border-light);
    flex-shrink: 0;
}

.kabiri-mobile-drawer-title {
    font-size: 14.2px;
    font-weight: 700;
    color: var(--text-primary);
}

.kabiri-mobile-drawer-close {
    width: 32.4px;
    height: 32.4px;
    border-radius: 7.2px;
    background: transparent;
    border: 0.9px solid transparent;
    cursor: pointer;
    color: var(--text-secondary);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s;
}

.kabiri-mobile-drawer-close:active {
    background: rgb(0 0 0 / 6%);
}

.kabiri-mobile-drawer-body {
    flex: 1;
    overflow-y: auto;
    padding: 12.6px 16.2px 21.6px;
    -webkit-overflow-scrolling: touch;
}

.kabiri-mobile-drawer-section {
    margin-bottom: 18px;
}

.kabiri-mobile-drawer-section-title {
    font-size: 10.4px;
    font-weight: 600;
    color: var(--text-tertiary);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 9px;
}

.kabiri-mobile-drawer-segmented {
    display: flex;
    gap: 5.4px;
    background: var(--bg-secondary);
    border-radius: 7.2px;
    padding: 3.6px;
}

.kabiri-mobile-drawer-segmented-btn {
    flex: 1;
    padding: 7.2px 10.8px;
    background: transparent;
    border: none;
    border-radius: 5.4px;
    font-size: 12.3px;
    font-weight: 500;
    cursor: pointer;
    color: var(--text-secondary);
    transition: all 0.18s;
    font-family: inherit;
}

.kabiri-mobile-drawer-segmented-btn.active {
    background: var(--brand-gradient);
    color: white;
}

.kabiri-mobile-drawer-option {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 9px 0;
}

.kabiri-mobile-drawer-option-label {
    font-size: 13.2px;
    color: var(--text-primary);
}

.kabiri-mobile-drawer-tz-list {
    max-height: 50vh;
    overflow-y: auto;
    border-radius: 9px;
    border: var(--border-light);
    background: var(--bg-secondary);
    -webkit-overflow-scrolling: touch;
}

.kabiri-mobile-drawer-tz-region {
    position: sticky;
    top: 0;
    z-index: 1;
    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);
}

.kabiri-mobile-drawer-tz-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: 9px 10.8px;
    background: transparent;
    border: none;
    cursor: pointer;
    text-align: left;
    font-family: inherit;
    color: var(--text-primary);
    font-size: 12.3px;
    border-bottom: var(--border-light);
}

.kabiri-mobile-drawer-tz-item:last-child {
    border-bottom: none;
}

.kabiri-mobile-drawer-tz-item.active {
    background: rgba(var(--brand-primary-rgb), 0.08);
    color: var(--brand-primary);
    font-weight: 600;
}

.kabiri-mobile-drawer-tz-offset {
    font-size: 10.4px;
    color: var(--text-tertiary);
    flex-shrink: 0;
    margin-left: 10.8px;
}

/* 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-dropdown {
    position: absolute;
    top: 100%;
    right: 0;
    margin-top: 3.6px;

    /* Opaque surface so the settings float legibly over the week grid
       (matches the timezone and booking-links dropdowns). */
    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: 252px;
    padding: 10.8px;
}

[data-theme='dark'] .calendar-settings-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-settings-section {
    margin-bottom: 14.4px;
}

.calendar-settings-section:last-child {
    margin-bottom: 0;
}

.calendar-settings-title {
    font-size: 10.4px;
    font-weight: 600;
    color: var(--text-tertiary);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 9px;
}

.calendar-settings-option {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 7.2px 0;
}

.calendar-settings-option-label {
    font-size: 12.3px;
    color: var(--text-primary);
}

.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);
}

.calendar-settings-time-row {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 7.2px 0;
}

.calendar-settings-time-label {
    font-size: 12.3px;
    color: var(--text-primary);
    min-width: 54px;
}

.calendar-settings-time-select {
    flex: 1;
    padding: 5.4px 9px;
    background: rgb(255 255 255 / 72%);
    backdrop-filter: blur(10.8px);
    border: 0.9px solid rgb(255 255 255 / 45%);
    border-radius: 7.2px;
    font-size: 11.3px;
    color: var(--text-primary);
    cursor: pointer;
    font-family: inherit;
    transition: all 0.18s cubic-bezier(0.4, 0, 0.2, 1);
}

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

.calendar-settings-time-select:focus {
    outline: none;
    border-color: rgba(var(--brand-primary-rgb), 0.5);
    box-shadow: 0 0 0 2.7px rgba(var(--brand-primary-rgb), 0.1);
}

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

/* 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);
}

@media (width <= 768px) {
    .calendar-week-header {
        padding: 5.4px 7.2px;
        flex-wrap: wrap;
        gap: 5.4px;

        /* Mobile lets the action row wrap onto a second line, so
           relax the desktop's fixed 52px header height. */
        height: auto;
        min-height: 46.8px;
        max-height: none;
    }

    .calendar-week-header-title {
        font-size: 12.3px;
    }

    .calendar-week-header-subtitle {
        font-size: 9.5px;
    }

    .calendar-timezone-dropdown {
        min-width: 252px;
        right: -45px;
    }
}

@media (width <= 480px) {
    .calendar-week-header-title {
        font-size: 11.3px;
    }

    .calendar-timezone-dropdown {
        min-width: 234px;
        right: -72px;
    }
}

/* ============================================================
   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;
}

/* 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, spine and text through
   CalendarUtils.solidWash / spine / 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 too, three quarters of the way from --text-primary to
   --text-secondary (25 / 75), so a finished event's text reads as behind you
   at a glance - as far as it can go and still clear 3:1. Not all the way: the tile's time line already sits at
   0.75-0.8 opacity over that ink, and a past event's title and time still
   have to clear 3:1 on the darkest wash (Tomato, Grape, Kabiri blue) with
   that line on top. CalendarPastEventContrast.test.js works the sums for
   every palette colour in both themes. --text-secondary itself measured
   3.4-4.0:1 on the faded light-theme washes, and 2.5:1 for the time line.

   0.6, against .calendar-task-done's 0.5: a done task is finished WORK and
   can go quiet, while a meeting that happened an hour ago is still something
   you look back at to remember what was said. Enough to sort the day at a
   glance, not enough to make you lean in.
   ============================================================================ */

.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.6;
    --cal-event-ink: color-mix(in srgb, var(--text-primary) 25%, var(--text-secondary));
}

/* 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: var(--text-primary);
}

.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: var(--text-primary);
}

/* 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.5;
}

/* 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: var(--text-primary);
    }
}

/* ============================================================================
   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,
    .kabiri-mobile-drawer *,
    .calendar-mobile-stacked * {
        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);
}

/* ============================================================
   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. Desktop only: a phone's
   stacked view has none of these cards to lay on it. */
@media (width >= 769px) {
    .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 laid over the row's right edge: its footprint
       and the 10px between the two cards. Collapsed, just the panel edge's
       10px - in one step, not animated (see .calendar-body). */
    margin-right: calc(var(--cal-sidebar-w) + 10px);
}

.calendar-body.is-sidebar-collapsed > .calendar-main {
    margin-right: 10px;
}

/* Dark: the view's card sits back - darker than the sidebar's glass, and
   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. Still a clear step (+7 levels) above the
   graph paper behind it (--bg-primary), so it reads as a card, not a hole;
   the border and the bevel stay. (The [data-theme='dark'] .calendar-layout
   rule near the top of this file does not reach in here: the rule above
   restates the tokens on this card.) High contrast keeps its own flat
   glass. */
[data-theme='dark']:not([data-high-contrast]) .calendar-body > .calendar-main {
    --cal-gutter-surface: color-mix(in srgb, var(--bg-primary) 97%, #fff);
    --cal-surface: var(--cal-gutter-surface);
    --cal-grid-surface: var(--cal-gutter-surface);

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

/* The settings card takes the whole row over, so it takes the right edge's
   10px itself. (A collapsed sidebar keeps its own right margin, so the
   view's card needs none.) */
.calendar-body > .calendar-settings-panel {
    margin-right: 10px;
}

/* Settings take the top bar's place too (CalendarShellView leaves the bar
   out while they are open): the card is 10px in from the content panel's
   top, left and right, and steps around the app's top-right cut-out - the
   shared cut-out notch
   (CutoutNotchStyles), laid over the card's top-right corner from the body
   and painted with this layout's graph paper. The panel itself is the
   shared settings shell in its flush form (settings-shell--flush in
   SettingsPanelStyles), whose header is exactly as tall as the step - the
   same panel as the Email tab's settings. */
.calendar-body.calendar-body--settings {
    --cutout-notch-canvas: var(--app-canvas, #f4f5f7);
}

[data-theme='dark'] .calendar-body.calendar-body--settings {
    --cutout-notch-canvas: var(--bg-primary);
}
